Fix residence auto-update, widget theming, and document patterns
- Fix residence detail not updating after edit: - DataManager.updateResidence() now updates both _residences and _myResidences - ResidenceViewModel auto-updates selectedResidence when data changes - No pull-to-refresh needed after editing - Add widget theme support: - Widgets now use user's selected theme via App Group UserDefaults - ThemeManager has simplified version for widget extension context - Added WIDGET_EXTENSION compiler flag to CaseraExtension target - Redesign widget views with organic aesthetic: - Updated FreeWidgetView, SmallWidgetView, MediumWidgetView, LargeWidgetView - Created OrganicTaskRowView, OrganicStatsView, OrganicStatPillWidget - Document patterns in CLAUDE.md: - Added Mutation & Auto-Update Pattern section - Added iOS Shared Components documentation - Documented reusable buttons, forms, empty states, cards, modifiers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import SwiftUI
|
||||
#if !WIDGET_EXTENSION
|
||||
import Combine
|
||||
#endif
|
||||
|
||||
// MARK: - Theme ID Enum
|
||||
enum ThemeID: String, CaseIterable, Codable {
|
||||
@@ -56,7 +59,31 @@ enum ThemeID: String, CaseIterable, Codable {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Shared App Group UserDefaults
|
||||
private let appGroupID = "group.com.tt.casera.CaseraDev"
|
||||
private let sharedDefaults = UserDefaults(suiteName: appGroupID) ?? UserDefaults.standard
|
||||
|
||||
// MARK: - Theme Manager
|
||||
#if WIDGET_EXTENSION
|
||||
// Simplified ThemeManager for widget extensions (no ObservableObject needed)
|
||||
class ThemeManager {
|
||||
static let shared = ThemeManager()
|
||||
|
||||
var currentTheme: ThemeID {
|
||||
// Load saved theme from shared App Group defaults
|
||||
if let savedThemeRawValue = sharedDefaults.string(forKey: themeKey),
|
||||
let savedTheme = ThemeID(rawValue: savedThemeRawValue) {
|
||||
return savedTheme
|
||||
}
|
||||
return .bright
|
||||
}
|
||||
|
||||
private let themeKey = "selectedTheme"
|
||||
|
||||
private init() {}
|
||||
}
|
||||
#else
|
||||
// Full ThemeManager for main app with ObservableObject support
|
||||
class ThemeManager: ObservableObject {
|
||||
static let shared = ThemeManager()
|
||||
|
||||
@@ -69,8 +96,8 @@ class ThemeManager: ObservableObject {
|
||||
private let themeKey = "selectedTheme"
|
||||
|
||||
private init() {
|
||||
// Load saved theme or default to .bright
|
||||
if let savedThemeRawValue = UserDefaults.standard.string(forKey: themeKey),
|
||||
// Load saved theme from shared App Group defaults
|
||||
if let savedThemeRawValue = sharedDefaults.string(forKey: themeKey),
|
||||
let savedTheme = ThemeID(rawValue: savedThemeRawValue) {
|
||||
self.currentTheme = savedTheme
|
||||
} else {
|
||||
@@ -79,7 +106,8 @@ class ThemeManager: ObservableObject {
|
||||
}
|
||||
|
||||
private func saveTheme() {
|
||||
UserDefaults.standard.set(currentTheme.rawValue, forKey: themeKey)
|
||||
// Save to shared App Group defaults so widgets can access it
|
||||
sharedDefaults.set(currentTheme.rawValue, forKey: themeKey)
|
||||
}
|
||||
|
||||
func setTheme(_ theme: ThemeID) {
|
||||
@@ -88,3 +116,4 @@ class ThemeManager: ObservableObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user