Skip to content

Add cached GitHub notification inbox with reusable popover and menu bar access #44

Description

@Tranthanh98

Problem and intended behavior

Users should be able to view GitHub notifications for their connected GitHub accounts directly in Commit+, without waiting for background refresh or opening GitHub for every check. Opening the inbox should display locally cached notifications immediately.

UI scope

Build one reusable notification popover, backed by shared application state, and expose it through:

  • A bell beside the repository name in the main window header.
  • A bell beside the account control on the Welcome screen when signed in.
  • A macOS menu bar status item whose click opens the same notification content.

The menu bar item means an icon in the macOS system menu bar, not an entry in the app's menu commands. It is available while Commit+ is running; launching at login or fetching after the app exits is outside this issue.

The popover includes:

  • Account dropdown with avatar, username, host, and an “All accounts” option. Remember the last selection; identify the receiving account on each row in the combined view.
  • Notification title, repository, reason/type, updated time, and unread state.
  • Manual Refresh button with loading feedback, fetching the selected account or all accounts in the combined view.
  • Load more: show 20 rows initially and expand from the cache up to 50 per account.
  • A bottom “View more on GitHub” action opening https://github.com/notifications. In the combined view, ask/select which account to open. The browser's signed-in account may differ from the account selected in Commit+; do not imply automatic account switching.
  • Open on GitHub, Mark as read, and Done actions; read/done changes sync to GitHub after a successful API operation.
  • Clear empty, offline/cached, missing-account, authorization, and fetch-error states. If signed into Commit+ without a connected GitHub account, show a Connect GitHub action.

Cache and refresh

  • Persist the latest 50 notifications per connected GitHub account in the existing SQLite persistence architecture.
  • Key cache records by host + stable GitHub user ID + notification thread ID. Keep account caches isolated and remove the matching cache on disconnect.
  • Store notification display data, unread state, update timestamps, last successful refresh, and conditional-request metadata. Tokens remain in the existing local Keychain vault.
  • Load SQLite immediately on opening the popover, then refresh in the background when stale. A fresh cache should avoid an unnecessary fetch on every open.
  • Use one shared polling coordinator across all three presentation surfaces to avoid duplicate requests. Background polling target is once per minute while the app is running and eligible to refresh; respect GitHub X-Poll-Interval if it requires a longer interval.
  • Manual Refresh requests the latest data promptly, while respecting rate limits, server backoff, and any required polling restrictions. Prevent overlapping requests and preserve cached data on failure.
  • Use Last-Modified / If-Modified-Since and handle 304 without clearing the cache. Handle pagination sufficiently to maintain the latest 50 per account.
  • Unread badges represent unread notifications within the cached subset, not a guaranteed total for the entire GitHub inbox. Load more does not increase the persistence cap.

GitHub API feasibility gate

The current native GitHub connection uses OAuth App device flow with repo, read:user, and workflow scopes. Verify GET /notifications using an existing connected OAuth account before implementation assumptions are finalized. GitHub documentation currently describes notifications/repo scopes and OAuth notification scopes, but also says Notifications endpoints support only classic PATs; OAuth compatibility must be verified rather than assumed. GitHub App tokens and fine-grained PATs are explicitly unsupported for these endpoints. Accounts connected only through SSH also need a compatible API credential.

If the existing token cannot access notifications, surface a clear unsupported/reauthorization state and determine the smallest compatible authentication change. Do not silently replace existing account credentials or add Firebase token storage. The initial design uses direct native GitHub API calls and requires no Firebase backend changes.

References:

Acceptance criteria

  • All three bells/status item open the same reusable popover and reflect shared notification state.
  • Switching accounts never displays another account's private cached notifications under the wrong identity.
  • Reopening displays cached rows immediately; background refresh runs once per coordinator at the permitted interval.
  • Manual Refresh updates rows, cache, and badges without duplicate concurrent requests.
  • SQLite retains at most 50 latest notifications per account; initial display is 20, Load more expands locally, and the bottom GitHub action opens the full inbox.
  • Read/Done actions correctly sync to GitHub and all open surfaces; failed operations remain recoverable.
  • Offline, no-account, revoked/unsupported-token, 304, rate-limit/backoff, and disconnect cases are handled.
  • Build the macOS app successfully; do not automatically relaunch it for validation.

Clarified defaults

  • The inbox covers each selected account across repositories; the main-window bell does not implicitly filter to the current repository.
  • “Load more” expands the cached list; “View more on GitHub” opens the full inbox.
  • The menu bar feature works while Commit+ runs. Native macOS notification banners and operation after app exit are deferred.
  • Default account selection restores the user's previous choice; first use selects the first available connected GitHub account.

Activity

  1. Tranthanh98 commented on Oct 7, 2026

    @Tranthanh98
    CollaboratorAuthor

    resolved in #45

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions