Gmail notifier run on macOS menu bar.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
WanCW 4ed2fb1f38
Add roadmap of unimplemented features and improvements
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:13:51 +08:00
Config Add Google OAuth sign-in with PKCE and Keychain tokens 2026-10-16 15:13:46 +08:00
docs Add roadmap of unimplemented features and improvements 2026-10-16 15:13:51 +08:00
Magpie Fix label picker keyboard focus and add keyboard tests 2026-10-16 15:13:50 +08:00
Magpie.xcodeproj Add Google OAuth sign-in with PKCE and Keychain tokens 2026-10-16 15:13:46 +08:00
MagpieTests Fix label picker keyboard focus and add keyboard tests 2026-10-16 15:13:50 +08:00
.gitignore Add Google OAuth sign-in with PKCE and Keychain tokens 2026-10-16 15:13:46 +08:00
AGENTS.md Fix label picker keyboard focus and add keyboard tests 2026-10-16 15:13:50 +08:00
README.md Add roadmap of unimplemented features and improvements 2026-10-16 15:13:51 +08:00

Magpie

macOS 選單列 App:監看多個 Gmail 帳號未讀數,以指定瀏覽器開啟 Gmail。

  • Swift 6、SwiftUI + AppKit、macOS 14+,無外部相依
  • Google OAuth 2.0(PKCE + loopback),token 存 Keychain
  • Gmail API:labels.list 探索標籤、labels.get 取未讀數,只需 gmail.labels scope

設定

Google Cloud 與 client ID 設定見 docs/google-oauth-setup.md。 尚未實作與改進項目見 docs/roadmap.md。 未設定 client ID 時以示範模式執行(假帳號、不保存)。

結構

Config/        xcconfig、Info.plist(OAuth client ID 注入)
Magpie/
  App/         進入點、AppEnvironment(composition root / DI)
  Models/      Account、GmailLabel、LabelCatalog、AccountStatus、UnreadCount、Browser、OAuthToken
  Services/    外部相依的 protocol 與實作(Keychain、UserDefaults、檔案、NSWorkspace、Gmail HTTP)
    OAuth/     GoogleOAuthManager、PKCE、LoopbackRedirectServer、IDToken
    Mock/      MockGmailAPIClient、MockOAuthManager、SampleData
  Domain/      AccountManager、LabelManager(actor)、LabelIndex、GmailRequestExecutor、RefreshScheduler(actor)
  ViewModels/  MenuBarViewModel、SettingsViewModel、LabelPickerModel
  Views/       MenuBar/、Settings/、Shared/
MagpieTests/   Swift Testing 單元測試與替身

資料流:View → ViewModel → AccountManager → OAuthManager / GmailAPIClient / SettingsStore / LabelCatalogStore。

標籤與未讀數

  • 標籤以 Gmail label ID 識別;名稱只是快取,改名後同步更新,不影響監看。
  • 探索(labels.list,無分頁)與輪詢(labels.get)分開:
    • 探索:新增帳號、設定中尚無清單、使用者按重新整理、清單超過 1 小時或上次失敗時。結果存 Application Support JSON。
    • 輪詢:只請求收件匣 + 監看標籤(500 個標籤監看 5 個 → 每輪 6 個請求)。預設每 5 分鐘;資料仍新時略過。
  • 收件匣一律監看。選單列總數只加總各帳號收件匣,不加監看標籤,避免重複計算。預設以會話(threadsUnread)計。
  • 清單中找不到的監看標籤標示「無法使用」並停止輪詢;只在成功取得完整清單後判定,同名新標籤不會被誤認。
  • 每帳號最多 4 個並行請求;同帳號刷新不重疊。5xx/429/限流 403/網路錯誤以指數退避 + jitter 重試(最多 3 次,遵守 Retry-After);401 先更新 token 重試一次。失敗時保留上次數字並標示過時。
  • 系統睡眠時暫停排程,喚醒、回到前景或開啟選單時補刷新過時資料。

建置與測試

xcodebuild -project Magpie.xcodeproj -scheme Magpie -destination 'platform=macOS' test

Xcode 專案使用資料夾同步群組,新增檔案不需改 project.pbxproj。