mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-08-21 14:34:32 +00:00
The release's new capabilities were unevenly surfaced: the Spend punchcard existed only on the web dashboard, and the menubar decoded nothing of the PR-attribution block the payload already carries. - Desktop app: new Punchcard component (hour-of-day x weekday spend matrix, ported from the dash and restyled to the app's tokens) on the Spend page. Fed by a dedicated getTimeline bridge channel that fetches the payload WITH history.timeline; every other fetch keeps the lean --no-timeline path, and the serve child makes the extra fetch cheap. Hides gracefully when the payload has no timeline (older CLI). - Menubar: PullRequestsSection renders the top three PRs by attributed spend under the Workflow strip; MenubarPayload now decodes the pullRequests block (decodeIfPresent, so older payloads are unchanged). Hidden when absent or empty. Deliberately NOT ported: codex Tok/s (reads rollout files per session - too heavy for payload cadence; stays a TUI/report analytics view) and the punchcard in the menubar (a 7x24 matrix has no legible place in a compact popover). App suite 468 green (bridge channel pinned, mocks extended), swift build + 156 tests green, CLI suite green.
36 lines
1.5 KiB
Swift
36 lines
1.5 KiB
Swift
import SwiftUI
|
|
|
|
/// Compact top-pull-requests strip: the menubar's slice of the PR attribution
|
|
/// the desktop app shows in full. Renders the top three PRs by attributed
|
|
/// spend for the selected period; hides entirely when the payload carries no
|
|
/// PR block (older CLI, provider-scoped payload, or nothing attributed).
|
|
struct PullRequestsSection: View {
|
|
@Environment(AppStore.self) private var store
|
|
|
|
var body: some View {
|
|
let rows = Array((store.payload.current.pullRequests?.rows ?? []).prefix(3))
|
|
if !rows.isEmpty {
|
|
VStack(spacing: 0) {
|
|
Divider().opacity(0.5)
|
|
VStack(alignment: .leading, spacing: 6) {
|
|
SectionCaption(text: "Pull requests")
|
|
ForEach(rows, id: \.url) { row in
|
|
HStack(spacing: 8) {
|
|
Text(row.label)
|
|
.font(.system(size: 11.5, design: .monospaced))
|
|
.lineLimit(1)
|
|
.truncationMode(.middle)
|
|
Spacer(minLength: 8)
|
|
Text(row.cost.asCurrency())
|
|
.font(.system(size: 11.5, weight: .medium))
|
|
.monospacedDigit()
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
}
|
|
.padding(.horizontal, 14)
|
|
.padding(.vertical, 11)
|
|
}
|
|
}
|
|
}
|
|
}
|