diff --git a/iosApp/iosApp/Core/Dependencies.swift b/iosApp/iosApp/Core/Dependencies.swift index 36c0b9c..048de4d 100644 --- a/iosApp/iosApp/Core/Dependencies.swift +++ b/iosApp/iosApp/Core/Dependencies.swift @@ -40,29 +40,32 @@ final class Dependencies { // MARK: - Kotlin ViewModel Factories + // SKIE doesn't expose Kotlin default constructor params to Swift, so + // pass DataManager.shared explicitly on each factory. + /// Create a new AuthViewModel instance func makeAuthViewModel() -> ComposeApp.AuthViewModel { - ComposeApp.AuthViewModel() + ComposeApp.AuthViewModel(dataManager: ComposeApp.DataManager.shared) } /// Create a new ResidenceViewModel instance func makeResidenceViewModel() -> ComposeApp.ResidenceViewModel { - ComposeApp.ResidenceViewModel() + ComposeApp.ResidenceViewModel(dataManager: ComposeApp.DataManager.shared) } /// Create a new TaskViewModel instance func makeTaskViewModel() -> ComposeApp.TaskViewModel { - ComposeApp.TaskViewModel() + ComposeApp.TaskViewModel(dataManager: ComposeApp.DataManager.shared) } /// Create a new ContractorViewModel instance func makeContractorViewModel() -> ComposeApp.ContractorViewModel { - ComposeApp.ContractorViewModel() + ComposeApp.ContractorViewModel(dataManager: ComposeApp.DataManager.shared) } /// Create a new DocumentViewModel instance func makeDocumentViewModel() -> ComposeApp.DocumentViewModel { - ComposeApp.DocumentViewModel() + ComposeApp.DocumentViewModel(dataManager: ComposeApp.DataManager.shared) } // MARK: - Service Factories diff --git a/iosApp/iosApp/Login/AppleSignInViewModel.swift b/iosApp/iosApp/Login/AppleSignInViewModel.swift index ca4a193..edfddfe 100644 --- a/iosApp/iosApp/Login/AppleSignInViewModel.swift +++ b/iosApp/iosApp/Login/AppleSignInViewModel.swift @@ -13,6 +13,12 @@ class AppleSignInViewModel: ObservableObject { // MARK: - Private Properties private let appleSignInManager = AppleSignInManager() + private let dataManager: DataManagerObservable + + // MARK: - Initialization + init(dataManager: DataManagerObservable = .shared) { + self.dataManager = dataManager + } // MARK: - Callbacks var onSignInSuccess: ((Bool) -> Void)? // Bool indicates if user is verified diff --git a/iosApp/iosApp/Onboarding/OnboardingTasksViewModel.swift b/iosApp/iosApp/Onboarding/OnboardingTasksViewModel.swift index 56257f6..835a4f8 100644 --- a/iosApp/iosApp/Onboarding/OnboardingTasksViewModel.swift +++ b/iosApp/iosApp/Onboarding/OnboardingTasksViewModel.swift @@ -33,6 +33,14 @@ final class OnboardingTasksViewModel: ObservableObject { @Published private(set) var isSubmitting = false @Published private(set) var submitError: String? + // MARK: - Private Properties + private let dataManager: DataManagerObservable + + // MARK: - Initialization + init(dataManager: DataManagerObservable = .shared) { + self.dataManager = dataManager + } + // MARK: - Loads func loadSuggestions(residenceId: Int32) async { diff --git a/iosApp/iosApp/PasswordReset/PasswordResetViewModel.swift b/iosApp/iosApp/PasswordReset/PasswordResetViewModel.swift index 37f170a..ae0e57f 100644 --- a/iosApp/iosApp/PasswordReset/PasswordResetViewModel.swift +++ b/iosApp/iosApp/PasswordReset/PasswordResetViewModel.swift @@ -31,8 +31,15 @@ class PasswordResetViewModel: ObservableObject { // Cancellable delayed transition task private var delayedTransitionTask: Task? + // MARK: - Private Properties + private let dataManager: DataManagerObservable + // MARK: - Initialization - init(resetToken: String? = nil) { + init( + resetToken: String? = nil, + dataManager: DataManagerObservable = .shared + ) { + self.dataManager = dataManager // If we have a reset token from deep link, skip to password reset step if let token = resetToken { self.resetToken = token diff --git a/iosApp/iosApp/Register/RegisterViewModel.swift b/iosApp/iosApp/Register/RegisterViewModel.swift index 4ab799a..1269c99 100644 --- a/iosApp/iosApp/Register/RegisterViewModel.swift +++ b/iosApp/iosApp/Register/RegisterViewModel.swift @@ -15,8 +15,13 @@ class RegisterViewModel: ObservableObject { @Published var errorMessage: String? @Published var isRegistered: Bool = false + // MARK: - Private Properties + private let dataManager: DataManagerObservable + // MARK: - Initialization - init() {} + init(dataManager: DataManagerObservable = .shared) { + self.dataManager = dataManager + } // MARK: - Public Methods func register() { diff --git a/iosApp/iosApp/VerifyEmail/VerifyEmailViewModel.swift b/iosApp/iosApp/VerifyEmail/VerifyEmailViewModel.swift index 59b474b..78ad1ab 100644 --- a/iosApp/iosApp/VerifyEmail/VerifyEmailViewModel.swift +++ b/iosApp/iosApp/VerifyEmail/VerifyEmailViewModel.swift @@ -14,10 +14,15 @@ class VerifyEmailViewModel: ObservableObject { // MARK: - Private Properties private let tokenStorage: TokenStorageProtocol + private let dataManager: DataManagerObservable // MARK: - Initialization - init(tokenStorage: TokenStorageProtocol? = nil) { + init( + tokenStorage: TokenStorageProtocol? = nil, + dataManager: DataManagerObservable = .shared + ) { self.tokenStorage = tokenStorage ?? Dependencies.current.makeTokenStorage() + self.dataManager = dataManager } // MARK: - Public Methods diff --git a/iosApp/iosApp/iOSApp.swift b/iosApp/iosApp/iOSApp.swift index 190e21d..48b84ef 100644 --- a/iosApp/iosApp/iOSApp.swift +++ b/iosApp/iosApp/iOSApp.swift @@ -66,6 +66,10 @@ struct iOSApp: App { var body: some Scene { WindowGroup { RootView(deepLinkResetToken: $deepLinkResetToken) + // Single source of truth injection — every descendant view can + // reach @EnvironmentObject var dataManager: DataManagerObservable + // without reading the .shared singleton implicitly. + .environmentObject(DataManagerObservable.shared) .environmentObject(themeManager) .environmentObject(contractorSharingManager) .environmentObject(residenceSharingManager)