Add desktop import connectors to Apps page#6364
Conversation
Greptile SummaryAdds an Imports section to the desktop Apps page wiring six connector cards (Calendar, Gmail, Local Files, Apple Notes, ChatGPT, Claude) to existing import services with stateful Connected/Update actions and branded icons. All findings are P2 style items that do not affect the primary import flows. Confidence Score: 5/5Safe to merge — all findings are P2 style items with no impact on import correctness or user data Three P2 findings (locale-sensitive number parsing, dead switch block, un-annotated static cache) are style improvements only; no P0 or P1 defects found in the new import connector flows AppsPage.swift (importedMemoriesCount locale safety) and ConnectorBrandIcon.swift (static cache annotation) Important Files Changed
Sequence DiagramsequenceDiagram
participant U as User
participant AP as AppsPage
participant SS as ImportConnectorStatusStore
participant SH as ImportConnectorSheet
participant SVC as Import Service
participant API as APIClient
U->>AP: Opens Apps page
AP->>SS: snapshot(for: connector)
SS-->>AP: Snapshot(isConnected, actionTitle, metricText)
U->>AP: Taps connector card
AP->>SH: Present ImportConnectorSheet
U->>SH: Taps primary action button
SH->>SVC: importCalendar() / importGmail() / importAppleNotes() / importMemoryLog()
SVC->>API: createMemory(content:tags:source:)
API-->>SVC: Memory saved
SVC-->>SH: (memories, profileSummary)
SH->>SS: markImported(connectorID:memories:)
SS->>SS: Persist count to UserDefaults
SH-->>U: Show status message
|
| private func importedMemoriesCount(from statusMessage: String?) -> Int? { | ||
| guard let statusMessage else { return nil } | ||
| let values = statusMessage | ||
| .split(whereSeparator: { !$0.isNumber }) | ||
| .compactMap { Int($0) } | ||
| return values.last |
There was a problem hiding this comment.
Locale-sensitive number parsing
Int.formatted() respects the device locale — on locales with a non-ASCII thousands separator (French "1 234", German "1.234"), split(whereSeparator: { !$0.isNumber }) fragments the number and .last returns the trailing segment rather than the full value. A status string of "saved 1.234 memories" would persist 234 to UserDefaults instead of 1234, causing connector cards to display the wrong imported-memory count.
| private func importedMemoriesCount(from statusMessage: String?) -> Int? { | |
| guard let statusMessage else { return nil } | |
| let values = statusMessage | |
| .split(whereSeparator: { !$0.isNumber }) | |
| .compactMap { Int($0) } | |
| return values.last | |
| private func importedMemoriesCount(from statusMessage: String?) -> Int? { | |
| guard let statusMessage else { return nil } | |
| // Avoid locale-formatted separators splitting "1,234" into ["1", "234"]. | |
| // The memory count is the last all-digit token in every status message. | |
| let tokens = statusMessage.components(separatedBy: .whitespaces) | |
| return tokens.last(where: { $0.allSatisfy(\.isNumber) }).flatMap { Int($0) } | |
| } |
| } catch let error as AppleNotesReaderError { | ||
| switch error { | ||
| case .storeNotFound, .storeUnavailable: | ||
| break | ||
| } | ||
| let granted = await selectAppleNotesFolder() |
There was a problem hiding this comment.
Both arms of this exhaustive switch just break, so execution always falls through to selectAppleNotesFolder() regardless of which AppleNotesReaderError was thrown. The block adds no runtime effect and could mislead anyone who adds a new case to AppleNotesReaderError expecting per-case differentiation here.
| } catch let error as AppleNotesReaderError { | |
| switch error { | |
| case .storeNotFound, .storeUnavailable: | |
| break | |
| } | |
| let granted = await selectAppleNotesFolder() | |
| } catch let error as AppleNotesReaderError { | |
| let granted = await selectAppleNotesFolder() |
## Summary\n- add an Imports section to the desktop Apps page for Calendar, Email, Local files, Apple Notes, ChatGPT, and Claude\n- wire connector cards to working import flows with stateful Connected/Update actions and branded icons\n- add Apple Notes folder fallback and keep Create App/Category controls visually neutral\n\n## Testing\n- cd desktop/Desktop && swift test --filter OnboardingFlowTests\n- cd desktop && ./run.sh --yolo
Summary\n- add an Imports section to the desktop Apps page for Calendar, Email, Local files, Apple Notes, ChatGPT, and Claude\n- wire connector cards to working import flows with stateful Connected/Update actions and branded icons\n- add Apple Notes folder fallback and keep Create App/Category controls visually neutral\n\n## Testing\n- cd desktop/Desktop && swift test --filter OnboardingFlowTests\n- cd desktop && ./run.sh --yolo