ReadKeep/readeck/UI/readeckApp.swift
Ilyas Hallak b9f8e11782 Refactor offline sync to enforce Clean Architecture
Refactorings:
- Extract HTMLImageEmbedder and HTMLImageExtractor utilities
- Create UseCases for cached data access (GetCachedBookmarksUseCase, GetCachedArticleUseCase)
- Create CreateAnnotationUseCase to remove API dependency from ViewModel
- Simplify CachedAsyncImage by extracting helper methods
- Fix Kingfisher API compatibility (Source types, Result handling)
- Add documentation to OfflineCacheSyncUseCase
- Remove unused TestView from production code

Enforces Clean Architecture:
- ViewModels now only use UseCases, no direct Repository or API access
- All data layer access goes through Domain layer
2025-11-30 19:12:51 +01:00

75 lines
2.1 KiB
Swift

//
// readeckApp.swift
// readeck
//
// Created by Ilyas Hallak on 10.06.25.
//
import SwiftUI
import netfox
@main
struct readeckApp: App {
@State private var appViewModel = AppViewModel()
@StateObject private var appSettings = AppSettings()
@Environment(\.scenePhase) private var scenePhase
#if DEBUG
@State private var showDebugMenu = false
#endif
var body: some Scene {
WindowGroup {
Group {
if appViewModel.hasFinishedSetup {
MainTabView()
} else {
OnboardingServerView()
.padding()
}
}
.environmentObject(appSettings)
.environment(\.managedObjectContext, CoreDataManager.shared.context)
.preferredColorScheme(appSettings.theme.colorScheme)
#if DEBUG
.onShake {
showDebugMenu = true
}
.sheet(isPresented: $showDebugMenu) {
DebugMenuView()
.environmentObject(appSettings)
}
#endif
.onAppear {
#if DEBUG
NFX.sharedInstance().start()
#endif
Task {
await loadAppSettings()
}
appViewModel.bindNetworkStatus(to: appSettings)
}
.onReceive(NotificationCenter.default.publisher(for: .settingsChanged)) { _ in
Task {
await loadAppSettings()
}
}
.onChange(of: scenePhase) { oldPhase, newPhase in
if newPhase == .active {
Task {
await appViewModel.onAppResume()
}
}
}
}
}
private func loadAppSettings() async {
let settingsRepository = SettingsRepository()
let settings = try? await settingsRepository.loadSettings()
await MainActor.run {
appSettings.settings = settings
}
}
}