Skip to content

Show overall build status with a labeled icon in the menu bar - #23

Open
sour4bhdex wants to merge 9 commits into
anuj-delta:masterfrom
sour4bhdex:feat/menu-bar-status-label
Open

Show overall build status with a labeled icon in the menu bar#23
sour4bhdex wants to merge 9 commits into
anuj-delta:masterfrom
sour4bhdex:feat/menu-bar-status-label

Conversation

@sour4bhdex

@sour4bhdex sour4bhdex commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

The menu bar shows a short status label beside its icon. Pending approval takes priority, followed by running, failing, passing, and unknown. The running state animates. The cached status updates after each poll and clears when an integration disconnects.

The branch includes current master. Sign-out and token-change cleanup use the new repository-card regrouping method and retain the cached-status reset. Existing abandoned feature branches outside the visible, recent set do not keep the overall status failing.

Validation on 06dcfcfd31ac068b381bb8b778828fc0900867ef: swift test passes all 155 tests. SKIP_INSTALL=1 ./build-app.sh builds and signs the release bundle without replacing the installed app. The isolated app process starts, but the computer-use service times out when inspecting this menu-bar-only app, so a visible menu-bar interaction remains unverified.

The configured greploop skill has no reviewer route for anuj-delta; no bot review is claimed.

@greptile-apps

greptile-apps Bot commented Jul 20, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a labeled icon to the menu bar (e.g. 2 failing, building, 3 waiting) and replaces the per-frame status recomputation with a poller-updated cache (menuBarCounts/menuBarStatus) to avoid parsing ISO-8601 timestamps at 60 fps. The showDeployLoader preference is removed in favour of always animating while any build or deploy is running.

  • Introduces StatusCounts and OverallStatus.menuBarTint to drive the new icon+label rendering in MenuBarLabel, with the cache read at render time instead of recomputing on each animation frame.
  • Adds refreshDeploySpinner() calls to signOut(), changeToken(), and disconnectVercel() so the cached menu-bar state and spinner timer are reset when data is cleared — addressing the previously-flagged stale-cache gap.
  • Replaces per-call ISO8601DateFormatter construction with two lazily-created static formatters, removing the allocation hot-path concern.

Confidence Score: 5/5

Safe to merge — all meaningful logic paths are exercised by the new test suite and the previously-flagged stale-cache issue is resolved.

The status-counting and cache-refresh logic is well-contained in StatusCounts and refreshDeploySpinner. The three code paths that could leave the menu bar showing stale state (signOut, changeToken, disconnectVercel) now all call refreshDeploySpinner after clearing data. The 60 fps timer is correctly stopped when no builds are running. The test suite covers the full priority ladder (pendingApproval > running > failing > passing > unknown), key-branch exemptions, the recency window, the visibility cap, and the cache-reset-on-clear path — leaving no obvious untested gap.

No files require special attention.

Important Files Changed

Filename Overview
BuildNotifier/State/AppState.swift Adds StatusCounts, menuBarCounts/menuBarStatus cache, 60fps phase-derived spinner timer, and refreshDeploySpinner calls on sign-out/disconnect. Previously-flagged stale-cache bug is addressed.
BuildNotifier/BuildNotifierApp.swift MenuBarLabel now reads cached menuBarStatus/menuBarCounts instead of recomputing; MenuBarSpinnerGlyph removed; AppDelegate receives AppState at init time for eager launch fetch.
BuildNotifier/Models/Build.swift parseISO8601 converted from per-call formatter construction to two shared static formatters, removing the allocation hot-path.
BuildNotifier/Models/WatchedProject.swift Removes showDeployLoader field, default value, and migration read; deployLoaderStyle picker is now always enabled.
BuildNotifier/Views/Settings/SettingsView.swift Removes the 'Show deploy loader' toggle and its disabled state on the style picker; subtitle copy updated.
Tests/BuildNotifierTests/StatusCountsTests.swift New test suite covering CircleCI branch counting, Vercel deployment counting, recency/visibility filtering, pending approval precedence, and cache reset — all key paths exercised.

Sequence Diagram

sequenceDiagram
    participant AL as AppDelegate.applicationDidFinishLaunching
    participant AS as AppState
    participant P as Pollers (Build/Vercel/AutoApproval)
    participant MBL as MenuBarLabel (60 fps render)

    AL->>AS: "Task { await appState.initialize() }"
    AS->>P: startPolling()
    loop Each poll cycle
        P->>AS: update buildsByProject / deploymentsByProject / pendingApprovals
        P->>AS: refreshDeploySpinner()
        AS->>AS: "menuBarCounts = statusCounts (parse ISO8601 here)"
        AS->>AS: "menuBarStatus = overallStatus(pendingApprovals)"
        alt "menuBarStatus == .running"
            AS->>AS: start 60 fps Timer (deploySpinnerPhase)
        else
            AS->>AS: stop Timer, reset phase to 0
        end
    end

    loop Each frame (up to 60 fps, only while running)
        AS->>AS: "Timer fires → deploySpinnerPhase = elapsed/period % 1"
        AS-->>MBL: "@Observable notifies change"
        MBL->>MBL: read menuBarStatus (cached)
        MBL->>MBL: read menuBarCounts (cached)
        MBL->>MBL: render iconView + labelText (no ISO8601 parsing)
    end

    note over AS,MBL: sign-out / changeToken / disconnectVercel also call refreshDeploySpinner() to clear stale cache + stop timer
Loading

Reviews (9): Last reviewed commit: "Reset cached menu bar status on sign-out..." | Re-trigger Greptile

Comment thread BuildNotifier/BuildNotifierApp.swift Outdated
Comment thread Tests/BuildNotifierTests/StatusCountsTests.swift
@sour4bhdex

Copy link
Copy Markdown
Contributor Author

@greptile review

@sour4bhdex
sour4bhdex force-pushed the feat/menu-bar-status-label branch from 551aa31 to c90fc2f Compare August 14, 2026 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant