Implement storage architecture from ai_blueprint.md
Primary sync: replace PersistenceActor JSON file with SwiftData + CloudKit - Add SavedCardModel (@Model class) and PersistenceController (ModelContainer with .automatic CloudKit, fallback to local). BackgroundPersistenceActor (@ModelActor) handles all DB I/O off the main thread. - One-time migration imports user_collection.json into SwiftData and renames the original file to prevent re-import. - Inject modelContainer into SwiftUI environment in IYmtgApp. Image storage: Documents/UserContent/ subfolder (blueprint requirement) - ImageManager.dir now targets iCloud Documents/UserContent/ (or local equiv). - migrateImagesToUserContent() moves existing JPGs to the new subfolder on first launch; called during the SwiftData migration. Firebase: demoted to optional manual backup (metadata only, no images) - Remove all automatic CloudEngine.save/delete/batchUpdatePrices calls from CollectionViewModel mutations. - Add backupAllToFirebase() for user-triggered metadata sync. - Add isFirebaseBackupEnabled to AppConfig (default false). - Add Cloud Backup section in Library settings with iCloud vs Firebase explanation and "Backup Metadata to Firebase Now" button. Also: full modular refactor (Data/, Features/, Services/ directories) and README updated with CloudKit setup steps and revised release checklist. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
40
README.md
40
README.md
@@ -208,12 +208,34 @@ IYmtg_Training/
|
||||
|
||||
## 4. Backend & Security
|
||||
|
||||
### Firebase Configuration (Required for Cloud Sync)
|
||||
### Cloud Storage Architecture
|
||||
The app uses a two-tier cloud strategy:
|
||||
|
||||
| Tier | Technology | What it stores | Cost |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **Primary** | iCloud + CloudKit (SwiftData) | All card metadata, synced automatically across devices | Free (user's iCloud) |
|
||||
| **Secondary** | Firebase Firestore | Metadata only — no images — optional manual backup | Free (Firestore free tier) |
|
||||
|
||||
Card images are stored in the user's iCloud Drive under `Documents/UserContent/` and are **never** uploaded to Firebase.
|
||||
|
||||
### iCloud / CloudKit Setup (Required for Primary Sync)
|
||||
1. In Xcode, open **Signing & Capabilities**.
|
||||
2. Add the **iCloud** capability. Enable **CloudKit**.
|
||||
3. Add a CloudKit container named `iCloud.<your-bundle-id>`.
|
||||
4. Add the **Background Modes** capability. Enable **Remote notifications**.
|
||||
5. Set the minimum deployment target to **iOS 17** (required by SwiftData).
|
||||
|
||||
Without this setup the app falls back to local-only storage automatically.
|
||||
|
||||
### Firebase Configuration (Optional Secondary Backup)
|
||||
Firebase is no longer the primary sync mechanism. It serves as a user-triggered metadata backup.
|
||||
1. **Create Project:** Go to the Firebase Console and create a new project.
|
||||
2. **Authentication:** Enable "Anonymous" sign-in in the Authentication tab.
|
||||
3. **Firestore Database:** Create a database and apply the rules from `IYmtg_App_iOS/Firebase/firestore.rules`.
|
||||
4. **Storage:** Enable Storage and apply the rules from `IYmtg_App_iOS/Firebase/storage.rules`.
|
||||
5. **Setup:** Download `GoogleService-Info.plist` from Project Settings and drag it into the `IYmtg_App_iOS` folder in Xcode (ensure "Copy items if needed" is checked).
|
||||
4. **Setup:** Download `GoogleService-Info.plist` from Project Settings and drag it into the `IYmtg_App_iOS` folder in Xcode (ensure "Copy items if needed" is checked).
|
||||
5. Users trigger backup manually via **Library → Cloud Backup → Backup Metadata to Firebase Now**.
|
||||
|
||||
The app runs fully without `GoogleService-Info.plist` (Local Mode — iCloud sync still works).
|
||||
|
||||
### Over-the-Air (OTA) Model Updates
|
||||
To update ML models without an App Store release:
|
||||
@@ -249,6 +271,7 @@ chmod +x IYmtg_Automation/weekly_update.sh
|
||||
**CRITICAL:** Edit `IYmtg_App_iOS/AppConfig.swift` before building to ensure payments and support work correctly:
|
||||
1. Set `contactEmail` to your real email address.
|
||||
2. Set `tipJarProductIDs` to your actual In-App Purchase IDs.
|
||||
3. `isFirebaseBackupEnabled` defaults to `false`. Users opt-in from Library settings.
|
||||
|
||||
## 7. Development Mode
|
||||
|
||||
@@ -279,12 +302,17 @@ Perform these steps before submitting to the App Store.
|
||||
* [ ] Verify `contactEmail` is valid.
|
||||
* [ ] Verify `tipJarProductIDs` match App Store Connect.
|
||||
* [ ] Ensure `enableFoilDetection` and other flags are `true`.
|
||||
2. **Assets:**
|
||||
2. **iCloud / CloudKit:**
|
||||
* [ ] Signing & Capabilities → iCloud → CloudKit enabled.
|
||||
* [ ] CloudKit container added: `iCloud.<bundle-id>`.
|
||||
* [ ] Background Modes → Remote notifications enabled.
|
||||
* [ ] Minimum deployment target set to **iOS 17**.
|
||||
3. **Assets:**
|
||||
* [ ] Ensure `Assets.xcassets` has the AppIcon filled for all sizes.
|
||||
3. **Testing:**
|
||||
4. **Testing:**
|
||||
* [ ] Run Unit Tests (`Cmd+U`) - All must pass.
|
||||
* [ ] Run on Physical Device - Verify Camera permissions prompt appears.
|
||||
4. **Build:**
|
||||
5. **Build:**
|
||||
* [ ] Select "Any iOS Device (arm64)".
|
||||
* [ ] Product -> Archive.
|
||||
* [ ] Validate App in Organizer.
|
||||
|
||||
Reference in New Issue
Block a user