cross server notifications

This commit is contained in:
Ian Gulliver
2026-10-19 09:06:08 -07:00
parent dec87b3dc3
commit eb7e0a13c4
3 changed files with 57 additions and 19 deletions
+52 -18
View File
@@ -458,28 +458,62 @@ struct ServerWindow: View {
struct ServerPicker: View {
var body: some View {
let servers = Servers.shared
Menu {
HStack(spacing: 4) {
ForEach(servers.origins, id: \.self) { origin in
Button(serverName(origin)) {
servers.current = origin
}
ServerChip(origin: origin)
}
Divider()
Button("Add Server…") {
Button("+") {
servers.current = nil
}
} label: {
HStack(spacing: 6) {
if let current = servers.current {
Circle()
.fill(servers.color(current))
.frame(width: 8, height: 8)
Text(serverName(current))
} else {
Text("Add Server")
}
}
.font(Fonts.font(13))
.buttonStyle(.plain)
.foregroundStyle(servers.current == nil ? Palette.text : Palette.muted)
.padding(.horizontal, 8)
.padding(.vertical, 3)
.help("Add Server")
}
.font(Fonts.font(13))
}
}
private struct ServerChip: View {
let origin: String
@ViewState private var hover = false
var body: some View {
let servers = Servers.shared
let store = servers.connections[origin]?.store
let questions = store?.inbox.count ?? 0
let summaries = store?.unreadSummaries ?? 0
let current = servers.current == origin
Button {
servers.current = origin
} label: {
HStack(spacing: 6) {
Circle()
.fill(store == nil ? .clear : servers.color(origin))
.stroke(servers.color(origin))
.frame(width: 8, height: 8)
Text(serverName(origin))
.fontWeight(current || questions > 0 ? .bold : .regular)
if questions > 0 {
Badge(count: questions)
.help("open questions")
}
if summaries > 0 {
Text("\(summaries) new")
.font(Fonts.font(11, weight: 700))
.foregroundStyle(Palette.accent)
.help("Turn summaries you haven't read")
}
}
.foregroundStyle(hover || current ? Palette.text : questions > 0 ? Palette.warn : Palette.muted)
.padding(.horizontal, 8)
.padding(.vertical, 3)
.background(questions > 0 ? Palette.warnTint : current ? Palette.surface : .clear, in: RoundedRectangle(cornerRadius: 6))
.contentShape(Rectangle())
}
.buttonStyle(.plain)
.help(store == nil ? "\(serverName(origin)): not connected" : serverName(origin))
.onHover { hover = $0 }
}
}
+4
View File
@@ -482,6 +482,10 @@ final class Store {
task.workflow == nil && task.summarySeq > (summaryReads[task.id] ?? 0)
}
var unreadSummaries: Int {
tasks.values.joined().filter { $0.status == .active && unreadSummary($0) }.count
}
private func noteSummaryRead(_ taskId: String, _ seq: Int64) -> Bool {
if (summaryReads[taskId] ?? 0) >= seq {
return false