feat: surface provider and model on each generated card#326
Open
M3NT1 wants to merge 2 commits into
Open
Conversation
The toast that warns the user about missing screen-recording access was gated on 'getSavedPreference() == true || appState.isRecording', but the recorder forces isRecording off the moment it detects the permission is missing, and getSavedPreference() is nil for users who have never explicitly toggled it. Net effect: the notice never surfaced for the exact case it was meant to alert on, and the user had no UI signal that recording was broken (the Resume button appeared to do nothing). Switch the guard to the 'didOnboard' UserDefaults flag so the notice appears whenever the user has completed onboarding and the permission is missing. Also re-evaluate the notice on every tab change to .timeline so a user who lands on the timeline after dismissing elsewhere still sees it (the session-dismiss flag prevents spam).
Cards in the timeline now carry a small 'Provider · Model' badge so the user can see at a glance which model produced them. Older cards saved before this change render without the badge (no placeholder), because the new fields are optional in the JSON metadata column — no DB migration required. Three places show the badge: - Canvas timeline card (CanvasActivityCard) — a small text line below the time range - Right-side detail card (MainView/ActivityCard) — a chip next to the category badge with a sparkles icon - Review-mode swipe card (TimelineReviewCard) — a chip next to the category pill A new 'TimelineActivity.providerBadge' computed property centralises the provider-id → human-label mapping (e.g. 'gemini' → 'Gemini', 'chatgpt_claude' → 'Claude' or 'ChatGPT' based on the model name), and looks up the model alias through ClaudeModel / CodexModel enums so 'sonnet' displays as 'Claude Sonnet' rather than the raw alias. Storage: TimelineCard, TimelineCardShell, TimelineActivity, and the TimelineMetadata JSON envelope gained optional 'providerId' and 'modelId' fields. LLMService stamps these onto every card it writes, using 'activeContext.id.providerLabel' for the provider and a new 'providerModelId(for:)' helper for the model.
This was referenced Jul 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cards in the timeline now carry a small 'Provider · Model' badge so the user can see at a glance which model produced them. Three places show it:
MainView/ActivityCard) — a chip next to the category badge with a sparkles iconTimelineReviewCard) — a chip next to the category pillA new
TimelineActivity.providerBadgecomputed property centralises the provider-id → human-label mapping (e.g.'gemini'→'Gemini','chatgpt_claude'→'Claude'or'ChatGPT'based on the model name), so the timeline list, detail panel, and review mode can never disagree.Older cards saved before this change render without the badge (no placeholder), because the new fields are optional in the JSON metadata column — no DB migration required.
Files changed
Dayflow/Core/Recording/StorageModels.swift— new optionalproviderIdandmodelIdfields onTimelineCard,TimelineCardShell,TimelineActivity, andTimelineMetadataDayflow/Core/Recording/StorageManager+TimelineCards.swift— read/write the new fieldsDayflow/Core/AI/LLMService.swift— newproviderModelId(for:)helper and stamps the fields on every cardDayflow/Views/UI/TimelineDataModels.swift—providerBadgecomputed property + alias-to-display-name mappingDayflow/Views/UI/CanvasActivityCard.swift— small badge in the timeline cardDayflow/Views/UI/CanvasTimelineDataView.swift— passes the badge into the cardDayflow/Views/UI/MainView/ActivityCard.swift— detail-panel chipDayflow/Views/UI/MainView/TimelineActivityLoader.swift— pass-throughDayflow/Views/UI/MainView/WeekTimelineGridPreview.swift— test fixtureDayflow/Views/UI/TimelineReviewCard.swift— review-mode chipDayflow/Views/UI/TimelineReviewTypes.swift— pass-throughDayflowTests/TimelineActivityLoaderTests.swift— updated for the new fieldsDepends on
fix/claude-cli-model-alias) fixes a separate Claude CLI bug and depends on this PR.feat/chat-cli-model-picker) adds the Settings UI for picking the Claude/Codex model and depends on PRs 1 and 2.Test plan
xcodebuild build -configuration Debug— succeedsxcodebuild test -only-testing:DayflowTests— all unit tests pass