Resolve #328: MistDemoApp CloudKit refresh (CKRecord-first, @Observable)#339
Conversation
…, public/private picker) - Rename `NativeCloudKitService`/`Error` to `CloudKitStore`/`Error` — the app target no longer depends on MistKit, so the "Native" disambiguator is dead weight; "Store" reads as the SwiftUI source-of-truth idiom. - `Note` wraps `CKRecord` instead of copying fields out of it. Update is now "mutate the held record, save" — no extra fetch round-trip to refresh the change tag. - `@Observable` + `@MainActor` on `CloudKitStore`; views use `@Environment(CloudKitStore.self)` and `@Bindable` for the picker. App entry switches to `@State` + `.environment(_:)`. - Public/private database picker in `AccountView`; `QueryView` and `ZoneListView` re-fetch on `.onChange(of: store.databaseScope)` and show the active scope in their navigation title. - Drop web-auth-token UI (`AccountView+Actions.swift`, related state) and the `CLOUDKIT_API_TOKEN` scheme env var — the native app authenticates via the signed-in iCloud user. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## 330-interactive-mistdemo #339 +/- ##
============================================================
- Coverage 70.54% 70.51% -0.04%
============================================================
Files 549 551 +2
Lines 15317 15422 +105
============================================================
+ Hits 10806 10875 +69
- Misses 4511 4547 +36
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
WebBackendFactory.live calls CloudKitService's URLSession-defaulted convenience init, which is gated behind #if !os(WASI). The rest of the Server/ folder is already wrapped in #if canImport(Hummingbird); this file was missed. Wrapping it the same way unblocks the wasm, wasm 6.2, and wasm-embedded CI jobs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…auth-token UI Two review comments from #pullrequestreview-4286058024: 1. Note: revert from CKRecord wrapper back to value-struct (id/title/index/ imageAssetURL + system metadata). updateNote now fetches by ID before apply+save instead of mutating the original record in place; deleteNote reconstructs CKRecord.ID from the recordName. Views switch from note.recordName to note.id. 2. AccountView: restore the API-token TextField, "Fetch Web Auth Token" button, copyable token display, and CLOUDKIT_API_TOKEN env-var seed, ported from the pre-#328 NativeCloudKitService design onto the new @observable CloudKitStore + @Environment binding. Database picker stays. Adds CloudKitStore.fetchWebAuthToken via CKFetchWebAuthTokenOperation and a webAuthTokenUnavailable error case. Recreates AccountView+Actions.swift (deleted in #328). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
PR 339 Review: MistDemoApp CloudKit refresh Summary: Renames NativeCloudKitService to CloudKitStore, migrates from ObservableObject/@Published/Combine to @observable, replaces @EnvironmentObject with @Environment, and adds a public/private database scope picker that re-fetches on change. A focused, clean SwiftUI modernisation. Strengths
Issues
No-action notes
Overall: Clean and correct modernisation. The CKDatabase.Scope question and the fetchWebAuthToken database routing are the two items worth confirming before merge; the rest is minor. |
…ing + scheme env - Replace CloudKitStore.DatabaseScope with CKDatabase.Scope; new CKDatabaseScope+Demo.swift extension provides the demo-scoped selectable list ([.public, .private]) and label. - Route CKFetchWebAuthTokenOperation through container.privateCloudDatabase unconditionally; the operation is documented to require the private database and was previously running against the user-selected scope. - Migrate fetchWebAuthTokenCompletionBlock -> fetchWebAuthTokenResultBlock (the completion-block API is deprecated in macOS 12+); drop the now- unreachable webAuthTokenUnavailable error case. - Bake CLOUDKIT_API_TOKEN into the macOS + iOS scheme run actions so xcodegen substitutes the .env value AccountView already reads from ProcessInfo at launch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rash The continuation body inherited @mainactor isolation from CloudKitStore, which tripped a dispatch_assert_queue assertion on com.apple.cloudkit.callback when CKFetchWebAuthTokenOperation's result block fired — crashing with EXC_BREAKPOINT in _dispatch_assert_queue_fail on macOS 26.5. Marking the bridge nonisolated lets the operation enqueue + callback dispatch run off the main actor. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors the web demo: track the signed-in user's record name via CKContainer.userRecordID, capture each note's creator from CKRecord.creatorUserRecordID, and tag matching rows in QueryView. Also sorts Notes by creationDate desc with modificationDate desc as the tiebreaker, matching the web demo's default ordering. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code Review — PR #339: MistDemoApp CloudKit refresh (CKRecord-first, @observable)OverviewThis PR has two distinct layers of change worth reviewing separately:
Both layers are clean and well-motivated. Notes below are mostly minor. Strengths
Issues & Suggestions1.
|
Summary
Refresh
MistDemoAppto use SwiftUI-idiomatic CloudKit-framework patterns and finish the app side of #275 (public/private picker). Closes #328.CloudKitStore(renamed fromNativeCloudKitService):@Observable+@MainActor. DropsObservableObject/@Published/ Combine. Errors renamed toCloudKitStoreError.NotewrapsCKRecordas the source of truth. Update mutates the held record and saves — no extrarecord(for:)fetch to refresh the change tag.@Environment(CloudKitStore.self);AccountViewuses@Bindablefor the picker binding; sheets re-inject with.environment(_:).AccountView;QueryViewandZoneListViewre-fetch on.onChange(of: store.databaseScope)and display the active scope in their navigation title.AccountView+Actions.swift, related state, and theCLOUDKIT_API_TOKENscheme env var inproject.yml. The native app authenticates via the signed-in iCloud user — no token plumbing applies.MistDemoApptarget already had no MistKit dep — confirmed clean. The web demo and CLI continue to use MistKit.Notes
CKRecord(per the issue's API surface) rather than SwiftData+CloudKit; SwiftData would shift the comparison axis of the Interactive MistDemo: web (MistKit vs CloudKit JS) + native app (pure CloudKit framework) #330 story and was an explicit non-goal here.328-native-cloudkit-framework). Happy to rename if preferred — let me know.Test plan
swift buildinExamples/MistDemo(passes)./Scripts/lint.shfrom repo root (passes; no warnings on touched files)make generateor xcodegen) and runMistDemoApp-macOS/-iOSagainst a real containerpublicCloudDatabaseandprivateCloudDatabaserecord(for:)round-trip (network panel)🤖 Generated with Claude Code