Migrate offline settings from UserDefaults to CoreData

Move offline reading settings from JSON-based UserDefaults storage to CoreData SettingEntity for consistency with other app settings.

Changes:
- Add offline settings fields to SettingEntity (offlineEnabled, offlineMaxUnreadArticles, offlineSaveImages, offlineLastSyncDate)
- Update SettingsRepository to use CoreData instead of UserDefaults for offline settings
- Use consistent async/await pattern with withCheckedThrowingContinuation
- Remove JSON encoding/decoding in favor of direct CoreData properties

Benefits:
- Unified settings storage in CoreData
- Type-safe property access
- Automatic migration support
- No redundant UserDefaults entries
This commit is contained in:
Ilyas Hallak 2025-12-01 21:43:29 +01:00
parent b9f8e11782
commit 39bb82ee3e
2 changed files with 52 additions and 13 deletions

View File

@ -273,25 +273,60 @@ class SettingsRepository: PSettingsRepository {
// MARK: - Offline Settings
private let offlineSettingsKey = "offlineSettings"
private let logger = Logger.data
func loadOfflineSettings() async throws -> OfflineSettings {
guard let data = userDefault.data(forKey: offlineSettingsKey) else {
logger.info("No offline settings found, returning defaults")
return OfflineSettings() // Default settings
}
let context = coreDataManager.context
let decoder = JSONDecoder()
let settings = try decoder.decode(OfflineSettings.self, from: data)
logger.debug("Loaded offline settings: enabled=\(settings.enabled), max=\(settings.maxUnreadArticlesInt)")
return settings
return try await withCheckedThrowingContinuation { continuation in
context.perform {
do {
let fetchRequest: NSFetchRequest<SettingEntity> = SettingEntity.fetchRequest()
fetchRequest.fetchLimit = 1
let settingEntities = try context.fetch(fetchRequest)
let settingEntity = settingEntities.first
let settings = OfflineSettings(
enabled: settingEntity?.offlineEnabled ?? false,
maxUnreadArticles: settingEntity?.offlineMaxUnreadArticles ?? 20,
saveImages: settingEntity?.offlineSaveImages ?? true,
lastSyncDate: settingEntity?.offlineLastSyncDate
)
self.logger.debug("Loaded offline settings: enabled=\(settings.enabled), max=\(settings.maxUnreadArticlesInt)")
continuation.resume(returning: settings)
} catch {
self.logger.error("Failed to load offline settings: \(error.localizedDescription)")
continuation.resume(throwing: error)
}
}
}
}
func saveOfflineSettings(_ settings: OfflineSettings) async throws {
let encoder = JSONEncoder()
let data = try encoder.encode(settings)
userDefault.set(data, forKey: offlineSettingsKey)
logger.info("Saved offline settings: enabled=\(settings.enabled), max=\(settings.maxUnreadArticlesInt)")
let context = coreDataManager.context
return try await withCheckedThrowingContinuation { continuation in
context.perform {
do {
let fetchRequest: NSFetchRequest<SettingEntity> = SettingEntity.fetchRequest()
let existingSettings = try context.fetch(fetchRequest).first ?? SettingEntity(context: context)
existingSettings.offlineEnabled = settings.enabled
existingSettings.offlineMaxUnreadArticles = settings.maxUnreadArticles
existingSettings.offlineSaveImages = settings.saveImages
existingSettings.offlineLastSyncDate = settings.lastSyncDate
try context.save()
self.logger.info("Saved offline settings: enabled=\(settings.enabled), max=\(settings.maxUnreadArticlesInt)")
continuation.resume()
} catch {
self.logger.error("Failed to save offline settings: \(error.localizedDescription)")
continuation.resume(throwing: error)
}
}
}
}
}

View File

@ -61,6 +61,10 @@
<attribute name="enableTTS" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="fontFamily" optional="YES" attributeType="String"/>
<attribute name="fontSize" optional="YES" attributeType="String"/>
<attribute name="offlineEnabled" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="offlineLastSyncDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="offlineMaxUnreadArticles" optional="YES" attributeType="Double" defaultValueString="20" usesScalarValueType="YES"/>
<attribute name="offlineSaveImages" optional="YES" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="tagSortOrder" optional="YES" attributeType="String"/>
<attribute name="theme" optional="YES" attributeType="String"/>
<attribute name="token" optional="YES" attributeType="String"/>