Sessions Integration Feature
Nucleic-Session: FC94353F-9F0D-4BCC-AD7C-0FB14E38C2E5 Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -1188,6 +1188,60 @@ extension Data {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension DashboardSnapshot {
|
||||||
|
/// Merge every connected Mac's dashboard into one aggregate projection (mesh P3), so Home,
|
||||||
|
/// Projects, and To-Dos show all your Macs together: projects and to-dos concatenated, activity
|
||||||
|
/// summed per day, counts summed (active-days recomputed from the merged activity), subscription
|
||||||
|
/// usage taken from the first Mac that reports it (a user's Macs share one account, so their
|
||||||
|
/// windows match — summing would double-count), and provider status feeds unioned by provider
|
||||||
|
/// (provider status is global, not per-Mac).
|
||||||
|
static func merged(_ snapshots: some Collection<DashboardSnapshot>) -> DashboardSnapshot {
|
||||||
|
let snaps = Array(snapshots)
|
||||||
|
guard snaps.count != 1 else { return snaps[0] }
|
||||||
|
guard !snaps.isEmpty else { return .empty }
|
||||||
|
|
||||||
|
let projects = snaps.flatMap(\.projects)
|
||||||
|
let todos = snaps.flatMap(\.todos)
|
||||||
|
|
||||||
|
// Activity summed per start-of-day.
|
||||||
|
var byDay: [Date: (count: Int, tokens: Int)] = [:]
|
||||||
|
for snap in snaps {
|
||||||
|
for day in snap.activity {
|
||||||
|
let key = Calendar.current.startOfDay(for: day.day)
|
||||||
|
var entry = byDay[key] ?? (0, 0)
|
||||||
|
entry.count += day.count
|
||||||
|
entry.tokens += day.tokens
|
||||||
|
byDay[key] = entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let activity = byDay
|
||||||
|
.map { ActivityDay(day: $0.key, count: $0.value.count, tokens: $0.value.tokens) }
|
||||||
|
.sorted { $0.day < $1.day }
|
||||||
|
|
||||||
|
let counts = DashboardCounts(
|
||||||
|
projects: projects.count,
|
||||||
|
chats: snaps.reduce(0) { $0 + $1.counts.chats },
|
||||||
|
activeChats: snaps.reduce(0) { $0 + $1.counts.activeChats },
|
||||||
|
messages: snaps.reduce(0) { $0 + $1.counts.messages },
|
||||||
|
activeDays: activity.filter { $0.count > 0 || $0.tokens > 0 }.count,
|
||||||
|
tokens: snaps.reduce(0) { $0 + $1.counts.tokens })
|
||||||
|
|
||||||
|
let usage = snaps.compactMap(\.usage).first
|
||||||
|
|
||||||
|
var seenProviders = Set<String>()
|
||||||
|
var statusFeeds: [WireStatusFeed] = []
|
||||||
|
for snap in snaps {
|
||||||
|
for feed in snap.statusFeeds where seenProviders.insert(feed.provider).inserted {
|
||||||
|
statusFeeds.append(feed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DashboardSnapshot(
|
||||||
|
counts: counts, activity: activity, projects: projects,
|
||||||
|
todos: todos, usage: usage, statusFeeds: statusFeeds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension WireSessionSummary {
|
extension WireSessionSummary {
|
||||||
/// A copy with selected fields overridden — the demo simulator's only way to "mutate" a
|
/// A copy with selected fields overridden — the demo simulator's only way to "mutate" a
|
||||||
/// summary, whose stored properties are all `let`. Nullable fields use a double optional so a
|
/// summary, whose stored properties are all `let`. Nullable fields use a double optional so a
|
||||||
|
|||||||
Reference in New Issue
Block a user