Skip to content

Commit 90b8330

Browse files
committed
🔀️ Merge branch 'release/LekaApp/1.13.0'
2 parents 39127c0 + a3c6c66 commit 90b8330

394 files changed

Lines changed: 3954 additions & 772 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Apps/LekaApp/Project.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ let kLekaAppVersion: String = {
1313
}
1414

1515
// ? App version
16-
return "1.12.0"
16+
return "1.13.0"
1717
}()
1818

1919
let project = Project.app(

Apps/LekaApp/Sources/Navigation/Navigation+Category.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ extension Navigation {
2626
case vectorImageList
2727
case news
2828
case demo
29+
case libraryCurriculums
30+
case libraryActivities
31+
case libraryStories
32+
case libraryGamepads
2933

3034
// MARK: Internal
3135

Apps/LekaApp/Sources/Views/ConnectionView.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct ConnectionView: View {
7777
if newValue == .loggedIn {
7878
self.caregiverManager.initializeCaregiversListener()
7979
self.carereceiverManager.initializeCarereceiversListener()
80+
self.rootAccountManager.initializeRootAccountListener()
8081
self.authManagerViewModel.userAction = .none
8182
self.navigation.fullScreenCoverContent = nil
8283
}
@@ -99,6 +100,7 @@ struct ConnectionView: View {
99100
@State private var showResetPassword: Bool = false
100101

101102
private var authManager: AuthManager = .shared
103+
private var rootAccountManager: RootAccountManager = .shared
102104
private var caregiverManager: CaregiverManager = .shared
103105
private var carereceiverManager: CarereceiverManager = .shared
104106

Apps/LekaApp/Sources/Views/MainView/MainView+CategoryLabel.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ extension MainView {
99
struct CategoryLabel: View {
1010
// MARK: Lifecycle
1111

12+
// swiftlint:disable cyclomatic_complexity body_length
13+
1214
init(category: Navigation.Category) {
1315
self.category = category
1416

@@ -84,9 +86,27 @@ extension MainView {
8486
case .demo:
8587
self.title = "Demo"
8688
self.systemImage = "play.rectangle"
89+
90+
case .libraryCurriculums:
91+
self.title = String(l10n.MainView.Sidebar.CategoryLabel.curriculums.characters)
92+
self.systemImage = "graduationcap.fill"
93+
94+
case .libraryActivities:
95+
self.title = String(l10n.MainView.Sidebar.CategoryLabel.activities.characters)
96+
self.systemImage = "dice.fill"
97+
98+
case .libraryStories:
99+
self.title = String(l10n.MainView.Sidebar.CategoryLabel.stories.characters)
100+
self.systemImage = "text.book.closed.fill"
101+
102+
case .libraryGamepads:
103+
self.title = String(l10n.MainView.Sidebar.CategoryLabel.gamepads.characters)
104+
self.systemImage = "gamecontroller.fill"
87105
}
88106
}
89107

108+
// swiftlint:enable cyclomatic_complexity body_length
109+
90110
// MARK: Internal
91111

92112
let category: Navigation.Category

Apps/LekaApp/Sources/Views/MainView/MainView.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ struct MainView: View {
8888
CategoryLabel(category: .vectorImageList)
8989
CategoryLabel(category: .news)
9090
}
91+
92+
Section("Library") {
93+
CategoryLabel(category: .libraryCurriculums)
94+
CategoryLabel(category: .libraryActivities)
95+
CategoryLabel(category: .libraryStories)
96+
CategoryLabel(category: .libraryGamepads)
97+
}
9198
} else {
9299
Section("Demo mode") {
93100
CategoryLabel(category: .demo)
@@ -173,6 +180,22 @@ struct MainView: View {
173180
case .demo:
174181
DiscoverLekaView(demoMode: self.navigation.demoMode)
175182

183+
case .libraryCurriculums:
184+
Text("Curriculums")
185+
.navigationTitle("Curriculums")
186+
187+
case .libraryActivities:
188+
Text("Activities")
189+
.navigationTitle("Activities")
190+
191+
case .libraryStories:
192+
Text("Stories")
193+
.navigationTitle("Stories")
194+
195+
case .libraryGamepads:
196+
Text("Gamepads")
197+
.navigationTitle("Gamepads")
198+
176199
case .none:
177200
Text(l10n.MainView.Sidebar.CategoryLabel.home)
178201
.font(.largeTitle)

Apps/LekaApp/Sources/Views/Settings/SettingsView.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,12 @@ struct SettingsView: View {
212212
@ObservedObject private var styleManager: StyleManager = .shared
213213
@ObservedObject private var navigation = Navigation.shared
214214

215+
@StateObject private var rootAccountViewModel = RootAccountManagerViewModel()
216+
215217
private func reset() {
216218
self.caregiverManager.resetData()
217219
self.carereceiverManager.resetData()
220+
self.rootAccountViewModel.resetData()
218221
self.styleManager.accentColor = DesignKitAsset.Colors.lekaDarkBlue.swiftUIColor
219222
self.styleManager.colorScheme = .light
220223
}

Apps/LekaApp/Sources/Views/Users/CareReceiver/CreateCarereceiverView.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ struct CreateCarereceiverView: View {
8080
}
8181
}
8282

83+
Section {
84+
LabeledContent(String(l10n.ReinforcerPicker.header.characters)) {
85+
ReinforcerPicker(carereceiver: self.$newCarereceiver)
86+
}
87+
} footer: {
88+
Text(l10n.ReinforcerPicker.description)
89+
}
90+
8391
Button(String(l10n.CarereceiverCreation.createProfileButtonLabel.characters)) {
8492
if self.newCarereceiver.avatar.isEmpty {
8593
self.newCarereceiver.avatar = Avatars.categories.first!.avatars.randomElement()!

Modules/AccountKit/Sources/Database/DatabaseOperations.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,45 @@ public class DatabaseOperations {
9797
return subject.eraseToAnyPublisher()
9898
}
9999

100+
public func getCurrentRootAccount() -> AnyPublisher<RootAccount, Error> {
101+
let subject = PassthroughSubject<RootAccount, Error>()
102+
103+
guard let currentUserID = Auth.auth().currentUser?.uid else {
104+
subject.send(completion: .failure(DatabaseError.customError("User not authenticated")))
105+
return subject.eraseToAnyPublisher()
106+
}
107+
108+
if let existingListener = listenerRegistrations["ROOT_ACCOUNTS_\(currentUserID)"] {
109+
existingListener.remove()
110+
self.listenerRegistrations.removeValue(forKey: "ROOT_ACCOUNTS_\(currentUserID)")
111+
}
112+
113+
let listener = self.database.collection(DatabaseCollection.rootAccounts.rawValue)
114+
.whereField("root_owner_uid", isEqualTo: currentUserID)
115+
.addSnapshotListener { querySnapshot, error in
116+
if let error {
117+
log.error("\(error.localizedDescription)")
118+
subject.send(completion: .failure(error))
119+
} else if let querySnapshot, let document = querySnapshot.documents.first {
120+
do {
121+
let rootAccount = try document.data(as: RootAccount.self)
122+
log.info("Root account document fetched successfully for user \(currentUserID). 🎉")
123+
subject.send(rootAccount)
124+
} catch {
125+
log.error("\(error.localizedDescription)")
126+
subject.send(completion: .failure(error))
127+
}
128+
} else {
129+
log.error("Root account document not found for user \(currentUserID).")
130+
subject.send(completion: .failure(DatabaseError.documentNotFound))
131+
}
132+
}
133+
134+
self.listenerRegistrations["ROOT_ACCOUNTS_\(currentUserID)"] = listener
135+
136+
return subject.eraseToAnyPublisher()
137+
}
138+
100139
public func clearAllListeners() {
101140
for (_, registration) in self.listenerRegistrations {
102141
registration.remove()
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Leka - iOS Monorepo
2+
// Copyright APF France handicap
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
import FirebaseFirestore
6+
import SwiftUI
7+
8+
extension Library: Codable {
9+
public init(from decoder: Decoder) throws {
10+
let container = try decoder.container(keyedBy: CodingKeys.self)
11+
12+
self.id = try container.decodeIfPresent(String.self, forKey: .id)
13+
self.rootOwnerUid = try container.decode(String.self, forKey: .rootOwnerUid)
14+
self.savedActivities = try container.decodeIfPresent([SavedActivity].self, forKey: .savedActivities) ?? []
15+
self.savedCurriculums = try container.decodeIfPresent([SavedCurriculum].self, forKey: .savedCurriculums) ?? []
16+
self.savedStories = try container.decodeIfPresent([SavedStory].self, forKey: .savedStories) ?? []
17+
self.savedGamepads = try container.decodeIfPresent([SavedGamepad].self, forKey: .savedGamepads) ?? []
18+
self.createdAt = try container.decodeIfPresent(Timestamp.self, forKey: .createdAt)?.dateValue()
19+
self.lastEditedAt = try container.decodeIfPresent(Timestamp.self, forKey: .lastEditedAt)?.dateValue()
20+
}
21+
22+
public func encode(to encoder: Encoder) throws {
23+
var container = encoder.container(keyedBy: CodingKeys.self)
24+
25+
try container.encodeIfPresent(self.id, forKey: .id)
26+
try container.encode(self.rootOwnerUid, forKey: .rootOwnerUid)
27+
try container.encode(self.savedActivities, forKey: .savedActivities)
28+
try container.encode(self.savedCurriculums, forKey: .savedCurriculums)
29+
try container.encode(self.savedStories, forKey: .savedStories)
30+
try container.encode(self.savedGamepads, forKey: .savedGamepads)
31+
try container.encodeIfPresent(self.createdAt.map { Timestamp(date: $0) }, forKey: .createdAt)
32+
try container.encodeIfPresent(self.lastEditedAt.map { Timestamp(date: $0) }, forKey: .lastEditedAt)
33+
}
34+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Leka - iOS Monorepo
2+
// Copyright APF France handicap
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
import SwiftUI
6+
7+
public extension RootAccount {
8+
init(from decoder: Decoder) throws {
9+
let container = try decoder.container(keyedBy: CodingKeys.self)
10+
self.id = try container.decodeIfPresent(String.self, forKey: .id)
11+
self.rootOwnerUid = try container.decode(String.self, forKey: .rootOwnerUid)
12+
self.library = try container.decodeIfPresent(Library.self, forKey: .library) ?? Library()
13+
self.createdAt = try container.decodeIfPresent(Date.self, forKey: .createdAt)
14+
self.lastEditedAt = try container.decodeIfPresent(Date.self, forKey: .lastEditedAt)
15+
}
16+
}

0 commit comments

Comments
 (0)