Commit Graph

8 Commits

Author SHA1 Message Date
tigerenwork be384c9238 feat: 增强推送可靠性:指数退避重连、校准服务与飞书按人过滤查询 2026-07-10 01:59:05 +08:00
tigerenwork 64a35752c5 fix: use rawValue for customer field to handle all Feishu field types 2026-06-29 21:03:27 +08:00
tigerenwork 0ce557ac8e feat: add customer field to Bug model with configurable mapping
- 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>
2026-06-29 20:50:46 +08:00
tigerenwork 723c50fc9d feat: configurable status mappings, scrollable settings, case-insensitive assignee
- 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>
2026-06-29 00:51:03 +08:00
tigerenwork 0f8565f65d fix: OAuth token endpoint wraps in {code,message,data} — not flat
The /authen/v1/oidc/access_token response uses the standard Feishu envelope
with 'message' (not 'msg') field. Updated FeishuAPIResponse to handle both
'msg' and 'message' via custom init(from:). exchangeCode and
refreshAccessToken now decode via FeishuAPIResponse<OAuthTokenData>.

Tenant token endpoint (/auth/v3/tenant_access_token/internal) returns flat
response — TenantAccessTokenData decoded directly.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-29 00:33:53 +08:00
tigerenwork ae918a379c fix: remove redundant CodingKeys conflicting with .convertFromSnakeCase
JSONDecoder.keyDecodingStrategy = .convertFromSnakeCase converts JSON keys
like 'tenant_access_token' to Swift names like 'tenantAccessToken'. Having
explicit CodingKeys that map to the ORIGINAL snake_case keys (e.g.,
case tenantAccessToken = "tenant_access_token") causes a collision:
the decoder first converts the JSON key, then looks for a CodingKey
matching the original name — but the converted name doesn't match.

Removed redundant CodingKeys from OAuthTokenData, TenantAccessTokenData,
UserInfoData, and RecordItem. .convertFromSnakeCase handles all these
mappings automatically.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-29 00:30:51 +08:00
tigerenwork f1ef89ef55 fix: tenant_access_token response is flat, not wrapped in data key
The /auth/v3/tenant_access_token/internal endpoint, like the OAuth token
endpoints, returns code, msg, tenant_access_token, and expire at the top
level of the JSON response — NOT nested under a 'data' key.

FeishuAPIResponse<TenantAccessTokenData> decoded successfully but with
data=nil (extra fields silently ignored by JSONDecoder). The guard then
threw FeishuError.apiError(code: 0, message: 'ok') — appearing to succeed
but always failing. This blocked the subsequent OAuth token exchange call.

- Added code/msg fields to TenantAccessTokenData
- tenantAccessToken() now decodes TenantAccessTokenData directly and
  checks data.code != 0 instead of going through FeishuAPIResponse

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-29 00:28:39 +08:00
tigerenwork d9d8ce3e46 feat: full macOS menu bar app implementation
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>
2026-06-28 20:56:44 +08:00