first commit: project README, high-level design and detailed implementation docs
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
a9c90f64b9
|
|
@ -0,0 +1,14 @@
|
|||
# Bugger for macOS
|
||||
|
||||
A lightweight macOS menu bar app that surfaces bugs assigned to you from a [Feishu Bitable](https://www.feishu.cn/). Shows a badge in the menu bar, a popover with your active bugs, and native notifications when bugs are assigned or changed.
|
||||
|
||||
Inspired by the Windows Bugger tool.
|
||||
|
||||
## Status
|
||||
|
||||
Early design phase. See [docs/](docs/) for the high-level design and detailed implementation plan.
|
||||
|
||||
## Docs
|
||||
|
||||
- [High-Level Design](docs/HIGH_LEVEL_DESIGN.md)
|
||||
- [Detailed Design & Implementation](docs/DETAILED_DESIGN.md)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,147 @@
|
|||
# Bugger for macOS — High-Level Design
|
||||
|
||||
## Overview
|
||||
|
||||
**Bugger** is a lightweight macOS menu bar application that surfaces bugs assigned to
|
||||
you from a Feishu Bitable. It mirrors the experience of the Windows Bugger tool:
|
||||
a glanceable badge in the menu bar, a popover with your active bugs, native
|
||||
notifications when bugs are assigned or changed, and an optional floating widget.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ User's Mac │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌──────────────┐ │
|
||||
│ │ Menu Bar │ │ Floating │ │
|
||||
│ │ Icon+Badge │ │ Widget │ │
|
||||
│ │ [🐛 3] │ │ (optional) │ │
|
||||
│ └──────┬──────┘ └──────┬───────┘ │
|
||||
│ │ │ │
|
||||
│ ┌──────┴──────────────────┴───────┐ │
|
||||
│ │ BugStore │ │
|
||||
│ │ (ObservableObject) │ │
|
||||
│ │ - bugs: [Bug] │ │
|
||||
│ │ - unseenCount: Int │ │
|
||||
│ │ - lastUpdated: Date │ │
|
||||
│ └──────┬──────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────┴──────────┐ ┌─────────────┐ │
|
||||
│ │ PollerService │───▶│ FeishuService│ │
|
||||
│ │ (Timer, 5min) │ │ │ │
|
||||
│ └─────────────────┘ └──────┬──────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────┐ ┌────────┴───────┐ │
|
||||
│ │ Notification │ │ TokenManager │ │
|
||||
│ │ Service │ │ (Keychain) │ │
|
||||
│ └──────────────┘ └────────────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ HTTPS (OAuth Bearer)
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Feishu Cloud │
|
||||
│ ┌──────────────┐ ┌──────────────────┐ │
|
||||
│ │ OAuth │ │ Bitable API │ │
|
||||
│ │ /authen/v1/ │ │ /bitable/v1/ │ │
|
||||
│ │ oidc/ │ │ apps/{token}/ │ │
|
||||
│ │ access_token│ │ tables/{id}/ │ │
|
||||
│ └──────────────┘ │ records │ │
|
||||
│ └──────────────────┘ │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
### 1. Native SwiftUI (not cross-platform)
|
||||
The app targets macOS exclusively. SwiftUI + AppKit bridging gives the best
|
||||
integration with macOS idioms — `MenuBarExtra`, `NSPanel` floating windows,
|
||||
Keychain, and `UserNotifications` — while keeping the binary under 10 MB.
|
||||
|
||||
### 2. Poll-based sync, not push
|
||||
Feishu webhooks require a public-facing HTTP endpoint. For a personal tool,
|
||||
polling the Bitable API every N minutes is simpler, safer, and sufficient.
|
||||
Default interval: 5 minutes.
|
||||
|
||||
### 3. OAuth user_access_token with refresh
|
||||
Uses Feishu's OAuth 2.0 authorization code flow to get a `user_access_token`
|
||||
(valid 2h) and `refresh_token` (valid 30 days). Tokens are stored in the macOS
|
||||
Keychain. The app acts on behalf of the user — no admin approval needed.
|
||||
|
||||
### 4. No backend server
|
||||
Everything runs locally. No database, no server, no cloud hosting. The app
|
||||
stores only:
|
||||
- OAuth tokens (Keychain)
|
||||
- Configuration (UserDefaults: table ID, polling interval, etc.)
|
||||
- Cached bug state (in-memory, rebuilt on launch)
|
||||
|
||||
### 5. Menu bar first, floating widget second
|
||||
The menu bar popover is the primary interaction surface. The floating widget is
|
||||
an optional companion — a small always-on-top window showing the count, which
|
||||
clicks through to open the menu bar popover.
|
||||
|
||||
## Component Map
|
||||
|
||||
| Component | Responsibility |
|
||||
|---|---|
|
||||
| `App` | `@main` entry, sets activation policy to `.accessory` (no dock icon) |
|
||||
| `AppDelegate` | Menu bar icon registration, window management |
|
||||
| `BugStore` | Central observable state: bug list, unseen count, loading/error |
|
||||
| `FeishuService` | HTTP client for Feishu Open API (bitable records, OAuth) |
|
||||
| `TokenManager` | OAuth flow orchestration, Keychain read/write, token refresh |
|
||||
| `PollerService` | Configurable timer driving the fetch cycle |
|
||||
| `NotificationService` | Diff engine + `UNUserNotificationCenter` push |
|
||||
| `MenuBarView` | Menu bar icon with badge count |
|
||||
| `BugListPopover` | Popover containing the scrollable bug list |
|
||||
| `BugRow` | Single bug: title, priority pill, age, clickable |
|
||||
| `FloatingWidget` | Optional `NSPanel`-based always-on-top overlay |
|
||||
| `SettingsWindow` | Preferences: table config, poll interval, widget toggle |
|
||||
| `KeychainHelper` | Thin wrapper around Security framework |
|
||||
|
||||
## Data Flow
|
||||
|
||||
```
|
||||
1. App Launch
|
||||
├── Load tokens from Keychain
|
||||
├── If no token → show OAuth setup window
|
||||
├── If token expired → refresh via refresh_token
|
||||
└── Start PollerService
|
||||
|
||||
2. Poll Cycle (every 5 min, configurable)
|
||||
├── FeishuService.fetchRecords(table_id, filter=assignee=me)
|
||||
├── Parse response → [Bug]
|
||||
├── BugStore.diff(old, new)
|
||||
│ ├── New bugs → NotificationService.fire()
|
||||
│ ├── Status changes → NotificationService.fire()
|
||||
│ └── Assignee changes → NotificationService.fire()
|
||||
└── BugStore.bugs = new; BugStore.lastUpdated = now
|
||||
|
||||
3. User Interaction
|
||||
├── Click menu bar icon → toggle popover
|
||||
├── Click bug in popover → open in Feishu (browser / Feishu app URL)
|
||||
├── "Mark all seen" → reset badge count
|
||||
└── Floating widget click → open menu bar popover
|
||||
```
|
||||
|
||||
## Feishu API Surface
|
||||
|
||||
| API | Method | Purpose |
|
||||
|---|---|---|
|
||||
| `/authen/v1/oidc/access_token` | POST | Exchange authorization code for user_access_token |
|
||||
| `/authen/v1/refresh_access_token` | POST | Refresh expired user_access_token |
|
||||
| `/bitable/v1/apps/{app_token}/tables/{table_id}/records` | GET | Fetch bug records with filter |
|
||||
|
||||
All calls use `Authorization: Bearer <user_access_token>` and go to
|
||||
`https://open.feishu.cn`.
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
- **Memory**: < 80 MB at steady state
|
||||
- **CPU**: idle < 0.1%, spike < 2% during poll
|
||||
- **Binary**: < 15 MB
|
||||
- **Startup**: < 2 seconds to menu bar icon visible
|
||||
- **Offline**: graceful degradation (show stale data, retry on next interval)
|
||||
- **macOS**: 14.0+ (Sonoma) — `MenuBarExtra` is stable from 13.3, but 14.0 is a
|
||||
reasonable floor for 2024+
|
||||
Loading…
Reference in New Issue