1.0.5: Eating out slots, rule violations panel, Crashlytics, search bar fix

- Eating out: tap any empty slot → "Mark as eating out"; shows teal indicator,
  skipped by auto-assign, counts as complete, tap again to unmark
- Rule violations panel: access via wand long-press context menu when conflicts exist;
  shows all isRuleOverridden slots with Fix (clear) or Ignore (acknowledge) actions
- Firebase Crashlytics integrated: CrashlyticsService + dSYM upload build phase,
  isPremium property tracked per session
- PremiumSyncService: extracted premium state machine, StoreKit Transaction.updates
  listener, isPremium no longer synced via iCloud to avoid stale state
- StoreManager: analytics on purchase/restore, bundle ID fallback for product ID lookup
- Search bar contrast bug fixed: TextField now has explicit foreground color for dark mode
- WelcomeStepView: redesigned onboarding welcome screen with week preview
- Version bump: 1.0.5 build 22

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
alexandrev-tibco
2026-04-27 09:48:20 +02:00
parent 6c7e12b41f
commit 110807d239
111 changed files with 3116 additions and 154 deletions
+5 -3
View File
@@ -71,7 +71,6 @@ final class ICloudSyncService {
reminderMinutesBefore: $0.reminderMinutesBefore,
iCloudSyncEnabled: $0.iCloudSyncEnabled,
weekExportStyle: $0.weekExportStyle,
isPremium: $0.isPremium,
onboardingCompleted: $0.onboardingCompleted
)
},
@@ -153,7 +152,9 @@ final class ICloudSyncService {
settings.reminderMinutesBefore = settingsPayload.reminderMinutesBefore
settings.iCloudSyncEnabled = settingsPayload.iCloudSyncEnabled
settings.weekExportStyle = settingsPayload.weekExportStyle
settings.isPremium = settingsPayload.isPremium
// isPremium is intentionally NOT synced via iCloud.
// It is determined exclusively by StoreKit to avoid stale state
// overwriting a freshly completed purchase.
settings.onboardingCompleted = settingsPayload.onboardingCompleted
context.insert(settings)
}
@@ -236,8 +237,9 @@ private struct SettingsPayload: Codable {
let reminderMinutesBefore: Int?
let iCloudSyncEnabled: Bool?
let weekExportStyle: String?
let isPremium: Bool
let onboardingCompleted: Bool
// isPremium is intentionally omitted determined by StoreKit only, never by sync.
// Old payloads in iCloud may contain this key; it is safely ignored by the decoder.
}
private struct TagPayload: Codable {