Skip to content

feat: surface provider and model on each generated card#326

Open
M3NT1 wants to merge 2 commits into
JerryZLiu:mainfrom
M3NT1:feat/per-card-provider-badge
Open

feat: surface provider and model on each generated card#326
M3NT1 wants to merge 2 commits into
JerryZLiu:mainfrom
M3NT1:feat/per-card-provider-badge

Conversation

@M3NT1

@M3NT1 M3NT1 commented Jul 19, 2026

Copy link
Copy Markdown

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:

  • Canvas timeline card (the timeline list view) — 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), 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 optional providerId and modelId fields on TimelineCard, TimelineCardShell, TimelineActivity, and TimelineMetadata
  • Dayflow/Core/Recording/StorageManager+TimelineCards.swift — read/write the new fields
  • Dayflow/Core/AI/LLMService.swift — new providerModelId(for:) helper and stamps the fields on every card
  • Dayflow/Views/UI/TimelineDataModels.swiftproviderBadge computed property + alias-to-display-name mapping
  • Dayflow/Views/UI/CanvasActivityCard.swift — small badge in the timeline card
  • Dayflow/Views/UI/CanvasTimelineDataView.swift — passes the badge into the card
  • Dayflow/Views/UI/MainView/ActivityCard.swift — detail-panel chip
  • Dayflow/Views/UI/MainView/TimelineActivityLoader.swift — pass-through
  • Dayflow/Views/UI/MainView/WeekTimelineGridPreview.swift — test fixture
  • Dayflow/Views/UI/TimelineReviewCard.swift — review-mode chip
  • Dayflow/Views/UI/TimelineReviewTypes.swift — pass-through
  • DayflowTests/TimelineActivityLoaderTests.swift — updated for the new fields

Depends on

  • This is the first of three PRs. It stands on its own.
  • PR 2 (fix/claude-cli-model-alias) fixes a separate Claude CLI bug and depends on this PR.
  • PR 3 (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 — succeeds
  • xcodebuild test -only-testing:DayflowTests — all unit tests pass
  • Manual: open the timeline, confirm the badge appears on a new card; confirm older cards render without one.

M3NT1 added 2 commits July 19, 2026 21:51
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant