diff --git a/Apps/LekaApp/Sources/MainApp.swift b/Apps/LekaApp/Sources/MainApp.swift index e72e495af..59dc8adbd 100644 --- a/Apps/LekaApp/Sources/MainApp.swift +++ b/Apps/LekaApp/Sources/MainApp.swift @@ -59,6 +59,7 @@ struct LekaApp: App { @Environment(\.colorScheme) var colorScheme @StateObject var updateManager: UpdateManager = .shared + @StateObject var rootAccountViewModel = RootAccountManagerViewModel() @ObservedObject var styleManager: StyleManager = .shared var body: some Scene { diff --git a/Apps/LekaApp/Sources/Navigation/Navigation.swift b/Apps/LekaApp/Sources/Navigation/Navigation.swift index 118d04ffc..cd49a22f6 100644 --- a/Apps/LekaApp/Sources/Navigation/Navigation.swift +++ b/Apps/LekaApp/Sources/Navigation/Navigation.swift @@ -23,6 +23,7 @@ enum FullScreenCoverContent: Hashable, Identifiable { enum SheetContent: Hashable, Identifiable { case robotConnection + case consent case createCaregiver case editCaregiver case caregiverPicker diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView.swift b/Apps/LekaApp/Sources/Views/MainView/MainView.swift index 43d1f1c30..964d78e7b 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView.swift @@ -329,6 +329,21 @@ struct MainView: View { }) .logEventScreenView(screenName: "carereceiver_picker", context: .sheet) .navigationBarTitleDisplayMode(.inline) + + case .consent: + ConsentView( + onCancel: { + print("Consent was denied") // Add analytics + }, + onAccept: { + self.rootAccountViewModel.updateConsentInfo(policyVersion: self.latestPolicyVersion) + if self.caregiverManager.currentCaregiver.value == nil { + self.navigation.sheetContent = .caregiverPicker + } else { + self.navigation.sheetContent = nil + } + } + ) } } } @@ -375,6 +390,18 @@ struct MainView: View { self.caregiverManager.setCurrentCaregiver(byID: storedCaregiverID) } } + .onReceive(self.rootAccountViewModel.$currentRootAccount) { rootAccount in +// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + guard rootAccount != nil else { return } + + guard self.rootAccountViewModel.needsConsentUpdate( + latestPolicyVersion: self.latestPolicyVersion + ) else { + return + } + self.navigation.sheetContent = .consent +// } + } .onChange(of: self.caregiverManagerViewModel.currentCaregiver) { currentCaregiver in self.persistentDataManager.lastActiveCaregiverID = currentCaregiver?.id self.persistentDataManager.updateLastActiveTimestamp() @@ -401,6 +428,7 @@ struct MainView: View { private var persistentDataManager: PersistentDataManager = .shared private var caregiverManager: CaregiverManager = .shared private var carereceiverManager: CarereceiverManager = .shared + private var latestPolicyVersion: String = "1.2.4" // fetch from Yaml } // swiftlint:enable type_body_length diff --git a/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManager.swift b/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManager.swift index 4d1a460e0..9179481e2 100644 --- a/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManager.swift +++ b/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManager.swift @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 import Combine +import Foundation public class RootAccountManager { // MARK: Lifecycle @@ -57,6 +58,20 @@ public class RootAccountManager { .store(in: &self.cancellables) } + // MARK: ConsentInfo + + public func appendConsentInfo(policyVersion: String) { + guard var rootAccount = self.currentRootAccount.value else { + self.fetchErrorSubject.send(DatabaseError.customError("RootAccount not found")) + return + } + + let newConsentInfo = ConsentInfo(policyVersion: policyVersion, acceptedAt: Date()) + rootAccount.consentInfo.append(newConsentInfo) + + self.updateRootAccount(rootAccount: &rootAccount) + } + // MARK: Activities public func addSavedActivity(activityID: String, caregiverID: String) { diff --git a/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManagerViewModel.swift b/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManagerViewModel.swift index 0dcc4dbab..30bffa942 100644 --- a/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManagerViewModel.swift +++ b/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManagerViewModel.swift @@ -15,7 +15,8 @@ public class RootAccountManagerViewModel: ObservableObject { // MARK: Public - @Published public var latestConsentInfo: ConsentInfo? + @Published public var currentRootAccount: RootAccount? + @Published public var currentConsentInfo: ConsentInfo? // Not published @Published public var savedActivities: [SavedActivity] = [] @Published public var savedCurriculums: [SavedCurriculum] = [] @Published public var savedStories: [SavedStory] = [] @@ -84,6 +85,22 @@ public class RootAccountManagerViewModel: ObservableObject { self.rootAccountManager.resetData() } + // ConsentInfo + + public func needsConsentUpdate(latestPolicyVersion: String) -> Bool { + guard let currentConsent = self.currentConsentInfo, + let currentVersion = Version(tolerant: currentConsent.policyVersion), + let latestVersion = Version(tolerant: latestPolicyVersion) + else { + return true + } + return currentVersion < latestVersion + } + + public func updateConsentInfo(policyVersion: String) { + self.rootAccountManager.appendConsentInfo(policyVersion: policyVersion) + } + // MARK: Private private var cancellables = Set() @@ -102,6 +119,7 @@ public class RootAccountManagerViewModel: ObservableObject { .receive(on: DispatchQueue.main) .sink(receiveValue: { [weak self] rootAccount in guard let self, let rootAccount else { return } + self.currentRootAccount = rootAccount let library = rootAccount.library self.savedActivities = library.savedActivities @@ -109,7 +127,7 @@ public class RootAccountManagerViewModel: ObservableObject { self.savedStories = library.savedStories self.savedGamepads = library.savedGamepads - self.latestConsentInfo = self.getLatestConsentInfo(from: rootAccount.consentInfo) + self.currentConsentInfo = self.getLatestConsentInfo(from: rootAccount.consentInfo) }) .store(in: &self.cancellables)