- Daily schedule mode now shows macOS-native hour:minute DatePickers
instead of a comma-separated text field
- Each time entry has its own picker with a remove button
- '+ Add time' button to add more entries
- Minimum 1 entry enforced (remove disabled when only 1 left)
- No hardcoded defaults — starts empty, user picks their times
Co-Authored-By: Claude <noreply@anthropic.com>
- Added 8-hour and 12-hour polling interval options
- Added 'Daily schedule' mode (pollIntervalSeconds = -1): fires at
specific wall-clock times configured in dailyRefreshTimes (e.g. 08:00, 14:00)
- PollerService: in daily mode, checks every 60s and triggers fetch when
current time matches a scheduled time (with 2-min dedup window)
- Settings UI: shows HH:mm text field when daily schedule is selected
- AppConfig: added dailyRefreshTimes: [String] field
Co-Authored-By: Claude <noreply@anthropic.com>
- Bug model: added optional 'customer' property
- FieldMappings: added 'customerField' (default: 客户名称)
- BugMapper: reads customer value from configured column
- BugRow: displays customer in blue when present
- Settings: Customer field text field in Field Mappings section
Co-Authored-By: Claude <noreply@anthropic.com>
- Popover footer now has a Quit button (power icon) to terminate the app
- Polling interval picker now includes 1h, 2h, 4h, and 1 day options
Co-Authored-By: Claude <noreply@anthropic.com>
- Added FieldMappings.statusMappings: [FeishuValue: BugStatus] dict
mapping Feishu select-option text to standard Bugger statuses.
Pre-populated with common Chinese/English values:
开发进行中→inProgress, 验收完毕→resolved, Bug Triage→open, etc.
- BugMapper.mapStatus() looks up Feishu value in the mapping,
falling back to .unknown (shown as active bug).
- Settings: status mapping section with one TextField per status
showing comma-separated Feishu values. Editable and saved to config.
- Settings: wrapped Form in ScrollView, removed fixed height,
use minHeight/maxHeight — no more truncated buttons.
- Assignee matching now uses case-insensitive contains instead of
exact match, handling display name variations from Feishu API.
Co-Authored-By: Claude <noreply@anthropic.com>
- SettingsWindow: widened to 500pt min, connection result on its own line
with multiline support (error messages no longer truncated)
- OAuthSetupView: clear statusMessage on error, added 'Try again' button
when authorization fails, disable Connect button while in progress
- TokenManager: guard against empty refresh token strings (was stored as ''
when Feishu didn't return refresh_token, causing confusing 'No Feishu
session' error after access token expired)
Co-Authored-By: Claude <noreply@anthropic.com>
SwiftUI macOS menu bar app for tracking Feishu Bitable bugs:
- Menu bar icon with active bug count badge
- Popover with bug list sorted by priority, click to open in Feishu
- Floating always-on-top widget (NSPanel, optional)
- OAuth 2.0 flow with Feishu Open API (user_access_token + refresh)
- PollerService with configurable interval (default 5 min)
- Diff engine detecting new bugs, status/priority/assignee changes
- Native macOS notifications (UserNotifications framework)
- Keychain-backed token storage
- Settings window with field mapping, polling interval, widget toggle
- Support for custom Bitable column name mappings
- Zero third-party dependencies
17 source files across Models/Services/Views/ViewModels/Utils layers.
Xcode project generated via scripts/generate_xcode_project.py.
Co-Authored-By: Claude <noreply@anthropic.com>