From cb2ae660561eedf31963f08b617c74868e1fb9e8 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 7 Oct 2024 12:53:38 +0300 Subject: [PATCH 01/99] =?UTF-8?q?=E2=9C=A8=20(LekaApp):=20Add=20Library+Ac?= =?UTF-8?q?tivitiesView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/MainView/MainView.swift | 3 +- .../Library+ActivitiesView.swift | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView.swift b/Apps/LekaApp/Sources/Views/MainView/MainView.swift index 20b5c29b8..d5b3b9354 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView.swift @@ -185,7 +185,7 @@ struct MainView: View { .navigationTitle("Curriculums") case .libraryActivities: - Text("Activities") + LibraryActivitiesView(viewModel: self.rootAccountViewModel) .navigationTitle("Activities") case .libraryStories: @@ -325,6 +325,7 @@ struct MainView: View { @ObservedObject private var styleManager: StyleManager = .shared @StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel() + @StateObject private var rootAccountViewModel = RootAccountManagerViewModel() private var persistentDataManager: PersistentDataManager = .shared private var caregiverManager: CaregiverManager = .shared diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift new file mode 100644 index 000000000..a2d96efdd --- /dev/null +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift @@ -0,0 +1,50 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import AccountKit +import ContentKit +import LocalizationKit +import SwiftUI + +// MARK: - PersonalLibraryActivitiesView + +struct LibraryActivitiesView: View { + // MARK: Lifecycle + + init(viewModel: RootAccountManagerViewModel) { + self.viewModel = viewModel + } + + // MARK: Internal + + var body: some View { + ScrollView(showsIndicators: true) { + ActivityListView(activities: self.activities) { activity in + self.navigation.currentActivity = activity + self.navigation.fullScreenCoverContent = .activityView(carereceivers: []) + } + } + } + + // MARK: Private + + @ObservedObject private var navigation: Navigation = .shared + @ObservedObject private var viewModel: RootAccountManagerViewModel + + private var activities: [Activity] { + self.viewModel.savedActivities.compactMap { savedActivity in + ContentKit.allPublishedActivities.first { $0.id == savedActivity.id } + } + .sorted { + $0.details.title.compare($1.details.title, locale: NSLocale.current) == .orderedAscending + } + } +} + +#Preview { + let viewModel = RootAccountManagerViewModel() + NavigationStack { + LibraryActivitiesView(viewModel: viewModel) + } +} From 791525b57486ef49ff90202995bdc21247e52cd5 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 7 Oct 2024 20:07:00 +0300 Subject: [PATCH 02/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20button?= =?UTF-8?q?=20to=20save/remove=20activity=20in=20DetailView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/ActivityDetailsView.swift | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift index 5d176a4f2..3db5a3511 100644 --- a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift @@ -2,6 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 +import AccountKit import DesignKit import Fit import LocalizationKit @@ -116,6 +117,27 @@ public struct ActivityDetailsView: View { } } .toolbar { + ToolbarItem { + Button { + let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" + if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { + self.rootAccountViewModel.removeSavedActivity(activityID: self.activity.uuid) + } else { + self.rootAccountViewModel.addSavedActivity( + activityID: self.activity.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } + } + .tint(self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) ? .red : self.styleManager.accentColor!) + } + ToolbarItem { Button { self.onStartActivity?(self.activity) @@ -141,6 +163,11 @@ public struct ActivityDetailsView: View { @State private var selectedAuthor: Author? @State private var selectedSkill: Skill? + + @ObservedObject private var styleManager: StyleManager = .shared + + @StateObject private var rootAccountViewModel = RootAccountManagerViewModel() + @StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel() } // MARK: - l10n.ActivityDetailsView From 95366a28600aa1bfbe1f7aecd471a5d6366ceb45 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 7 Oct 2024 22:06:51 +0300 Subject: [PATCH 03/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20btn=20t?= =?UTF-8?q?o=20save/remove=20in=20ActivityListView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/ActivityListView.swift | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Modules/ContentKit/Sources/Views/ActivityListView.swift b/Modules/ContentKit/Sources/Views/ActivityListView.swift index 6a43c7a97..3062713fe 100644 --- a/Modules/ContentKit/Sources/Views/ActivityListView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityListView.swift @@ -2,6 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 +import AccountKit import DesignKit import LocalizationKit import SwiftUI @@ -68,6 +69,25 @@ public struct ActivityListView: View { IconImageView(image: templateIconUIImage) } + Button { + let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" + if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { + self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) + } else { + self.rootAccountViewModel.addSavedActivity( + activityID: activity.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } + } + .tint(self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) ? .red : self.styleManager.accentColor!) + Button { self.onStartActivity?(activity) } label: { @@ -108,6 +128,9 @@ public struct ActivityListView: View { private let columns = Array(repeating: GridItem(), count: 3) @ObservedObject private var styleManager: StyleManager = .shared + + @StateObject private var rootAccountViewModel = RootAccountManagerViewModel() + @StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel() } // MARK: - l10n.ActivityListView From 4248ed22e230740d49a50cadb1dc6af97b0d292b Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 21 Oct 2024 17:33:07 +0300 Subject: [PATCH 04/99] =?UTF-8?q?=F0=9F=94=A5=20(ContentKit):=20Remove=20u?= =?UTF-8?q?nused=20properties=20&=20l10n=20from=20ActListView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ContentKit/Resources/Localizable.xcstrings | 18 ------------------ .../Sources/Views/ActivityListView.swift | 12 ------------ 2 files changed, 30 deletions(-) diff --git a/Modules/ContentKit/Resources/Localizable.xcstrings b/Modules/ContentKit/Resources/Localizable.xcstrings index 04534c112..9e40ae82c 100644 --- a/Modules/ContentKit/Resources/Localizable.xcstrings +++ b/Modules/ContentKit/Resources/Localizable.xcstrings @@ -92,24 +92,6 @@ } } }, - "content_kit.activity_list_view.start_activity_button_label": { - "comment": "Start activity button label on ActivityListView", - "extractionState": "extracted_with_value", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Start" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "D\u00e9marrer" - } - } - } - }, "content_kit.curriculum_details_view.activities_section_title": { "comment": "CurriculumDetailsView 'activities' section title", "extractionState": "extracted_with_value", diff --git a/Modules/ContentKit/Sources/Views/ActivityListView.swift b/Modules/ContentKit/Sources/Views/ActivityListView.swift index 3062713fe..b5351adf2 100644 --- a/Modules/ContentKit/Sources/Views/ActivityListView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityListView.swift @@ -126,24 +126,12 @@ public struct ActivityListView: View { } } - private let columns = Array(repeating: GridItem(), count: 3) @ObservedObject private var styleManager: StyleManager = .shared @StateObject private var rootAccountViewModel = RootAccountManagerViewModel() @StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel() } -// MARK: - l10n.ActivityListView - -extension l10n { - enum ActivityListView { - static let startActivityButtonLabel = LocalizedString("content_kit.activity_list_view.start_activity_button_label", - bundle: ContentKitResources.bundle, - value: "Start", - comment: "Start activity button label on ActivityListView") - } -} - #Preview { NavigationSplitView { Text("Sidebar") From c49000242d6572c54fcdfdd41da56eff68b226d4 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Wed, 23 Oct 2024 13:31:22 +0300 Subject: [PATCH 05/99] =?UTF-8?q?=E2=9C=A8=20(LekaApp):=20Add=20CategoryLi?= =?UTF-8?q?braryView=20w/=20loggedOut=20fallback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/l10n/Localizable.xcstrings | 36 ++++++++++++++++ .../Categories/CategoryLibraryView.swift | 41 +++++++++++++++++++ .../Views/MainView/MainView+l10n.swift | 6 +++ .../Sources/Views/MainView/MainView.swift | 14 +++---- 4 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift diff --git a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings index 4f09fb797..1f49bb759 100644 --- a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings +++ b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings @@ -1676,6 +1676,24 @@ } } }, + "lekaapp.main_view.detailView.disconnected_library_message": { + "comment": "The message to invite users to connect to display the Library", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Log in to your account to access your personal library." + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Connectez-vous \u00e0 votre compte pour acc\u00e9der \u00e0 votre biblioth\u00e8que personnelle." + } + } + } + }, "lekaapp.main_view.sidebar.category_label.activities": { "comment": "The title of the category 'Activities'", "extractionState": "extracted_with_value", @@ -1964,6 +1982,24 @@ } } }, + "lekaapp.main_view.sidebar.section.library": { + "comment": "The title of the section 'Library'", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Library" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Biblioth\u00e8que" + } + } + } + }, "lekaapp.main_view.sidebar.section.monitoring": { "comment": "The title of the section 'Users'", "extractionState": "extracted_with_value", diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift new file mode 100644 index 000000000..898ea4935 --- /dev/null +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift @@ -0,0 +1,41 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import AccountKit +import ContentKit +import LocalizationKit +import SwiftUI + +struct CategoryLibraryView: View { + @State var category: Navigation.Category + + var body: some View { + if self.authManagerViewModel.userAuthenticationState == .loggedIn { + switch self.category { + case .libraryCurriculums: + Text("Curriculums") + .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.curriculums.characters)) + case .libraryStories: + Text("Stories") + .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.stories.characters)) + case .libraryGamepads: + Text("Gamepads") + .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.gamepads.characters)) + default: + LibraryActivitiesView(viewModel: self.rootAccountViewModel) + .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.activities.characters)) + } + } else { + Text(String(l10n.MainView.DetailView.disconnectedLibraryMessage.characters)) + .navigationTitle(String(l10n.MainView.Sidebar.sectionLibrary.characters)) + } + } + + @StateObject private var rootAccountViewModel = RootAccountManagerViewModel() + @ObservedObject var authManagerViewModel = AuthManagerViewModel.shared +} + +#Preview { + CategoryLibraryView(category: .activities) +} diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift b/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift index 2311616c3..838391f3c 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift @@ -34,6 +34,12 @@ extension l10n { static let sectionContent = LocalizedString("lekaapp.main_view.sidebar.section.content", value: "Content", comment: "The title of the section 'Content'") static let sectionUsers = LocalizedString("lekaapp.main_view.sidebar.section.monitoring", value: "Users", comment: "The title of the section 'Users'") + + static let sectionLibrary = LocalizedString("lekaapp.main_view.sidebar.section.library", value: "Library", comment: "The title of the section 'Library'") + } + + enum DetailView { + static let disconnectedLibraryMessage = LocalizedString("lekaapp.main_view.detailView.disconnected_library_message", value: "Log in to your account to access your personal library.", comment: "The message to invite users to connect to display the Library") } } } diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView.swift b/Apps/LekaApp/Sources/Views/MainView/MainView.swift index d5b3b9354..06537d84c 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView.swift @@ -89,7 +89,7 @@ struct MainView: View { CategoryLabel(category: .news) } - Section("Library") { + Section(String(l10n.MainView.Sidebar.sectionLibrary.characters)) { CategoryLabel(category: .libraryCurriculums) CategoryLabel(category: .libraryActivities) CategoryLabel(category: .libraryStories) @@ -181,20 +181,16 @@ struct MainView: View { DiscoverLekaView(demoMode: self.navigation.demoMode) case .libraryCurriculums: - Text("Curriculums") - .navigationTitle("Curriculums") + CategoryLibraryView(category: .libraryCurriculums) case .libraryActivities: - LibraryActivitiesView(viewModel: self.rootAccountViewModel) - .navigationTitle("Activities") + CategoryLibraryView(category: .libraryActivities) case .libraryStories: - Text("Stories") - .navigationTitle("Stories") + CategoryLibraryView(category: .libraryStories) case .libraryGamepads: - Text("Gamepads") - .navigationTitle("Gamepads") + CategoryLibraryView(category: .libraryGamepads) case .none: Text(l10n.MainView.Sidebar.CategoryLabel.home) From 004135382014f7183b2efed0d3e183fa5a83365c Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 24 Oct 2024 20:39:38 +0200 Subject: [PATCH 06/99] =?UTF-8?q?=F0=9F=9A=B8=20(ContentKit):=20Hide=20+?= =?UTF-8?q?=20button=20when=20logged=20out?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/ActivityDetailsView.swift | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift index 3db5a3511..fa8cd38ea 100644 --- a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift @@ -117,25 +117,27 @@ public struct ActivityDetailsView: View { } } .toolbar { - ToolbarItem { - Button { - let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" - if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { - self.rootAccountViewModel.removeSavedActivity(activityID: self.activity.uuid) - } else { - self.rootAccountViewModel.addSavedActivity( - activityID: self.activity.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + ToolbarItem { + Button { + // let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" + if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { + self.rootAccountViewModel.removeSavedActivity(activityID: self.activity.uuid) + } else { + self.rootAccountViewModel.addSavedActivity( + activityID: self.activity.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) ? .red : self.styleManager.accentColor!) } ToolbarItem { From 03ba4b30bbd66ecb001c170913c99cbdd87c5920 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 21 Oct 2024 16:56:12 +0300 Subject: [PATCH 07/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20StoryLi?= =?UTF-8?q?stView=20to=20present=20Stories=20as=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/StoryListView.swift | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 Modules/ContentKit/Sources/Views/StoryListView.swift diff --git a/Modules/ContentKit/Sources/Views/StoryListView.swift b/Modules/ContentKit/Sources/Views/StoryListView.swift new file mode 100644 index 000000000..096ca549e --- /dev/null +++ b/Modules/ContentKit/Sources/Views/StoryListView.swift @@ -0,0 +1,121 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import AccountKit +import DesignKit +import LocalizationKit +import SwiftUI + +// MARK: - StoryListView + +public struct StoryListView: View { + // MARK: Lifecycle + + public init(stories: [Story]? = nil, onStartStory: ((Story) -> Void)?) { + self.stories = stories ?? [] + self.onStartStory = onStartStory + } + + // MARK: Public + + public var body: some View { + LazyVStack(alignment: .leading, spacing: 20) { + ForEach(self.stories) { story in + NavigationLink(destination: + StoryDetailsView(story: story, onStartStory: self.onStartStory) + ) { + HStack(alignment: .center, spacing: 30) { + Image(uiImage: story.details.iconImage) + .resizable() + .scaledToFit() + .clipShape(Circle()) + .frame(width: 50) + .overlay( + Circle() + .stroke(self.styleManager.accentColor!, lineWidth: 1) + ) + + VStack(alignment: .leading) { + HStack { + Text(story.details.title) + .font(.headline) + .frame(alignment: .leading) + } + + if let subtitle = story.details.subtitle { + Text(subtitle) + .font(.subheadline) + .frame(alignment: .leading) + } + } + .padding(.vertical) + + Spacer() + + Button { + let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" + if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { + self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) + } else { + self.rootAccountViewModel.addSavedStory( + storyID: story.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } + } + .tint(self.rootAccountViewModel.isStorySaved(storyID: story.uuid) ? .red : self.styleManager.accentColor!) + + Button { + self.onStartStory?(story) + } label: { + Image(systemName: "play.circle") + .font(.system(size: 24)) + .contentShape(Rectangle()) + } + .tint(.lkGreen) + } + .frame(maxWidth: .infinity, maxHeight: 120) + .contentShape(Rectangle()) + } + .buttonStyle(.plain) + } + } + .padding() + } + + // MARK: Internal + + let stories: [Story] + let onStartStory: ((Story) -> Void)? + + // MARK: Private + + @ObservedObject private var styleManager: StyleManager = .shared + + @StateObject private var rootAccountViewModel = RootAccountManagerViewModel() + @StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel() +} + +#Preview { + NavigationSplitView { + Text("Sidebar") + } detail: { + NavigationStack { + ScrollView { + StoryListView( + stories: ContentKit.allStories, + onStartStory: { _ in + print("Story Started") + } + ) + } + } + } +} From b1bc1e1b56b92b96079b7235d363ce82e758b85c Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 21 Oct 2024 17:01:08 +0300 Subject: [PATCH 08/99] =?UTF-8?q?=E2=9C=A8=20(LekaApp):=20Add=20LibrarySto?= =?UTF-8?q?riesView=20to=20CategoryLibraryView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Categories/CategoryLibraryView.swift | 2 +- .../PersonalLibrary/Library+StoriesView.swift | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift index 898ea4935..76b6cba4c 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift @@ -17,7 +17,7 @@ struct CategoryLibraryView: View { Text("Curriculums") .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.curriculums.characters)) case .libraryStories: - Text("Stories") + LibraryStoriesView(viewModel: self.rootAccountViewModel) .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.stories.characters)) case .libraryGamepads: Text("Gamepads") diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift new file mode 100644 index 000000000..ed0d16a9f --- /dev/null +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift @@ -0,0 +1,50 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import AccountKit +import ContentKit +import LocalizationKit +import SwiftUI + +// MARK: - LibraryStoriesView + +struct LibraryStoriesView: View { + // MARK: Lifecycle + + init(viewModel: RootAccountManagerViewModel) { + self.viewModel = viewModel + } + + // MARK: Internal + + var body: some View { + ScrollView(showsIndicators: true) { + StoryListView(stories: self.stories) { story in + self.navigation.currentStory = story + self.navigation.fullScreenCoverContent = .storyView(carereceivers: []) + } + } + } + + // MARK: Private + + @ObservedObject private var navigation: Navigation = .shared + @ObservedObject private var viewModel: RootAccountManagerViewModel + + private var stories: [Story] { + self.viewModel.savedStories.compactMap { savedStories in + ContentKit.allStories.first { $0.id == savedStories.id } + } + .sorted { + $0.details.title.compare($1.details.title, locale: NSLocale.current) == .orderedAscending + } + } +} + +#Preview { + let viewModel = RootAccountManagerViewModel() + NavigationStack { + LibraryStoriesView(viewModel: viewModel) + } +} From 15049eeec9ecf6597ccf5adbbca2ff2ad8968fda Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 21 Oct 2024 17:08:44 +0300 Subject: [PATCH 09/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20btn=20t?= =?UTF-8?q?o=20save/remove=20Story=20in=20StoryDetailView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/StoryDetailsView.swift | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift index 7f223fb58..fb7c9e76a 100644 --- a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift @@ -2,6 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 +import AccountKit import DesignKit import Fit import LocalizationKit @@ -107,6 +108,26 @@ public struct StoryDetailsView: View { } } .toolbar { + ToolbarItem { + Button { + let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" + if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { + self.rootAccountViewModel.removeSavedStory(storyID: self.story.uuid) + } else { + self.rootAccountViewModel.addSavedStory( + storyID: self.story.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } + } + .tint(self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) ? .red : self.styleManager.accentColor!) + } ToolbarItem { Button { self.onStartStory?(self.story) @@ -132,6 +153,11 @@ public struct StoryDetailsView: View { @State private var selectedAuthor: Author? @State private var selectedSkill: Skill? + + @ObservedObject private var styleManager: StyleManager = .shared + + @StateObject private var rootAccountViewModel = RootAccountManagerViewModel() + @StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel() } // MARK: - l10n.StoryDetailsView From b28dc9c4f89df12edd2b5e99add48c8071b042df Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Fri, 25 Oct 2024 09:09:07 +0300 Subject: [PATCH 10/99] =?UTF-8?q?=F0=9F=9A=B8=20(ContentKit):=20Hide=20+?= =?UTF-8?q?=20button=20when=20logged=20out=20in=20ActListView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/ActivityListView.swift | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/ActivityListView.swift b/Modules/ContentKit/Sources/Views/ActivityListView.swift index b5351adf2..2127653dd 100644 --- a/Modules/ContentKit/Sources/Views/ActivityListView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityListView.swift @@ -69,24 +69,25 @@ public struct ActivityListView: View { IconImageView(image: templateIconUIImage) } - Button { - let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" - if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { - self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) - } else { - self.rootAccountViewModel.addSavedActivity( - activityID: activity.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + Button { + if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { + self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) + } else { + self.rootAccountViewModel.addSavedActivity( + activityID: activity.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) ? .red : self.styleManager.accentColor!) Button { self.onStartActivity?(activity) From 798259afa53d2a57edf7f632f236c12c5f470a4a Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Fri, 25 Oct 2024 09:18:18 +0300 Subject: [PATCH 11/99] =?UTF-8?q?=F0=9F=9A=B8=20(ContentKit):=20Hide=20+?= =?UTF-8?q?=20button=20when=20logged=20out?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/StoryDetailsView.swift | 33 ++++++++++--------- .../Sources/Views/StoryListView.swift | 33 ++++++++++--------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift index fb7c9e76a..351be39cb 100644 --- a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift @@ -109,24 +109,25 @@ public struct StoryDetailsView: View { } .toolbar { ToolbarItem { - Button { - let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" - if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { - self.rootAccountViewModel.removeSavedStory(storyID: self.story.uuid) - } else { - self.rootAccountViewModel.addSavedStory( - storyID: self.story.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + Button { + if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { + self.rootAccountViewModel.removeSavedStory(storyID: self.story.uuid) + } else { + self.rootAccountViewModel.addSavedStory( + storyID: self.story.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) ? .red : self.styleManager.accentColor!) } ToolbarItem { Button { diff --git a/Modules/ContentKit/Sources/Views/StoryListView.swift b/Modules/ContentKit/Sources/Views/StoryListView.swift index 096ca549e..034af849f 100644 --- a/Modules/ContentKit/Sources/Views/StoryListView.swift +++ b/Modules/ContentKit/Sources/Views/StoryListView.swift @@ -53,24 +53,25 @@ public struct StoryListView: View { Spacer() - Button { - let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" - if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { - self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) - } else { - self.rootAccountViewModel.addSavedStory( - storyID: story.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + Button { + if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { + self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) + } else { + self.rootAccountViewModel.addSavedStory( + storyID: story.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isStorySaved(storyID: story.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isStorySaved(storyID: story.uuid) ? .red : self.styleManager.accentColor!) Button { self.onStartStory?(story) From 0cafa30e9742688ba74a1e9f2609ff3dc1fc33b5 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 21 Oct 2024 19:25:57 +0300 Subject: [PATCH 12/99] =?UTF-8?q?=E2=9C=A8=20(LekaApp):=20Add=20LibraryGam?= =?UTF-8?q?epadsView=20to=20CategoryLibraryView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Categories/CategoryLibraryView.swift | 2 +- .../Library+GamepadsView.swift | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 Apps/LekaApp/Sources/Views/PersonalLibrary/Library+GamepadsView.swift diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift index 76b6cba4c..c364141a2 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift @@ -20,7 +20,7 @@ struct CategoryLibraryView: View { LibraryStoriesView(viewModel: self.rootAccountViewModel) .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.stories.characters)) case .libraryGamepads: - Text("Gamepads") + LibraryGamepadsView() .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.gamepads.characters)) default: LibraryActivitiesView(viewModel: self.rootAccountViewModel) diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+GamepadsView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+GamepadsView.swift new file mode 100644 index 000000000..7c7188c89 --- /dev/null +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+GamepadsView.swift @@ -0,0 +1,45 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import AccountKit +import ContentKit +import LocalizationKit +import SwiftUI + +// MARK: - LibraryGamepadsView + +struct LibraryGamepadsView: View { + // MARK: Internal + + var body: some View { + VStack { + Spacer() + + GamepadGridView(gamepads: self.category.activities, onStartGamepad: { activity in + if self.authManagerViewModel.userAuthenticationState == .loggedIn, !self.navigation.demoMode { + self.navigation.sheetContent = .carereceiverPicker(activity: activity, story: nil) + } else { + self.navigation.currentActivity = activity + self.navigation.fullScreenCoverContent = .activityView(carereceivers: []) + } + }) + + Spacer() + } + .navigationTitle(self.category.details.title) + } + + // MARK: Private + + private let category: CategoryGamepads = .shared + + @ObservedObject private var authManagerViewModel: AuthManagerViewModel = .shared + @ObservedObject private var navigation: Navigation = .shared +} + +#Preview { + NavigationStack { + LibraryGamepadsView() + } +} From 75eb91d593af73117a2c8504652019a65d509bb6 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Thu, 24 Oct 2024 15:50:28 +0300 Subject: [PATCH 13/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20add/rem?= =?UTF-8?q?=20btn=20to=20CurriculumDetailsView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/CurriculumDetailsView.swift | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift index add9706c6..1cb155ff4 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift @@ -2,6 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 +import AccountKit import DesignKit import Fit import LocalizationKit @@ -140,6 +141,28 @@ public struct CurriculumDetailsView: View { } } } + .toolbar { + ToolbarItem { + Button { + let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + } else { + self.rootAccountViewModel.addSavedCurriculum( + curriculumID: self.curriculum.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } + } + .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) + } + } } // MARK: Internal @@ -154,6 +177,9 @@ public struct CurriculumDetailsView: View { @State private var selectedSkill: Skill? @State private var isDescriptionExpanded = false @ObservedObject private var styleManager: StyleManager = .shared + + @StateObject private var rootAccountViewModel = RootAccountManagerViewModel() + @StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel() } // MARK: - l10n.CurriculumDetailsView From 762fff6d8dee888461680a39546842370cd11295 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Thu, 24 Oct 2024 16:22:38 +0300 Subject: [PATCH 14/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20add/rem?= =?UTF-8?q?=20btn=20to=20CurriculumGroupboxView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/CurriculumGroupboxView.swift | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift index 90ab7d93a..32268254c 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift @@ -2,6 +2,8 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 +import AccountKit +import DesignKit import LocalizationKit import SwiftUI @@ -27,6 +29,25 @@ public struct CurriculumGroupboxView: View { .foregroundStyle(Color.secondary) Spacer() + + Button { + let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + } else { + self.rootAccountViewModel.addSavedCurriculum( + curriculumID: self.curriculum.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } + } + .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) } VStack(spacing: 10) { @@ -72,6 +93,11 @@ public struct CurriculumGroupboxView: View { // MARK: Private private let curriculum: Curriculum + + @ObservedObject private var styleManager: StyleManager = .shared + + @StateObject private var rootAccountViewModel = RootAccountManagerViewModel() + @StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel() } // MARK: - l10n.CurriculumGroupboxView From f54e50c77971378d21c511bd1f7a047cf77808a9 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Thu, 24 Oct 2024 17:07:06 +0300 Subject: [PATCH 15/99] =?UTF-8?q?=E2=9C=A8=20(LekaApp):=20Add=20LibraryCur?= =?UTF-8?q?riculumsView=20to=20CategoryLibraryView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Categories/CategoryLibraryView.swift | 2 +- .../Library+CurriculumsView.swift | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift index c364141a2..69f14edc6 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift @@ -14,7 +14,7 @@ struct CategoryLibraryView: View { if self.authManagerViewModel.userAuthenticationState == .loggedIn { switch self.category { case .libraryCurriculums: - Text("Curriculums") + LibraryCurriculumsView(viewModel: self.rootAccountViewModel) .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.curriculums.characters)) case .libraryStories: LibraryStoriesView(viewModel: self.rootAccountViewModel) diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift new file mode 100644 index 000000000..93a2d3d73 --- /dev/null +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift @@ -0,0 +1,45 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import AccountKit +import ContentKit +import LocalizationKit +import SwiftUI + +struct LibraryCurriculumsView: View { + // MARK: Lifecycle + + init(viewModel: RootAccountManagerViewModel) { + self.viewModel = viewModel + } + + // MARK: Internal + + var body: some View { + ScrollView(showsIndicators: true) { + CurriculumGridView(curriculums: self.curriculums) { _ in + // Nothing to do + } + } + } + + // MARK: Private + + @ObservedObject private var navigation: Navigation = .shared + @ObservedObject private var viewModel: RootAccountManagerViewModel + + private var curriculums: [Curriculum] { + self.viewModel.savedCurriculums.compactMap { savedCurriculums in + ContentKit.allCurriculums.first { $0.id == savedCurriculums.id } + } + .sorted { + $0.details.title.compare($1.details.title, locale: NSLocale.current) == .orderedAscending + } + } +} + +#Preview { + let viewModel = RootAccountManagerViewModel() + LibraryCurriculumsView(viewModel: viewModel) +} From 11d6298955e9c4e4f79ba8dedf4464e6171fabd5 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Fri, 25 Oct 2024 09:50:30 +0300 Subject: [PATCH 16/99] =?UTF-8?q?=F0=9F=9A=B8=20(ContentKit):=20Hide=20+?= =?UTF-8?q?=20button=20when=20logged=20out?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/CurriculumDetailsView.swift | 36 ++++++++++--------- .../Views/CurriculumGroupboxView.swift | 33 ++++++++--------- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift index 1cb155ff4..5c90304d7 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift @@ -142,25 +142,27 @@ public struct CurriculumDetailsView: View { } } .toolbar { - ToolbarItem { - Button { - let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) - } else { - self.rootAccountViewModel.addSavedCurriculum( - curriculumID: self.curriculum.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + ToolbarItem { + Button { + let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + } else { + self.rootAccountViewModel.addSavedCurriculum( + curriculumID: self.curriculum.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) } } } diff --git a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift index 32268254c..5f2d6a2ae 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift @@ -30,24 +30,25 @@ public struct CurriculumGroupboxView: View { Spacer() - Button { - let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) - } else { - self.rootAccountViewModel.addSavedCurriculum( - curriculumID: self.curriculum.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + Button { + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + } else { + self.rootAccountViewModel.addSavedCurriculum( + curriculumID: self.curriculum.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) } VStack(spacing: 10) { From b24b3750f4e1d341d2973aedc554809ef7bd64c3 Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Fri, 25 Oct 2024 09:49:33 +0200 Subject: [PATCH 17/99] =?UTF-8?q?=F0=9F=92=84=20(LekaApp):=20Justify=20lea?= =?UTF-8?q?ding=20section=20description?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/Categories/CategoryActivitiesView.swift | 4 +++- .../Sources/Views/Categories/CategoryCurriculumsView.swift | 3 ++- .../Sources/Views/Categories/CategoryGamepadsView.swift | 3 ++- .../Views/Categories/CategoryResourcesDeepDiveView.swift | 3 ++- .../Views/Categories/CategoryResourcesFirstStepView.swift | 3 ++- .../Views/Categories/CategoryResourcesVideosView.swift | 3 ++- .../Sources/Views/Categories/CategoryStoriesView.swift | 4 +++- 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryActivitiesView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryActivitiesView.swift index 391646e9b..5332c2665 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryActivitiesView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryActivitiesView.swift @@ -31,7 +31,9 @@ struct CategoryActivitiesView: View { .foregroundStyle(.secondary) } } - .padding(.horizontal) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 30) + .padding(.bottom) ActivityGridView(activities: self.category.activities, onStartActivity: { activity in if self.authManagerViewModel.userAuthenticationState == .loggedIn, !self.navigation.demoMode { diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryCurriculumsView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryCurriculumsView.swift index 2aab82041..a6b96efc8 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryCurriculumsView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryCurriculumsView.swift @@ -31,7 +31,8 @@ struct CategoryCurriculumsView: View { .foregroundStyle(.secondary) } } - .padding(.horizontal) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 30) .padding(.bottom) Spacer() diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryGamepadsView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryGamepadsView.swift index f6e7b6c8b..bf79af4c3 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryGamepadsView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryGamepadsView.swift @@ -30,7 +30,8 @@ struct CategoryGamepadsView: View { .foregroundStyle(.secondary) } } - .padding(.horizontal) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 30) .padding(.bottom) Spacer() diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesDeepDiveView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesDeepDiveView.swift index 7bca7d69a..30c4aeb78 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesDeepDiveView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesDeepDiveView.swift @@ -29,7 +29,8 @@ struct CategoryResourcesDeepDiveView: View { .foregroundStyle(.secondary) } } - .padding(.horizontal) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 30) .padding(.bottom) VStack(alignment: .leading, spacing: 30) { diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesFirstStepView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesFirstStepView.swift index 32a99126c..610278a7b 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesFirstStepView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesFirstStepView.swift @@ -29,7 +29,8 @@ struct CategoryResourcesFirstStepsView: View { .foregroundStyle(.secondary) } } - .padding(.horizontal) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 30) .padding(.bottom) VStack(alignment: .leading, spacing: 30) { diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesVideosView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesVideosView.swift index 613e61ae8..c5b504681 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesVideosView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryResourcesVideosView.swift @@ -29,7 +29,8 @@ struct CategoryResourcesVideosView: View { .foregroundStyle(.secondary) } } - .padding(.horizontal) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 30) .padding(.bottom) Spacer() diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryStoriesView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryStoriesView.swift index 73ba7ad1f..6fcee0926 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryStoriesView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryStoriesView.swift @@ -31,7 +31,9 @@ struct CategoryStoriesView: View { .foregroundStyle(.secondary) } } - .padding(.horizontal) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 30) + .padding(.bottom) StoryGridView(stories: self.category.stories, onStartStory: { story in if self.authManagerViewModel.userAuthenticationState == .loggedIn, !self.navigation.demoMode { From e0e2288cd8ee6bc58f241e426a057dcf77f6be34 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Fri, 25 Oct 2024 11:22:18 +0200 Subject: [PATCH 18/99] =?UTF-8?q?=F0=9F=91=B7=20(workflows):=20Add=20workf?= =?UTF-8?q?low=20to=20cancel=20ongoing=20workflows=20on=20PR=20closed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ci-tools-cancel_workflows_on_pr_closed.yml | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml diff --git a/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml b/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml new file mode 100644 index 000000000..aa6ea3aaf --- /dev/null +++ b/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml @@ -0,0 +1,45 @@ +name: Cancel Workflows on PR Close + +on: + pull_request: + types: [closed] + +jobs: + cancel-workflows: + runs-on: ubuntu-latest + permissions: + actions: write # Ensure we have permission to cancel workflows + steps: + - name: Cancel Running Workflows + uses: actions/github-script@v7 + with: + script: | + const prNumber = context.payload.pull_request.number; + const { owner, repo } = context.repo; + const currentRunId = context.runId; // Get current workflow run ID + + // Fetch all in-progress workflow runs triggered by pull requests + const runs = await github.paginate( + github.rest.actions.listWorkflowRunsForRepo, + { + owner, + repo, + event: 'pull_request', + status: 'in_progress', + } + ); + + // Cancel runs associated with the closed PR, excluding the current run + for (const run of runs) { + if ( + run.id !== currentRunId && // Exclude current run + run.pull_requests.some(pr => pr.number === prNumber) + ) { + await github.rest.actions.cancelWorkflowRun({ + owner, + repo, + run_id: run.id, + }); + console.log(`Cancelled workflow run: ${run.id}`); + } + } From ccd9b9a8d2e169ac88eb86aa807f5a9116f39eb9 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Fri, 25 Oct 2024 11:50:01 +0200 Subject: [PATCH 19/99] =?UTF-8?q?=F0=9F=91=B7=20(worflows):=20Improve=20ca?= =?UTF-8?q?ncel=20on=20PR=20closed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ci-tools-cancel_workflows_on_pr_closed.yml | 78 +++++++++++++------ 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml b/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml index aa6ea3aaf..fab93f777 100644 --- a/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml +++ b/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml @@ -1,3 +1,7 @@ +# Leka - iOS Monorepo +# Copyright APF France handicap +# SPDX-License-Identifier: Apache-2.0 + name: Cancel Workflows on PR Close on: @@ -8,38 +12,62 @@ jobs: cancel-workflows: runs-on: ubuntu-latest permissions: - actions: write # Ensure we have permission to cancel workflows + actions: write + pull-requests: read steps: - - name: Cancel Running Workflows + - name: Cancel Running Workflows Based on Commit SHA uses: actions/github-script@v7 with: script: | const prNumber = context.payload.pull_request.number; + const prHeadSha = context.payload.pull_request.head.sha; const { owner, repo } = context.repo; - const currentRunId = context.runId; // Get current workflow run ID - - // Fetch all in-progress workflow runs triggered by pull requests - const runs = await github.paginate( - github.rest.actions.listWorkflowRunsForRepo, - { - owner, - repo, - event: 'pull_request', - status: 'in_progress', - } - ); + const currentRunId = context.runId; + + console.log(`PR Number: ${prNumber}`); + console.log(`PR Head SHA: ${prHeadSha}`); + console.log(`Current Run ID: ${currentRunId}`); + + // Fetch all in-progress and queued workflow runs + const statuses = ['in_progress', 'queued', 'requested', 'waiting', 'pending']; + let runs = []; + + for (const status of statuses) { + const response = await github.rest.actions.listWorkflowRunsForRepo({ + owner: owner, + repo: repo, + status: status, + per_page: 100, + head_sha: prHeadSha, + }); + runs = runs.concat(response.data.workflow_runs); + } + + console.log(`Total in-progress or queued runs: ${runs.length}`); + + runs.forEach(run => { + const runInfo = [ + ` - ID: ${run.id}`, + ` Name: ${run.name}`, + ` Head SHA: ${run.head_sha}`, + ` Event: ${run.event}`, + ` Status: ${run.status}` + ]; + console.log(runInfo.join('\n')); + }); - // Cancel runs associated with the closed PR, excluding the current run + // Cancel runs associated with the closed PR based on head SHA, excluding the current run for (const run of runs) { - if ( - run.id !== currentRunId && // Exclude current run - run.pull_requests.some(pr => pr.number === prNumber) - ) { - await github.rest.actions.cancelWorkflowRun({ - owner, - repo, - run_id: run.id, - }); - console.log(`Cancelled workflow run: ${run.id}`); + if (run.id !== currentRunId && run.head_sha === prHeadSha) { + try { + await github.rest.actions.cancelWorkflowRun({ + owner, + repo, + run_id: run.id, + }); + console.log(`Cancelled workflow run: ${run.id}`); + } catch (error) { + console.error(`Failed to cancel workflow run: ${run.id}. Error: ${error.message}`); + } } } From 374ff7903638b828adfdb7db5add6a232c294e6d Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Fri, 25 Oct 2024 15:36:45 +0200 Subject: [PATCH 20/99] =?UTF-8?q?=F0=9F=91=B7=20(workflows):=20Cancel=20wo?= =?UTF-8?q?rkflows=20on=20PR=20labeled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ci-tools-cancel_workflows_on_pr_closed.yml | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml b/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml index fab93f777..19d0bbc4e 100644 --- a/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml +++ b/.github/workflows/ci-tools-cancel_workflows_on_pr_closed.yml @@ -2,11 +2,11 @@ # Copyright APF France handicap # SPDX-License-Identifier: Apache-2.0 -name: Cancel Workflows on PR Close +name: Cancel Workflows on PR Close or Label on: pull_request: - types: [closed] + types: [closed, labeled] jobs: cancel-workflows: @@ -15,15 +15,42 @@ jobs: actions: write pull-requests: read steps: - - name: Cancel Running Workflows Based on Commit SHA + - name: Cancel Running Workflows Based on Event uses: actions/github-script@v7 with: script: | - const prNumber = context.payload.pull_request.number; - const prHeadSha = context.payload.pull_request.head.sha; const { owner, repo } = context.repo; + const eventName = context.eventName; + const action = context.payload.action; const currentRunId = context.runId; + let prNumber; + let prHeadSha; + + if (eventName === 'pull_request' && action === 'closed') { + // Event triggered by PR closure + prNumber = context.payload.pull_request.number; + prHeadSha = context.payload.pull_request.head.sha; + console.log(`Triggered by pull_request 'closed' event for PR #${prNumber}`); + } else if (eventName === 'pull_request' && action === 'labeled') { + // Event triggered by label addition + prNumber = context.payload.pull_request.number; + const labelName = context.payload.label.name; + console.log(`Triggered by pull_request 'labeled' event for PR #${prNumber}`); + console.log(`Label added: "${labelName}"`); + + // Check if the label matches the one we're interested in + if (labelName !== '🛑️ cancel workflows') { + console.log('Label does not match. Exiting.'); + return; + } + + prHeadSha = context.payload.pull_request.head.sha; + } else { + console.log('Unsupported event type or action. Exiting.'); + return; + } + console.log(`PR Number: ${prNumber}`); console.log(`PR Head SHA: ${prHeadSha}`); console.log(`Current Run ID: ${currentRunId}`); @@ -56,7 +83,7 @@ jobs: console.log(runInfo.join('\n')); }); - // Cancel runs associated with the closed PR based on head SHA, excluding the current run + // Cancel runs associated with the PR's head SHA, excluding the current run for (const run of runs) { if (run.id !== currentRunId && run.head_sha === prHeadSha) { try { From 6e76beb598135f45a8915352d1834a5f5df6dbbd Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Fri, 25 Oct 2024 16:17:52 +0200 Subject: [PATCH 21/99] =?UTF-8?q?=F0=9F=93=A6=EF=B8=8F=20(ios-monorepo):?= =?UTF-8?q?=20Add=20AppUpdately=20package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This package checks for new update of our app --- Apps/LekaApp/Project.swift | 1 + Tuist/Package.resolved | 9 +++++++++ Tuist/Package.swift | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/Apps/LekaApp/Project.swift b/Apps/LekaApp/Project.swift index 80eea391a..e2920dab0 100644 --- a/Apps/LekaApp/Project.swift +++ b/Apps/LekaApp/Project.swift @@ -44,6 +44,7 @@ let project = Project.app( .project(target: "RobotKit", path: Path("../../Modules/RobotKit")), .project(target: "UtilsKit", path: Path("../../Modules/UtilsKit")), + .external(name: "AppUpdately"), .external(name: "DeviceKit"), .external(name: "Fit"), .external(name: "MarkdownUI"), diff --git a/Tuist/Package.resolved b/Tuist/Package.resolved index 0d7bb6e11..5c457c8ae 100644 --- a/Tuist/Package.resolved +++ b/Tuist/Package.resolved @@ -18,6 +18,15 @@ "version" : "11.0.1" } }, + { + "identity" : "appupdately", + "kind" : "remoteSourceControl", + "location" : "https://github.com/AvdLee/AppUpdately", + "state" : { + "branch" : "main", + "revision" : "697c19e356241dcd097adde7f51398bdf18bf1ca" + } + }, { "identity" : "audiokit", "kind" : "remoteSourceControl", diff --git a/Tuist/Package.swift b/Tuist/Package.swift index b4ee0e47e..14d6c719f 100644 --- a/Tuist/Package.swift +++ b/Tuist/Package.swift @@ -70,6 +70,10 @@ let package = Package( url: "https://github.com/lukepistrol/SFSymbolsMacro", exact: "0.5.2" ), + .package( + url: "https://github.com/AvdLee/AppUpdately", + branch: "main" + ), ] ) From 7dc8ab77bfce759e51ad16c8c877bd0936904dd3 Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Fri, 25 Oct 2024 16:19:58 +0200 Subject: [PATCH 22/99] =?UTF-8?q?=F0=9F=9A=B8=20(LekaApp):=20Display=20ale?= =?UTF-8?q?rt=20when=20update=20is=20available?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/l10n/Localizable.xcstrings | 54 +++++++++++++++ Apps/LekaApp/Sources/MainApp.swift | 67 +++++++++++++++++-- 2 files changed, 117 insertions(+), 4 deletions(-) diff --git a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings index 1f49bb759..2700ee967 100644 --- a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings +++ b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings @@ -1676,6 +1676,60 @@ } } }, + "lekaapp.main_app.update_alert.action": { + "comment": "The action button of the alert to inform the user that an update is available", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Update now" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Mettre \u00e0 jour maintenant" + } + } + } + }, + "lekaapp.main_app.update_alert.message": { + "comment": "The message of the alert to inform the user that an update is available", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Enjoy new features by updating to the latest version of Leka!" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Profitez des nouvelles fonctionnalit\u00e9s en t\u00e9l\u00e9chargeant la nouvelle mise \u00e0 jour de l\u2019app Leka !" + } + } + } + }, + "lekaapp.main_app.update_alert.title": { + "comment": "The title of the alert to inform the user that an update is available", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "New update available" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Nouvelle mise \u00e0 jour disponible" + } + } + } + }, "lekaapp.main_view.detailView.disconnected_library_message": { "comment": "The message to invite users to connect to display the Library", "extractionState": "extracted_with_value", diff --git a/Apps/LekaApp/Sources/MainApp.swift b/Apps/LekaApp/Sources/MainApp.swift index 6ef0abc21..faa157cf7 100644 --- a/Apps/LekaApp/Sources/MainApp.swift +++ b/Apps/LekaApp/Sources/MainApp.swift @@ -3,9 +3,12 @@ // SPDX-License-Identifier: Apache-2.0 import AccountKit +import AppUpdately +import Combine import ContentKit import DesignKit import FirebaseCore +import LocalizationKit import LogKit import SwiftUI @@ -73,11 +76,50 @@ struct LekaApp: App { } } .animation(.default, value: self.showMainView) - .onAppear { - DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { - self.showMainView = true + #if PRODUCTION_BUILD + .onAppear { + var cancellable: AnyCancellable? + cancellable = UpdateStatusFetcher().fetch { result in + defer { cancellable?.cancel() } + guard let status = try? result.get() else { return } + + switch status { + case .upToDate, + .newerVersion: + DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { + self.showMainView = true + } + case .updateAvailable: + self.showingUpdateAlert = true + } + } } - } + .alert(isPresented: self.$showingUpdateAlert) { + Alert( + title: Text(l10n.MainApp.UpdateAlert.title), + message: Text(l10n.MainApp.UpdateAlert.message), + primaryButton: .default(Text(l10n.MainApp.UpdateAlert.action), action: { + if let url = URL(string: "https://apps.apple.com/app/leka/id6446940339") { + UIApplication.shared.open(url) + } + DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { + self.showMainView = true + } + }), + secondaryButton: .cancel { + DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { + self.showMainView = true + } + } + ) + } + #else + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { + self.showMainView = true + } + } + #endif } } @@ -85,6 +127,7 @@ struct LekaApp: App { @State private var loaderOpacity: Double = 1.0 @State private var showMainView: Bool = false + @State private var showingUpdateAlert: Bool = false } // MARK: - LoadingView @@ -110,6 +153,22 @@ struct LoadingView: View { } } +// MARK: - l10n.MainApp + +// swiftlint:disable nesting + +extension l10n { + enum MainApp { + enum UpdateAlert { + static let title = LocalizedString("lekaapp.main_app.update_alert.title", value: "New update available", comment: "The title of the alert to inform the user that an update is available") + static let message = LocalizedString("lekaapp.main_app.update_alert.message", value: "Enjoy new features by updating to the latest version of Leka!", comment: "The message of the alert to inform the user that an update is available") + static let action = LocalizedString("lekaapp.main_app.update_alert.action", value: "Update now", comment: "The action button of the alert to inform the user that an update is available") + } + } +} + +// swiftlint:enable nesting + #Preview { LoadingView() } From 0b05757d5522ab69e43222067d87a6e551324213 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Fri, 25 Oct 2024 17:21:20 +0200 Subject: [PATCH 23/99] =?UTF-8?q?=F0=9F=92=84=20(ContentKit):=20Update=20g?= =?UTF-8?q?esture=20icons=20for=20tts=20and=20dnd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accessibility/gesture/drag_and_drop.gesture.icon.png | 4 ++-- .../accessibility/gesture/touch_to_select.gesture.icon.png | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/ContentKit/Resources/Content/accessibility/gesture/drag_and_drop.gesture.icon.png b/Modules/ContentKit/Resources/Content/accessibility/gesture/drag_and_drop.gesture.icon.png index f366e9d2f..3b822bf7e 100644 --- a/Modules/ContentKit/Resources/Content/accessibility/gesture/drag_and_drop.gesture.icon.png +++ b/Modules/ContentKit/Resources/Content/accessibility/gesture/drag_and_drop.gesture.icon.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a2f011317d3304710bb1c43c64b62a3bc571aed2297caaeeb2637a3976897939 -size 4730 +oid sha256:93e11e62338494719501496bb8203ae83119894c1ad86a75dee756e6c8abfb52 +size 7100 diff --git a/Modules/ContentKit/Resources/Content/accessibility/gesture/touch_to_select.gesture.icon.png b/Modules/ContentKit/Resources/Content/accessibility/gesture/touch_to_select.gesture.icon.png index c898d0137..cb2818186 100644 --- a/Modules/ContentKit/Resources/Content/accessibility/gesture/touch_to_select.gesture.icon.png +++ b/Modules/ContentKit/Resources/Content/accessibility/gesture/touch_to_select.gesture.icon.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58eec6cacc9b8006381987de01da371de4649595a0aa2045bbee71285b8a4497 -size 3984 +oid sha256:471b4e13efaa465672dd10ce1fda1be2878f34c7782bc8fdd63768fc0505e297 +size 8217 From 98441b38fcb1e225f2875e64f3a3b6eab16367ac Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sat, 26 Oct 2024 16:38:43 +0300 Subject: [PATCH 24/99] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20(Cont?= =?UTF-8?q?entKit):=20Move=20+=20to=20Library=20btn=20to=20DeveloperMode?= =?UTF-8?q?=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/ActivityDetailsView.swift | 39 +++++++++--------- .../Sources/Views/ActivityListView.swift | 37 ++++++++--------- .../Sources/Views/CurriculumDetailsView.swift | 40 ++++++++++--------- .../Views/CurriculumGroupboxView.swift | 36 +++++++++-------- .../Sources/Views/StoryDetailsView.swift | 38 +++++++++--------- .../Sources/Views/StoryListView.swift | 36 +++++++++-------- 6 files changed, 118 insertions(+), 108 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift index fa8cd38ea..466d84a5f 100644 --- a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift @@ -117,28 +117,29 @@ public struct ActivityDetailsView: View { } } .toolbar { - if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - ToolbarItem { - Button { - // let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" - if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { - self.rootAccountViewModel.removeSavedActivity(activityID: self.activity.uuid) - } else { - self.rootAccountViewModel.addSavedActivity( - activityID: self.activity.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + #if DEVELOPER_MODE || TESTFLIGHT_BUILD + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + ToolbarItem { + Button { + if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { + self.rootAccountViewModel.removeSavedActivity(activityID: self.activity.uuid) + } else { + self.rootAccountViewModel.addSavedActivity( + activityID: self.activity.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) ? .red : self.styleManager.accentColor!) } - } + #endif ToolbarItem { Button { diff --git a/Modules/ContentKit/Sources/Views/ActivityListView.swift b/Modules/ContentKit/Sources/Views/ActivityListView.swift index 2127653dd..2916ace5d 100644 --- a/Modules/ContentKit/Sources/Views/ActivityListView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityListView.swift @@ -68,26 +68,27 @@ public struct ActivityListView: View { if let templateIconUIImage = ContentKit.getTemplateIconUIImage(for: activity) { IconImageView(image: templateIconUIImage) } - - if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Button { - if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { - self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) - } else { - self.rootAccountViewModel.addSavedActivity( - activityID: activity.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + #if DEVELOPER_MODE || TESTFLIGHT_BUILD + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + Button { + if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { + self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) + } else { + self.rootAccountViewModel.addSavedActivity( + activityID: activity.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) ? .red : self.styleManager.accentColor!) - } + #endif Button { self.onStartActivity?(activity) diff --git a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift index 5c90304d7..702c558e8 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift @@ -142,28 +142,30 @@ public struct CurriculumDetailsView: View { } } .toolbar { - if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - ToolbarItem { - Button { - let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) - } else { - self.rootAccountViewModel.addSavedCurriculum( - curriculumID: self.curriculum.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + #if DEVELOPER_MODE || TESTFLIGHT_BUILD + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + ToolbarItem { + Button { + let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + } else { + self.rootAccountViewModel.addSavedCurriculum( + curriculumID: self.curriculum.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) } - } + #endif } } diff --git a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift index 5f2d6a2ae..14a2fad0a 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift @@ -30,25 +30,27 @@ public struct CurriculumGroupboxView: View { Spacer() - if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Button { - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) - } else { - self.rootAccountViewModel.addSavedCurriculum( - curriculumID: self.curriculum.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + #if DEVELOPER_MODE || TESTFLIGHT_BUILD + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + Button { + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + } else { + self.rootAccountViewModel.addSavedCurriculum( + curriculumID: self.curriculum.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) - } + #endif } VStack(spacing: 10) { diff --git a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift index 351be39cb..7b1ae81e2 100644 --- a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift @@ -108,27 +108,29 @@ public struct StoryDetailsView: View { } } .toolbar { - ToolbarItem { - if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Button { - if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { - self.rootAccountViewModel.removeSavedStory(storyID: self.story.uuid) - } else { - self.rootAccountViewModel.addSavedStory( - storyID: self.story.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + #if DEVELOPER_MODE || TESTFLIGHT_BUILD + ToolbarItem { + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + Button { + if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { + self.rootAccountViewModel.removeSavedStory(storyID: self.story.uuid) + } else { + self.rootAccountViewModel.addSavedStory( + storyID: self.story.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) ? .red : self.styleManager.accentColor!) } - } + #endif ToolbarItem { Button { self.onStartStory?(self.story) diff --git a/Modules/ContentKit/Sources/Views/StoryListView.swift b/Modules/ContentKit/Sources/Views/StoryListView.swift index 034af849f..d58e48f37 100644 --- a/Modules/ContentKit/Sources/Views/StoryListView.swift +++ b/Modules/ContentKit/Sources/Views/StoryListView.swift @@ -53,25 +53,27 @@ public struct StoryListView: View { Spacer() - if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Button { - if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { - self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) - } else { - self.rootAccountViewModel.addSavedStory( - storyID: story.uuid, - caregiverID: currentCaregiverID - ) - } - } label: { - if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + #if DEVELOPER_MODE || TESTFLIGHT_BUILD + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + Button { + if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { + self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) + } else { + self.rootAccountViewModel.addSavedStory( + storyID: story.uuid, + caregiverID: currentCaregiverID + ) + } + } label: { + if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { + Image(systemName: "trash") + } else { + Image(systemName: "plus") + } } + .tint(self.rootAccountViewModel.isStorySaved(storyID: story.uuid) ? .red : self.styleManager.accentColor!) } - .tint(self.rootAccountViewModel.isStorySaved(storyID: story.uuid) ? .red : self.styleManager.accentColor!) - } + #endif Button { self.onStartStory?(story) From d50158921d945bb413fa5c799bec4fffbffe4af0 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sat, 26 Oct 2024 19:32:45 +0300 Subject: [PATCH 25/99] =?UTF-8?q?=F0=9F=92=84=20(DesignKit):=20Add=20Libra?= =?UTF-8?q?ry's=20TranslucentButtonStyle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/TranslucentButtonStyle.swift | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Modules/DesignKit/Sources/TranslucentButtonStyle.swift diff --git a/Modules/DesignKit/Sources/TranslucentButtonStyle.swift b/Modules/DesignKit/Sources/TranslucentButtonStyle.swift new file mode 100644 index 000000000..0b1a063d6 --- /dev/null +++ b/Modules/DesignKit/Sources/TranslucentButtonStyle.swift @@ -0,0 +1,35 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import SwiftUI + +public struct TranslucentButtonStyle: ButtonStyle { + // MARK: Lifecycle + + public init(color: Color, isExpanded: Bool = false) { + self.color = color + self.isExpanded = isExpanded + } + + // MARK: Public + + public let color: Color + public var isExpanded: Bool + + public func makeBody(configuration: Configuration) -> some View { + configuration.label + .font(.system(size: 13)) + .padding(8) + .frame(maxWidth: self.isExpanded ? .infinity : 28) + .frame(height: 28) + .background( + Capsule() + .fill(Color.primary.opacity(0.1)) + ) + .foregroundColor(self.color) + .opacity(configuration.isPressed ? 0.5 : 1.0) + .animation(.easeInOut(duration: 0.2), value: configuration.isPressed) + .animation(.easeInOut(duration: 0.3), value: self.isExpanded) + } +} From 3086a8ceac0b239e37479e15d666588f44b61280 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sat, 26 Oct 2024 20:16:16 +0300 Subject: [PATCH 26/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20Library?= =?UTF-8?q?=20Menu=20btn=20to=20ActivityListView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/ActivityListView.swift | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/ActivityListView.swift b/Modules/ContentKit/Sources/Views/ActivityListView.swift index 2916ace5d..57fc8c514 100644 --- a/Modules/ContentKit/Sources/Views/ActivityListView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityListView.swift @@ -68,25 +68,34 @@ public struct ActivityListView: View { if let templateIconUIImage = ContentKit.getTemplateIconUIImage(for: activity) { IconImageView(image: templateIconUIImage) } + #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Button { + Menu { if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { - self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) + Button(role: .destructive) { + self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) + } label: { + Label("Remove Activity", systemImage: "trash") + } } else { - self.rootAccountViewModel.addSavedActivity( - activityID: activity.uuid, - caregiverID: currentCaregiverID - ) + Button { + self.rootAccountViewModel.addSavedActivity( + activityID: activity.uuid, + caregiverID: currentCaregiverID + ) + } label: { + Label("Add Activity", systemImage: "plus") + } } } label: { - if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + Button { + // Nothing to do + } label: { + Image(systemName: "ellipsis") } + .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } - .tint(self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) ? .red : self.styleManager.accentColor!) } #endif From ce26d04b51c5c18feb26947e7d931a12abc17a56 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sat, 26 Oct 2024 20:19:59 +0300 Subject: [PATCH 27/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20Library?= =?UTF-8?q?=20Menu=20btn=20to=20StoryListView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/StoryListView.swift | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/StoryListView.swift b/Modules/ContentKit/Sources/Views/StoryListView.swift index d58e48f37..bc57aaac3 100644 --- a/Modules/ContentKit/Sources/Views/StoryListView.swift +++ b/Modules/ContentKit/Sources/Views/StoryListView.swift @@ -55,23 +55,31 @@ public struct StoryListView: View { #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Button { + Menu { if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { - self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) + Button(role: .destructive) { + self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) + } label: { + Label("Remove Story", systemImage: "trash") + } } else { - self.rootAccountViewModel.addSavedStory( - storyID: story.uuid, - caregiverID: currentCaregiverID - ) + Button { + self.rootAccountViewModel.addSavedStory( + storyID: story.uuid, + caregiverID: currentCaregiverID + ) + } label: { + Label("Add Story", systemImage: "plus") + } } } label: { - if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + Button { + // Nothing to do + } label: { + Image(systemName: "ellipsis") } + .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } - .tint(self.rootAccountViewModel.isStorySaved(storyID: story.uuid) ? .red : self.styleManager.accentColor!) } #endif From 4ae298c69220a5c5550071d1419740ca369a0ab3 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sat, 26 Oct 2024 20:22:20 +0300 Subject: [PATCH 28/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20Library?= =?UTF-8?q?=20Menu=20btn=20to=20CurriculumGroupboxView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/CurriculumGroupboxView.swift | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift index 14a2fad0a..0974b4277 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift @@ -32,23 +32,31 @@ public struct CurriculumGroupboxView: View { #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Button { + Menu { if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + Button(role: .destructive) { + self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + } label: { + Label("Remove Curriculum", systemImage: "trash") + } } else { - self.rootAccountViewModel.addSavedCurriculum( - curriculumID: self.curriculum.uuid, - caregiverID: currentCaregiverID - ) + Button { + self.rootAccountViewModel.addSavedCurriculum( + curriculumID: self.curriculum.uuid, + caregiverID: currentCaregiverID + ) + } label: { + Label("Add Curriculum", systemImage: "plus") + } } } label: { - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + Button { + // Nothing to do + } label: { + Image(systemName: "ellipsis") } + .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } - .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) } #endif } From 048abc67a75f977ae7fa9d46544cbf4dffc2973e Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sat, 26 Oct 2024 21:50:28 +0300 Subject: [PATCH 29/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20Library?= =?UTF-8?q?=20Menu=20btn=20to=20ActivityDetailView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/ActivityDetailsView.swift | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift index 466d84a5f..11859883c 100644 --- a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift @@ -120,23 +120,31 @@ public struct ActivityDetailsView: View { #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { ToolbarItem { - Button { + Menu { if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { - self.rootAccountViewModel.removeSavedActivity(activityID: self.activity.uuid) + Button(role: .destructive) { + self.rootAccountViewModel.removeSavedActivity(activityID: self.activity.uuid) + } label: { + Label("Remove Activity", systemImage: "trash") + } } else { - self.rootAccountViewModel.addSavedActivity( - activityID: self.activity.uuid, - caregiverID: currentCaregiverID - ) + Button { + self.rootAccountViewModel.addSavedActivity( + activityID: self.activity.uuid, + caregiverID: currentCaregiverID + ) + } label: { + Label("Add Activity", systemImage: "plus") + } } } label: { - if self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + Button { + // Nothing to do + } label: { + Image(systemName: "ellipsis") } + .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } - .tint(self.rootAccountViewModel.isActivitySaved(activityID: self.activity.uuid) ? .red : self.styleManager.accentColor!) } } #endif From 034a65fb90b4a965b0656f3c6d10c8ad5fb7341d Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sun, 27 Oct 2024 17:12:35 +0200 Subject: [PATCH 30/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20Library?= =?UTF-8?q?=20Menu=20btn=20to=20StoryDetailView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/StoryDetailsView.swift | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift index 7b1ae81e2..65a3c456d 100644 --- a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift @@ -109,28 +109,37 @@ public struct StoryDetailsView: View { } .toolbar { #if DEVELOPER_MODE || TESTFLIGHT_BUILD - ToolbarItem { - if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Button { + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + ToolbarItem { + Menu { if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { - self.rootAccountViewModel.removeSavedStory(storyID: self.story.uuid) + Button(role: .destructive) { + self.rootAccountViewModel.removeSavedStory(storyID: self.story.uuid) + } label: { + Label("Remove Story", systemImage: "trash") + } } else { - self.rootAccountViewModel.addSavedStory( - storyID: self.story.uuid, - caregiverID: currentCaregiverID - ) + Button { + self.rootAccountViewModel.addSavedStory( + storyID: self.story.uuid, + caregiverID: currentCaregiverID + ) + } label: { + Label("Add Story", systemImage: "plus") + } } } label: { - if self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + Button { + // Nothing to do + } label: { + Image(systemName: "ellipsis") } + .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } - .tint(self.rootAccountViewModel.isStorySaved(storyID: self.story.uuid) ? .red : self.styleManager.accentColor!) } } #endif + ToolbarItem { Button { self.onStartStory?(self.story) From e8fde566ff75fc92ce7e14d09e43ebf963e9bc9c Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sun, 27 Oct 2024 17:15:32 +0200 Subject: [PATCH 31/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20Library?= =?UTF-8?q?=20Menu=20btn=20to=20CurriculumDetailsView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/CurriculumDetailsView.swift | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift index 702c558e8..4e3cae4f3 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift @@ -145,24 +145,31 @@ public struct CurriculumDetailsView: View { #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { ToolbarItem { - Button { - let currentCaregiverID: String = self.caregiverManagerViewModel.currentCaregiver?.id ?? "" + Menu { if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + Button(role: .destructive) { + self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + } label: { + Label("Remove Curriculum", systemImage: "trash") + } } else { - self.rootAccountViewModel.addSavedCurriculum( - curriculumID: self.curriculum.uuid, - caregiverID: currentCaregiverID - ) + Button { + self.rootAccountViewModel.addSavedCurriculum( + curriculumID: self.curriculum.uuid, + caregiverID: currentCaregiverID + ) + } label: { + Label("Add Curriculum", systemImage: "plus") + } } } label: { - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - Image(systemName: "trash") - } else { - Image(systemName: "plus") + Button { + // Nothing to do + } label: { + Image(systemName: "ellipsis") } + .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } - .tint(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? .red : self.styleManager.accentColor!) } } #endif From 9df8599bd72d13f13aef6932ace286943c5538da Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Mon, 28 Oct 2024 11:18:47 +0100 Subject: [PATCH 32/99] =?UTF-8?q?=F0=9F=92=AC=20(ContentKit):=20Update=20a?= =?UTF-8?q?dd/remove=20content=20label?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modules/ContentKit/Sources/Views/ActivityDetailsView.swift | 4 ++-- Modules/ContentKit/Sources/Views/ActivityListView.swift | 4 ++-- Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift | 4 ++-- Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift | 4 ++-- Modules/ContentKit/Sources/Views/StoryDetailsView.swift | 4 ++-- Modules/ContentKit/Sources/Views/StoryListView.swift | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift index 11859883c..ed3805300 100644 --- a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift @@ -125,7 +125,7 @@ public struct ActivityDetailsView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedActivity(activityID: self.activity.uuid) } label: { - Label("Remove Activity", systemImage: "trash") + Label("Delete from Library", systemImage: "trash") } } else { Button { @@ -134,7 +134,7 @@ public struct ActivityDetailsView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add Activity", systemImage: "plus") + Label("Add to Library", systemImage: "plus") } } } label: { diff --git a/Modules/ContentKit/Sources/Views/ActivityListView.swift b/Modules/ContentKit/Sources/Views/ActivityListView.swift index 57fc8c514..c9bdc6aeb 100644 --- a/Modules/ContentKit/Sources/Views/ActivityListView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityListView.swift @@ -76,7 +76,7 @@ public struct ActivityListView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) } label: { - Label("Remove Activity", systemImage: "trash") + Label("Delete from Library", systemImage: "trash") } } else { Button { @@ -85,7 +85,7 @@ public struct ActivityListView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add Activity", systemImage: "plus") + Label("Add to Library", systemImage: "plus") } } } label: { diff --git a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift index 4e3cae4f3..0fe17bb4f 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift @@ -150,7 +150,7 @@ public struct CurriculumDetailsView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) } label: { - Label("Remove Curriculum", systemImage: "trash") + Label("Delete from Library", systemImage: "trash") } } else { Button { @@ -159,7 +159,7 @@ public struct CurriculumDetailsView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add Curriculum", systemImage: "plus") + Label("Add to Library", systemImage: "plus") } } } label: { diff --git a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift index 0974b4277..8a2dd7d07 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift @@ -37,7 +37,7 @@ public struct CurriculumGroupboxView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) } label: { - Label("Remove Curriculum", systemImage: "trash") + Label("Delete from Library", systemImage: "trash") } } else { Button { @@ -46,7 +46,7 @@ public struct CurriculumGroupboxView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add Curriculum", systemImage: "plus") + Label("Add to Library", systemImage: "plus") } } } label: { diff --git a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift index 65a3c456d..b26110633 100644 --- a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift @@ -116,7 +116,7 @@ public struct StoryDetailsView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedStory(storyID: self.story.uuid) } label: { - Label("Remove Story", systemImage: "trash") + Label("Delete from Library", systemImage: "trash") } } else { Button { @@ -125,7 +125,7 @@ public struct StoryDetailsView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add Story", systemImage: "plus") + Label("Add to Library", systemImage: "plus") } } } label: { diff --git a/Modules/ContentKit/Sources/Views/StoryListView.swift b/Modules/ContentKit/Sources/Views/StoryListView.swift index bc57aaac3..446739497 100644 --- a/Modules/ContentKit/Sources/Views/StoryListView.swift +++ b/Modules/ContentKit/Sources/Views/StoryListView.swift @@ -60,7 +60,7 @@ public struct StoryListView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) } label: { - Label("Remove Story", systemImage: "trash") + Label("Delete from Library", systemImage: "trash") } } else { Button { @@ -69,7 +69,7 @@ public struct StoryListView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add Story", systemImage: "plus") + Label("Add to Library", systemImage: "plus") } } } label: { From 8d813dbe22ed60789a6848c21d46efbe1dfeb906 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Mon, 28 Oct 2024 12:28:13 +0100 Subject: [PATCH 33/99] =?UTF-8?q?=F0=9F=90=9B=20(ContentKit):=20Curriculum?= =?UTF-8?q?GroupBox=20-=20fix=20menu=20button=20press=20in=20simulator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/CurriculumGroupboxView.swift | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift index 8a2dd7d07..f7358aae0 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift @@ -32,31 +32,30 @@ public struct CurriculumGroupboxView: View { #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Menu { - if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { - Button(role: .destructive) { - self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + Button {} + label: { + Menu { + if self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) { + Button(role: .destructive) { + self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) + } label: { + Label("Delete from Library", systemImage: "trash") + } + } else { + Button { + self.rootAccountViewModel.addSavedCurriculum( + curriculumID: self.curriculum.uuid, + caregiverID: currentCaregiverID + ) + } label: { + Label("Add to Library", systemImage: "plus") + } + } } label: { - Label("Delete from Library", systemImage: "trash") + Image(systemName: "ellipsis") } - } else { - Button { - self.rootAccountViewModel.addSavedCurriculum( - curriculumID: self.curriculum.uuid, - caregiverID: currentCaregiverID - ) - } label: { - Label("Add to Library", systemImage: "plus") - } - } - } label: { - Button { - // Nothing to do - } label: { - Image(systemName: "ellipsis") + .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } - .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) - } } #endif } From 6575146a561022ccdee50a44af8d4b93dc72b04d Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Mon, 28 Oct 2024 12:35:16 +0100 Subject: [PATCH 34/99] =?UTF-8?q?=F0=9F=90=9B=20(ContentKit):=20AcitivityL?= =?UTF-8?q?istView=20-=20fix=20menu=20button=20press=20in=20simulator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/ActivityListView.swift | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/ActivityListView.swift b/Modules/ContentKit/Sources/Views/ActivityListView.swift index c9bdc6aeb..07d984bd4 100644 --- a/Modules/ContentKit/Sources/Views/ActivityListView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityListView.swift @@ -71,26 +71,24 @@ public struct ActivityListView: View { #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Menu { - if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { - Button(role: .destructive) { - self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) - } label: { - Label("Delete from Library", systemImage: "trash") + Button {} label: { + Menu { + if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { + Button(role: .destructive) { + self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) + } label: { + Label("Delete from Library", systemImage: "trash") + } + } else { + Button { + self.rootAccountViewModel.addSavedActivity( + activityID: activity.uuid, + caregiverID: currentCaregiverID + ) + } label: { + Label("Add to Library", systemImage: "plus") + } } - } else { - Button { - self.rootAccountViewModel.addSavedActivity( - activityID: activity.uuid, - caregiverID: currentCaregiverID - ) - } label: { - Label("Add to Library", systemImage: "plus") - } - } - } label: { - Button { - // Nothing to do } label: { Image(systemName: "ellipsis") } From 9022d4398480fa6bf772e77f020f5e2bdacb26ca Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Mon, 28 Oct 2024 12:35:45 +0100 Subject: [PATCH 35/99] =?UTF-8?q?=F0=9F=90=9B=20(ContentKit):=20StoryListV?= =?UTF-8?q?iew=20-=20fix=20menu=20button=20press=20in=20simulator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/StoryListView.swift | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/StoryListView.swift b/Modules/ContentKit/Sources/Views/StoryListView.swift index 446739497..aa5b94d38 100644 --- a/Modules/ContentKit/Sources/Views/StoryListView.swift +++ b/Modules/ContentKit/Sources/Views/StoryListView.swift @@ -55,31 +55,30 @@ public struct StoryListView: View { #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { - Menu { - if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { - Button(role: .destructive) { - self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) + Button {} + label: { + Menu { + if self.rootAccountViewModel.isStorySaved(storyID: story.uuid) { + Button(role: .destructive) { + self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) + } label: { + Label("Delete from Library", systemImage: "trash") + } + } else { + Button { + self.rootAccountViewModel.addSavedStory( + storyID: story.uuid, + caregiverID: currentCaregiverID + ) + } label: { + Label("Add to Library", systemImage: "plus") + } + } } label: { - Label("Delete from Library", systemImage: "trash") + Image(systemName: "ellipsis") } - } else { - Button { - self.rootAccountViewModel.addSavedStory( - storyID: story.uuid, - caregiverID: currentCaregiverID - ) - } label: { - Label("Add to Library", systemImage: "plus") - } - } - } label: { - Button { - // Nothing to do - } label: { - Image(systemName: "ellipsis") + .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } - .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) - } } #endif From c08a9cd4ce19647cbe8effd232c4ea287c72be1f Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Mon, 28 Oct 2024 14:59:47 +0100 Subject: [PATCH 36/99] =?UTF-8?q?=F0=9F=9A=B8=20(ContentKit):=20Curriculum?= =?UTF-8?q?GroupBox=20-=20add=20check=20mark=20when=20curr=20is=20added=20?= =?UTF-8?q?to=20library?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/CurriculumGroupboxView.swift | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift index f7358aae0..11ee2cdd8 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift @@ -81,19 +81,25 @@ public struct CurriculumGroupboxView: View { Spacer() - HStack(alignment: .center) { - Spacer() + ZStack { + HStack { + Image(systemName: "checkmark.circle.fill") + .font(.title3) + .foregroundStyle(Color.secondary) + .opacity(self.rootAccountViewModel.isCurriculumSaved(curriculumID: self.curriculum.uuid) ? 1 : 0) + + Spacer() + + Image(systemName: "chevron.right") + .font(.title3) + .foregroundStyle(Color.secondary) + } Text(l10n.CurriculumGroupboxView.activityCountLabel(self.curriculum.activities.count)) .font(.caption.bold()) .foregroundStyle(Color.secondary) - - Spacer() - - Image(systemName: "chevron.right") - .font(.title3) - .foregroundStyle(Color.secondary) } + .frame(maxWidth: .infinity) } } .frame(width: 280) From 8662d5a1dd472156a0c9d957e45b819b027f134c Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Mon, 28 Oct 2024 15:04:44 +0100 Subject: [PATCH 37/99] =?UTF-8?q?=F0=9F=92=84=20(ContentKit):=20Make=20eli?= =?UTF-8?q?psis=20bold?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modules/ContentKit/Sources/Views/ActivityDetailsView.swift | 1 + Modules/ContentKit/Sources/Views/ActivityListView.swift | 1 + Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift | 1 + Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift | 1 + Modules/ContentKit/Sources/Views/StoryDetailsView.swift | 1 + Modules/ContentKit/Sources/Views/StoryListView.swift | 1 + 6 files changed, 6 insertions(+) diff --git a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift index ed3805300..7a38b0afc 100644 --- a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift @@ -142,6 +142,7 @@ public struct ActivityDetailsView: View { // Nothing to do } label: { Image(systemName: "ellipsis") + .bold() } .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } diff --git a/Modules/ContentKit/Sources/Views/ActivityListView.swift b/Modules/ContentKit/Sources/Views/ActivityListView.swift index 07d984bd4..b3b676401 100644 --- a/Modules/ContentKit/Sources/Views/ActivityListView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityListView.swift @@ -91,6 +91,7 @@ public struct ActivityListView: View { } } label: { Image(systemName: "ellipsis") + .bold() } .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } diff --git a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift index 0fe17bb4f..264b4677e 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift @@ -167,6 +167,7 @@ public struct CurriculumDetailsView: View { // Nothing to do } label: { Image(systemName: "ellipsis") + .bold() } .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } diff --git a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift index 11ee2cdd8..826d9b52e 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift @@ -53,6 +53,7 @@ public struct CurriculumGroupboxView: View { } } label: { Image(systemName: "ellipsis") + .bold() } .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } diff --git a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift index b26110633..fd6fed7ea 100644 --- a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift @@ -133,6 +133,7 @@ public struct StoryDetailsView: View { // Nothing to do } label: { Image(systemName: "ellipsis") + .bold() } .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } diff --git a/Modules/ContentKit/Sources/Views/StoryListView.swift b/Modules/ContentKit/Sources/Views/StoryListView.swift index aa5b94d38..da9890478 100644 --- a/Modules/ContentKit/Sources/Views/StoryListView.swift +++ b/Modules/ContentKit/Sources/Views/StoryListView.swift @@ -76,6 +76,7 @@ public struct StoryListView: View { } } label: { Image(systemName: "ellipsis") + .bold() } .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) } From 483f7eca9e22cbec3c6f776737e0a191f32a7370 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 28 Oct 2024 16:49:30 +0100 Subject: [PATCH 38/99] =?UTF-8?q?=F0=9F=8C=90=20(LekaApp):=20Add=20Library?= =?UTF-8?q?=20Categories=20sidebar=20l10n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/l10n/Localizable.xcstrings | 72 +++++++++++++++++++ .../Views/MainView/MainView+l10n.swift | 4 ++ 2 files changed, 76 insertions(+) diff --git a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings index 2700ee967..20f5d4f00 100644 --- a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings +++ b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings @@ -1856,6 +1856,78 @@ } } }, + "lekaapp.main_view.sidebar.category_label.library_activities": { + "comment": "The title of the category 'Library Activities'", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Activities" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Activit\u00e9s" + } + } + } + }, + "lekaapp.main_view.sidebar.category_label.library_curriculums": { + "comment": "The title of the category 'Library Curriculums'", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Curriculums" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Parcours" + } + } + } + }, + "lekaapp.main_view.sidebar.category_label.library_gamepads": { + "comment": "The title of the category 'Library Gamepads'", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Gamepads" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Manettes" + } + } + } + }, + "lekaapp.main_view.sidebar.category_label.library_stories": { + "comment": "The title of the category 'Library Stories'", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Stories" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Histoires" + } + } + } + }, "lekaapp.main_view.sidebar.category_label.news": { "comment": "The title of the category 'News'", "extractionState": "extracted_with_value", diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift b/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift index 838391f3c..ad7e22f1f 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift @@ -23,6 +23,10 @@ extension l10n { static let caregivers = LocalizedString("lekaapp.main_view.sidebar.category_label.caregivers", value: "Caregivers", comment: "The title of the category 'Caregivers'") static let carereceivers = LocalizedString("lekaapp.main_view.sidebar.category_label.carereceivers", value: "Care Receivers", comment: "The title of the category 'Care Receivers'") static let none = LocalizedString("lekaapp.main_view.sidebar.category_label.none", value: "Select a category", comment: "The title of the category 'none'") + static let libraryCurriculums = LocalizedString("lekaapp.main_view.sidebar.category_label.library_curriculums", value: "Curriculums", comment: "The title of the category 'Library Curriculums'") + static let libraryActivities = LocalizedString("lekaapp.main_view.sidebar.category_label.library_activities", value: "Activities", comment: "The title of the category 'Library Activities'") + static let libraryGamepads = LocalizedString("lekaapp.main_view.sidebar.category_label.library_gamepads", value: "Gamepads", comment: "The title of the category 'Library Gamepads'") + static let libraryStories = LocalizedString("lekaapp.main_view.sidebar.category_label.library_stories", value: "Stories", comment: "The title of the category 'Library Stories'") } static let navigationTitle = LocalizedString("lekaapp.main_view.sidebar.navigation_title", value: "Leka App", comment: "The title of the sidebar") From 180d07e2d26029969ec1336c678eda3dee57e9fb Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 28 Oct 2024 17:30:48 +0100 Subject: [PATCH 39/99] =?UTF-8?q?=F0=9F=8C=90=20(ContentKit):=20Add=20l10n?= =?UTF-8?q?=20for=20Library=20Menu=20Actions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/Localizable.xcstrings | 36 +++++++++++++++++++ .../Sources/Views/Library+l10n.swift | 21 +++++++++++ 2 files changed, 57 insertions(+) create mode 100644 Modules/ContentKit/Sources/Views/Library+l10n.swift diff --git a/Modules/ContentKit/Resources/Localizable.xcstrings b/Modules/ContentKit/Resources/Localizable.xcstrings index 9e40ae82c..e5dae47e0 100644 --- a/Modules/ContentKit/Resources/Localizable.xcstrings +++ b/Modules/ContentKit/Resources/Localizable.xcstrings @@ -277,6 +277,42 @@ } } }, + "content_kit.library_menu_actions.add_to_library_button_label": { + "comment": "Add to library button label", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Add to Library" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Ajouter \u00e0 la Biblioth\u00e8que" + } + } + } + }, + "content_kit.library_menu_actions.remove_from_library_button_label": { + "comment": "Remove from library button label", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Delete from Library" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Supprimer de la Biblioth\u00e8que" + } + } + } + }, "content_kit.sample_activity_list_view.start_activity_button_label": { "comment": "Start activity button label on Sample Activity List view", "extractionState": "extracted_with_value", diff --git a/Modules/ContentKit/Sources/Views/Library+l10n.swift b/Modules/ContentKit/Sources/Views/Library+l10n.swift new file mode 100644 index 000000000..4cee7fe95 --- /dev/null +++ b/Modules/ContentKit/Sources/Views/Library+l10n.swift @@ -0,0 +1,21 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import LocalizationKit + +extension l10n { + enum Library { + enum MenuActions { + static let addTolibraryButtonLabel = LocalizedString("content_kit.library_menu_actions.add_to_library_button_label", + bundle: ContentKitResources.bundle, + value: "Add to Library", + comment: "Add to library button label") + + static let removeFromlibraryButtonLabel = LocalizedString("content_kit.library_menu_actions.remove_from_library_button_label", + bundle: ContentKitResources.bundle, + value: "Delete from Library", + comment: "Remove from library button label") + } + } +} From 8be694df75944f0bf0aa0d582c2a5676090c7d44 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Mon, 28 Oct 2024 17:36:08 +0100 Subject: [PATCH 40/99] =?UTF-8?q?=F0=9F=8C=90=20(ContentKit):=20Add=20l10n?= =?UTF-8?q?=20on=20all=20Library=20Menu=20Buttons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modules/ContentKit/Sources/Views/ActivityDetailsView.swift | 4 ++-- Modules/ContentKit/Sources/Views/ActivityListView.swift | 4 ++-- Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift | 4 ++-- Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift | 4 ++-- Modules/ContentKit/Sources/Views/StoryDetailsView.swift | 4 ++-- Modules/ContentKit/Sources/Views/StoryListView.swift | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift index 7a38b0afc..ed573455b 100644 --- a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift @@ -125,7 +125,7 @@ public struct ActivityDetailsView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedActivity(activityID: self.activity.uuid) } label: { - Label("Delete from Library", systemImage: "trash") + Label(String(l10n.Library.MenuActions.removeFromlibraryButtonLabel.characters), systemImage: "trash") } } else { Button { @@ -134,7 +134,7 @@ public struct ActivityDetailsView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add to Library", systemImage: "plus") + Label(String(l10n.Library.MenuActions.addTolibraryButtonLabel.characters), systemImage: "plus") } } } label: { diff --git a/Modules/ContentKit/Sources/Views/ActivityListView.swift b/Modules/ContentKit/Sources/Views/ActivityListView.swift index b3b676401..2fa972875 100644 --- a/Modules/ContentKit/Sources/Views/ActivityListView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityListView.swift @@ -77,7 +77,7 @@ public struct ActivityListView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) } label: { - Label("Delete from Library", systemImage: "trash") + Label(String(l10n.Library.MenuActions.removeFromlibraryButtonLabel.characters), systemImage: "trash") } } else { Button { @@ -86,7 +86,7 @@ public struct ActivityListView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add to Library", systemImage: "plus") + Label(String(l10n.Library.MenuActions.addTolibraryButtonLabel.characters), systemImage: "plus") } } } label: { diff --git a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift index 264b4677e..94f6371a3 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift @@ -150,7 +150,7 @@ public struct CurriculumDetailsView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) } label: { - Label("Delete from Library", systemImage: "trash") + Label(String(l10n.Library.MenuActions.removeFromlibraryButtonLabel.characters), systemImage: "trash") } } else { Button { @@ -159,7 +159,7 @@ public struct CurriculumDetailsView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add to Library", systemImage: "plus") + Label(String(l10n.Library.MenuActions.addTolibraryButtonLabel.characters), systemImage: "plus") } } } label: { diff --git a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift index 826d9b52e..1693e36e9 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumGroupboxView.swift @@ -39,7 +39,7 @@ public struct CurriculumGroupboxView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedCurriculum(curriculumID: self.curriculum.uuid) } label: { - Label("Delete from Library", systemImage: "trash") + Label(String(l10n.Library.MenuActions.removeFromlibraryButtonLabel.characters), systemImage: "trash") } } else { Button { @@ -48,7 +48,7 @@ public struct CurriculumGroupboxView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add to Library", systemImage: "plus") + Label(String(l10n.Library.MenuActions.addTolibraryButtonLabel.characters), systemImage: "plus") } } } label: { diff --git a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift index fd6fed7ea..51250e433 100644 --- a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift @@ -116,7 +116,7 @@ public struct StoryDetailsView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedStory(storyID: self.story.uuid) } label: { - Label("Delete from Library", systemImage: "trash") + Label(String(l10n.Library.MenuActions.removeFromlibraryButtonLabel.characters), systemImage: "trash") } } else { Button { @@ -125,7 +125,7 @@ public struct StoryDetailsView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add to Library", systemImage: "plus") + Label(String(l10n.Library.MenuActions.addTolibraryButtonLabel.characters), systemImage: "plus") } } } label: { diff --git a/Modules/ContentKit/Sources/Views/StoryListView.swift b/Modules/ContentKit/Sources/Views/StoryListView.swift index da9890478..1a538546d 100644 --- a/Modules/ContentKit/Sources/Views/StoryListView.swift +++ b/Modules/ContentKit/Sources/Views/StoryListView.swift @@ -62,7 +62,7 @@ public struct StoryListView: View { Button(role: .destructive) { self.rootAccountViewModel.removeSavedStory(storyID: story.uuid) } label: { - Label("Delete from Library", systemImage: "trash") + Label(String(l10n.Library.MenuActions.removeFromlibraryButtonLabel.characters), systemImage: "trash") } } else { Button { @@ -71,7 +71,7 @@ public struct StoryListView: View { caregiverID: currentCaregiverID ) } label: { - Label("Add to Library", systemImage: "plus") + Label(String(l10n.Library.MenuActions.addTolibraryButtonLabel.characters), systemImage: "plus") } } } label: { From 9916e9603aebd7145b30905a9a3d8684f8c3fe32 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sun, 27 Oct 2024 19:13:07 +0200 Subject: [PATCH 41/99] =?UTF-8?q?=E2=9C=A8=20(LekaApp):=20Add=20message=20?= =?UTF-8?q?to=20LibraryActivitiesView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library+ActivitiesView.swift | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift index a2d96efdd..92859046d 100644 --- a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift @@ -19,10 +19,19 @@ struct LibraryActivitiesView: View { // MARK: Internal var body: some View { - ScrollView(showsIndicators: true) { - ActivityListView(activities: self.activities) { activity in - self.navigation.currentActivity = activity - self.navigation.fullScreenCoverContent = .activityView(carereceivers: []) + if self.activities.isEmpty { + Text(""" + Your haven't saved any activity yet. + Tap the \(Image(systemName: "ellipsis.circle")) button on any activity to add it here. + You can then remove them from the Library using the same button. + """) + .multilineTextAlignment(.center) + } else { + ScrollView(showsIndicators: true) { + ActivityListView(activities: self.activities) { activity in + self.navigation.currentActivity = activity + self.navigation.fullScreenCoverContent = .activityView(carereceivers: []) + } } } } From 9aa2f1220c4751e8ff2c8f722980913887a7aa30 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sun, 27 Oct 2024 19:14:52 +0200 Subject: [PATCH 42/99] =?UTF-8?q?=E2=9C=A8=20(LekaApp):=20Add=20message=20?= =?UTF-8?q?to=20LibraryCurriculumsView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PersonalLibrary/Library+CurriculumsView.swift | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift index 93a2d3d73..2070f5825 100644 --- a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift @@ -17,9 +17,18 @@ struct LibraryCurriculumsView: View { // MARK: Internal var body: some View { - ScrollView(showsIndicators: true) { - CurriculumGridView(curriculums: self.curriculums) { _ in - // Nothing to do + if self.curriculums.isEmpty { + Text(""" + Your haven't saved any curriculum yet. + Tap the \(Image(systemName: "ellipsis.circle")) button on any curriculum to add it here. + You can then remove them from the Library using the same button. + """) + .multilineTextAlignment(.center) + } else { + ScrollView(showsIndicators: true) { + CurriculumGridView(curriculums: self.curriculums) { _ in + // Nothing to do + } } } } From 5fc6f8e495f861a1d8b2a3bfcf70da673b6d345a Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sun, 27 Oct 2024 19:16:40 +0200 Subject: [PATCH 43/99] =?UTF-8?q?=E2=9C=A8=20(LekaApp):=20Add=20message=20?= =?UTF-8?q?to=20LibraryStoriesView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PersonalLibrary/Library+StoriesView.swift | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift index ed0d16a9f..ae7de269f 100644 --- a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift @@ -19,10 +19,19 @@ struct LibraryStoriesView: View { // MARK: Internal var body: some View { - ScrollView(showsIndicators: true) { - StoryListView(stories: self.stories) { story in - self.navigation.currentStory = story - self.navigation.fullScreenCoverContent = .storyView(carereceivers: []) + if self.stories.isEmpty { + Text(""" + Your haven't saved any story yet. + Tap the \(Image(systemName: "ellipsis.circle")) button on any story to add it here. + You can then remove them from the Library using the same button. + """) + .multilineTextAlignment(.center) + } else { + ScrollView(showsIndicators: true) { + StoryListView(stories: self.stories) { story in + self.navigation.currentStory = story + self.navigation.fullScreenCoverContent = .storyView(carereceivers: []) + } } } } From 64a2745c762b955d8c47a0bd61b42e64e62a5590 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 30 Oct 2024 00:14:31 +0100 Subject: [PATCH 44/99] =?UTF-8?q?=E2=9C=A8=20(ContentKit):=20Add=20EmptyLi?= =?UTF-8?q?braryPlaceholderView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/l10n/Localizable.xcstrings | 72 ++++++++++++ .../EmptyLibraryPlaceholderView.swift | 105 ++++++++++++++++++ .../Library+ActivitiesView.swift | 7 +- .../Library+CurriculumsView.swift | 7 +- .../PersonalLibrary/Library+StoriesView.swift | 7 +- 5 files changed, 180 insertions(+), 18 deletions(-) create mode 100644 Apps/LekaApp/Sources/Views/PersonalLibrary/EmptyLibraryPlaceholderView.swift diff --git a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings index 20f5d4f00..380693e7f 100644 --- a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings +++ b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings @@ -1550,6 +1550,78 @@ } } }, + "lekaapp.empty_library_placedholder_view.button_instruction": { + "comment": "Instruction suffix", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "button on any activity, curriculum, or story to add them to your Library." + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "dans n'importe quelle activit\u00e9, parcours ou histoire pour les ajouter \u00e0 votre Biblioth\u00e8que." + } + } + } + }, + "lekaapp.empty_library_placedholder_view.library_is_empty": { + "comment": "Empty library title", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Your Library is Empty" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Votre Biblioth\u00e8que est vide" + } + } + } + }, + "lekaapp.empty_library_placedholder_view.remove_items": { + "comment": "Removal instruction", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "You can remove items from your Library using the same button." + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Vous pouvez supprimer des \u00e9l\u00e9ments de votre Biblioth\u00e8que en utilisant le m\u00eame bouton." + } + } + } + }, + "lekaapp.empty_library_placedholder_view.tap_the": { + "comment": "Instruction prefix", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Tap the" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Appuyez sur le bouton" + } + } + } + }, "lekaapp.forgot_password_view.context_message": { "comment": "Forgot Password View context message", "extractionState": "extracted_with_value", diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/EmptyLibraryPlaceholderView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/EmptyLibraryPlaceholderView.swift new file mode 100644 index 000000000..4e33466a8 --- /dev/null +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/EmptyLibraryPlaceholderView.swift @@ -0,0 +1,105 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import LocalizationKit +import SwiftUI + +// MARK: - EmptyLibraryPlaceholderView + +struct EmptyLibraryPlaceholderView: View { + // MARK: Lifecycle + + init(icon: Icon) { + self.icon = icon + } + + // MARK: Internal + + enum Icon { + case activities + case curriculums + case stories + + // MARK: Internal + + var systemName: String { + switch self { + case .activities: + "dice" + case .curriculums: + "graduationcap" + case .stories: + "text.book.closed" + } + } + } + + var body: some View { + VStack(alignment: .center, spacing: 16) { + Image(systemName: self.icon.systemName) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 100, height: 100) + .foregroundColor(.accentColor) + .padding(.bottom, 16) + + Text(l10n.EmptyLibraryPlaceholderView.libraryIsEmpty) + .font(.headline) + + HStack(spacing: 4) { + Text(l10n.EmptyLibraryPlaceholderView.tapThe) + .font(.subheadline) + .foregroundColor(.secondary) + Image(systemName: "ellipsis.circle") + .foregroundColor(.accentColor) + .accessibility(label: Text("More Options")) + Text(l10n.EmptyLibraryPlaceholderView.buttonInstruction) + .font(.subheadline) + .foregroundColor(.secondary) + } + .multilineTextAlignment(.center) + + Text(l10n.EmptyLibraryPlaceholderView.removeItems) + .font(.subheadline) + .foregroundColor(.secondary) + .multilineTextAlignment(.center) + } + .padding() + } + + // MARK: Private + + private let icon: Icon +} + +// MARK: - l10n.EmptyLibraryPlaceholderView + +extension l10n { + enum EmptyLibraryPlaceholderView { + static let libraryIsEmpty = LocalizedString( + "lekaapp.empty_library_placedholder_view.library_is_empty", + value: "Your Library is Empty", + comment: "Empty library title" + ) + static let tapThe = LocalizedString( + "lekaapp.empty_library_placedholder_view.tap_the", + value: "Tap the", + comment: "Instruction prefix" + ) + static let buttonInstruction = LocalizedString( + "lekaapp.empty_library_placedholder_view.button_instruction", + value: "button on any activity, curriculum, or story to add them to your Library.", + comment: "Instruction suffix" + ) + static let removeItems = LocalizedString( + "lekaapp.empty_library_placedholder_view.remove_items", + value: "You can remove items from your Library using the same button.", + comment: "Removal instruction" + ) + } +} + +#Preview { + EmptyLibraryPlaceholderView(icon: .stories) +} diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift index 92859046d..bcfd05abe 100644 --- a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift @@ -20,12 +20,7 @@ struct LibraryActivitiesView: View { var body: some View { if self.activities.isEmpty { - Text(""" - Your haven't saved any activity yet. - Tap the \(Image(systemName: "ellipsis.circle")) button on any activity to add it here. - You can then remove them from the Library using the same button. - """) - .multilineTextAlignment(.center) + EmptyLibraryPlaceholderView(icon: .activities) } else { ScrollView(showsIndicators: true) { ActivityListView(activities: self.activities) { activity in diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift index 2070f5825..00a26caa0 100644 --- a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+CurriculumsView.swift @@ -18,12 +18,7 @@ struct LibraryCurriculumsView: View { var body: some View { if self.curriculums.isEmpty { - Text(""" - Your haven't saved any curriculum yet. - Tap the \(Image(systemName: "ellipsis.circle")) button on any curriculum to add it here. - You can then remove them from the Library using the same button. - """) - .multilineTextAlignment(.center) + EmptyLibraryPlaceholderView(icon: .curriculums) } else { ScrollView(showsIndicators: true) { CurriculumGridView(curriculums: self.curriculums) { _ in diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift index ae7de269f..dbecdad19 100644 --- a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+StoriesView.swift @@ -20,12 +20,7 @@ struct LibraryStoriesView: View { var body: some View { if self.stories.isEmpty { - Text(""" - Your haven't saved any story yet. - Tap the \(Image(systemName: "ellipsis.circle")) button on any story to add it here. - You can then remove them from the Library using the same button. - """) - .multilineTextAlignment(.center) + EmptyLibraryPlaceholderView(icon: .stories) } else { ScrollView(showsIndicators: true) { StoryListView(stories: self.stories) { story in From 86bb7ecbe00cd64116b0977f5815befe7c199399 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Fri, 25 Oct 2024 11:00:28 +0200 Subject: [PATCH 45/99] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20(tuist):=20Upgrade?= =?UTF-8?q?=20Package.swift=20dependencies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tuist/Package.resolved | 16 ++++++++-------- Tuist/Package.swift | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Tuist/Package.resolved b/Tuist/Package.resolved index 5c457c8ae..3aea55632 100644 --- a/Tuist/Package.resolved +++ b/Tuist/Package.resolved @@ -50,8 +50,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/devicekit/DeviceKit", "state" : { - "revision" : "5757447e9f92c476ee2ca41ead7eb6db07936430", - "version" : "5.4.0" + "revision" : "7ff5331960151aec74fb422e1d45f54ef6cc086d", + "version" : "5.5.0" } }, { @@ -176,8 +176,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/lukepistrol/SFSymbolsMacro", "state" : { - "revision" : "e7d45d4f9d193f73de5533ab596e4684ef3b2189", - "version" : "0.5.2" + "revision" : "01d7874a6855a145b5e2584e9beb3ee9a63ce70b", + "version" : "0.5.3" } }, { @@ -230,8 +230,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-syntax.git", "state" : { - "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d", - "version" : "509.1.1" + "revision" : "0687f71944021d616d34d922343dcef086855920", + "version" : "600.0.1" } }, { @@ -248,8 +248,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mxcl/Version", "state" : { - "revision" : "1fe824b80d89201652e7eca7c9252269a1d85e25", - "version" : "2.0.1" + "revision" : "303a0f916772545e1e8667d3104f83be708a723c", + "version" : "2.1.0" } }, { diff --git a/Tuist/Package.swift b/Tuist/Package.swift index 14d6c719f..ab620a0e5 100644 --- a/Tuist/Package.swift +++ b/Tuist/Package.swift @@ -44,7 +44,7 @@ let package = Package( ), .package( url: "https://github.com/mxcl/Version", - exact: "2.0.1" + exact: "2.1.0" ), .package( url: "https://github.com/firebase/firebase-ios-sdk", @@ -60,7 +60,7 @@ let package = Package( ), .package( url: "https://github.com/devicekit/DeviceKit", - exact: "5.4.0" + exact: "5.5.0" ), .package( url: "https://github.com/SvenTiigi/YouTubePlayerKit", @@ -68,7 +68,7 @@ let package = Package( ), .package( url: "https://github.com/lukepistrol/SFSymbolsMacro", - exact: "0.5.2" + exact: "0.5.3" ), .package( url: "https://github.com/AvdLee/AppUpdately", From 32072401de86673384648eb04529e23aadd0282a Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 30 Oct 2024 09:59:59 +0100 Subject: [PATCH 46/99] =?UTF-8?q?=F0=9F=93=8C=20(packages):=20Upgrade=20Fi?= =?UTF-8?q?rebase=20to=20v11.4.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tuist/Package.resolved | 8 ++++---- Tuist/Package.swift | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Tuist/Package.resolved b/Tuist/Package.resolved index 3aea55632..17a43fb7b 100644 --- a/Tuist/Package.resolved +++ b/Tuist/Package.resolved @@ -59,8 +59,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/firebase/firebase-ios-sdk", "state" : { - "revision" : "1fc52ab0e172e7c5a961f975a76c2611f4f22852", - "version" : "11.2.0" + "revision" : "8328630971a8fdd8072b36bb22bef732eb15e1f0", + "version" : "11.4.0" } }, { @@ -77,8 +77,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/GoogleAppMeasurement.git", "state" : { - "revision" : "07a2f57d147d2bf368a0d2dcb5579ff082d9e44f", - "version" : "11.1.0" + "revision" : "4f234bcbdae841d7015258fbbf8e7743a39b8200", + "version" : "11.4.0" } }, { diff --git a/Tuist/Package.swift b/Tuist/Package.swift index ab620a0e5..51655c0f2 100644 --- a/Tuist/Package.swift +++ b/Tuist/Package.swift @@ -48,7 +48,7 @@ let package = Package( ), .package( url: "https://github.com/firebase/firebase-ios-sdk", - exact: "11.2.0" + exact: "11.4.0" ), .package( url: "https://github.com/OlehKorchytskyi/Fit", From 3d0389e199a160b8036c4a726ba47da9ed9e5c52 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 30 Oct 2024 10:38:17 +0100 Subject: [PATCH 47/99] =?UTF-8?q?=F0=9F=94=A5=20(LekaApp):=20Remove=20libr?= =?UTF-8?q?ary=20gamepads=20category?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/l10n/Localizable.xcstrings | 18 -------- .../Navigation/Navigation+Category.swift | 1 - .../Categories/CategoryLibraryView.swift | 3 -- .../MainView/MainView+CategoryLabel.swift | 4 -- .../Views/MainView/MainView+l10n.swift | 1 - .../Sources/Views/MainView/MainView.swift | 4 -- .../Library+GamepadsView.swift | 45 ------------------- 7 files changed, 76 deletions(-) delete mode 100644 Apps/LekaApp/Sources/Views/PersonalLibrary/Library+GamepadsView.swift diff --git a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings index 380693e7f..3b7cd606d 100644 --- a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings +++ b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings @@ -1964,24 +1964,6 @@ } } }, - "lekaapp.main_view.sidebar.category_label.library_gamepads": { - "comment": "The title of the category 'Library Gamepads'", - "extractionState": "extracted_with_value", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Gamepads" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Manettes" - } - } - } - }, "lekaapp.main_view.sidebar.category_label.library_stories": { "comment": "The title of the category 'Library Stories'", "extractionState": "extracted_with_value", diff --git a/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift b/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift index 1a1999112..77b3aed57 100644 --- a/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift +++ b/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift @@ -29,7 +29,6 @@ extension Navigation { case libraryCurriculums case libraryActivities case libraryStories - case libraryGamepads // MARK: Internal diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift index 69f14edc6..20ff9c7d0 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift @@ -19,9 +19,6 @@ struct CategoryLibraryView: View { case .libraryStories: LibraryStoriesView(viewModel: self.rootAccountViewModel) .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.stories.characters)) - case .libraryGamepads: - LibraryGamepadsView() - .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.gamepads.characters)) default: LibraryActivitiesView(viewModel: self.rootAccountViewModel) .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.activities.characters)) diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView+CategoryLabel.swift b/Apps/LekaApp/Sources/Views/MainView/MainView+CategoryLabel.swift index f74abcaff..83dc93176 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView+CategoryLabel.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView+CategoryLabel.swift @@ -98,10 +98,6 @@ extension MainView { case .libraryStories: self.title = String(l10n.MainView.Sidebar.CategoryLabel.stories.characters) self.systemImage = "text.book.closed.fill" - - case .libraryGamepads: - self.title = String(l10n.MainView.Sidebar.CategoryLabel.gamepads.characters) - self.systemImage = "gamecontroller.fill" } } diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift b/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift index ad7e22f1f..fc9df99e3 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift @@ -25,7 +25,6 @@ extension l10n { static let none = LocalizedString("lekaapp.main_view.sidebar.category_label.none", value: "Select a category", comment: "The title of the category 'none'") static let libraryCurriculums = LocalizedString("lekaapp.main_view.sidebar.category_label.library_curriculums", value: "Curriculums", comment: "The title of the category 'Library Curriculums'") static let libraryActivities = LocalizedString("lekaapp.main_view.sidebar.category_label.library_activities", value: "Activities", comment: "The title of the category 'Library Activities'") - static let libraryGamepads = LocalizedString("lekaapp.main_view.sidebar.category_label.library_gamepads", value: "Gamepads", comment: "The title of the category 'Library Gamepads'") static let libraryStories = LocalizedString("lekaapp.main_view.sidebar.category_label.library_stories", value: "Stories", comment: "The title of the category 'Library Stories'") } diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView.swift b/Apps/LekaApp/Sources/Views/MainView/MainView.swift index 06537d84c..ff2989852 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView.swift @@ -93,7 +93,6 @@ struct MainView: View { CategoryLabel(category: .libraryCurriculums) CategoryLabel(category: .libraryActivities) CategoryLabel(category: .libraryStories) - CategoryLabel(category: .libraryGamepads) } } else { Section("Demo mode") { @@ -189,9 +188,6 @@ struct MainView: View { case .libraryStories: CategoryLibraryView(category: .libraryStories) - case .libraryGamepads: - CategoryLibraryView(category: .libraryGamepads) - case .none: Text(l10n.MainView.Sidebar.CategoryLabel.home) .font(.largeTitle) diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+GamepadsView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+GamepadsView.swift deleted file mode 100644 index 7c7188c89..000000000 --- a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+GamepadsView.swift +++ /dev/null @@ -1,45 +0,0 @@ -// Leka - iOS Monorepo -// Copyright APF France handicap -// SPDX-License-Identifier: Apache-2.0 - -import AccountKit -import ContentKit -import LocalizationKit -import SwiftUI - -// MARK: - LibraryGamepadsView - -struct LibraryGamepadsView: View { - // MARK: Internal - - var body: some View { - VStack { - Spacer() - - GamepadGridView(gamepads: self.category.activities, onStartGamepad: { activity in - if self.authManagerViewModel.userAuthenticationState == .loggedIn, !self.navigation.demoMode { - self.navigation.sheetContent = .carereceiverPicker(activity: activity, story: nil) - } else { - self.navigation.currentActivity = activity - self.navigation.fullScreenCoverContent = .activityView(carereceivers: []) - } - }) - - Spacer() - } - .navigationTitle(self.category.details.title) - } - - // MARK: Private - - private let category: CategoryGamepads = .shared - - @ObservedObject private var authManagerViewModel: AuthManagerViewModel = .shared - @ObservedObject private var navigation: Navigation = .shared -} - -#Preview { - NavigationStack { - LibraryGamepadsView() - } -} From 01bd75ab0d229253e21c45eac7d24e6efa079aef Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 30 Oct 2024 11:35:44 +0100 Subject: [PATCH 48/99] =?UTF-8?q?=F0=9F=9A=B8=20(LekaApp):=20Reorganize=20?= =?UTF-8?q?sidebar=20content?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/MainView/MainView.swift | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView.swift b/Apps/LekaApp/Sources/Views/MainView/MainView.swift index ff2989852..de89cdc2d 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView.swift @@ -65,11 +65,13 @@ struct MainView: View { CategoryLabel(category: .gamepads) } - Section(String(l10n.MainView.Sidebar.sectionResources.characters)) { - CategoryLabel(category: .resourcesFirstSteps) - CategoryLabel(category: .resourcesVideo) - CategoryLabel(category: .resourcesDeepDive) - } + #if DEVELOPER_MODE || TESTFLIGHT_BUILD + Section(String(l10n.MainView.Sidebar.sectionLibrary.characters)) { + CategoryLabel(category: .libraryCurriculums) + CategoryLabel(category: .libraryActivities) + CategoryLabel(category: .libraryStories) + } + #endif if self.authManagerViewModel.userAuthenticationState == .loggedIn { Section(String(l10n.MainView.Sidebar.sectionUsers.characters)) { @@ -78,6 +80,12 @@ struct MainView: View { } } + Section(String(l10n.MainView.Sidebar.sectionResources.characters)) { + CategoryLabel(category: .resourcesFirstSteps) + CategoryLabel(category: .resourcesVideo) + CategoryLabel(category: .resourcesDeepDive) + } + #if DEVELOPER_MODE || TESTFLIGHT_BUILD if !self.navigation.demoMode { Section("Developer Mode") { @@ -88,12 +96,6 @@ struct MainView: View { CategoryLabel(category: .vectorImageList) CategoryLabel(category: .news) } - - Section(String(l10n.MainView.Sidebar.sectionLibrary.characters)) { - CategoryLabel(category: .libraryCurriculums) - CategoryLabel(category: .libraryActivities) - CategoryLabel(category: .libraryStories) - } } else { Section("Demo mode") { CategoryLabel(category: .demo) From b403bc66dd86ba1978d5ef66f282533fe323c908 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 30 Oct 2024 12:00:20 +0100 Subject: [PATCH 49/99] =?UTF-8?q?=F0=9F=9A=A8=20(LekaApp):=20Remove=20prev?= =?UTF-8?q?iew=20traits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Sources/Views/MainView/MainView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView.swift b/Apps/LekaApp/Sources/Views/MainView/MainView.swift index de89cdc2d..53dbe3b36 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView.swift @@ -328,5 +328,4 @@ struct MainView: View { #Preview { MainView() - .previewInterfaceOrientation(.landscapeLeft) } From 7afea24e0e23fd288bd78e7aabdc540b57139161 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 30 Oct 2024 12:02:24 +0100 Subject: [PATCH 50/99] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(LekaApp):=20Refacto?= =?UTF-8?q?r=20categories,=20add=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Navigation/Navigation+Category.swift | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift b/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift index 77b3aed57..688051937 100644 --- a/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift +++ b/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift @@ -6,18 +6,30 @@ import SwiftUI extension Navigation { enum Category: Hashable, Identifiable, CaseIterable { + // ? Information case home case search - case resourcesFirstSteps - case resourcesVideo - case resourcesDeepDive + + // ? Content case curriculums case activities case stories case gamepads + + // ? Library + case libraryCurriculums + case libraryActivities + case libraryStories + + // ? Monitoring case caregivers case carereceivers + // ? Resources + case resourcesFirstSteps + case resourcesVideo + case resourcesDeepDive + // ? DEVELOPER_MODE + TESTFLIGHT_BUILD case allPublishedActivities case allDraftActivities @@ -26,9 +38,6 @@ extension Navigation { case vectorImageList case news case demo - case libraryCurriculums - case libraryActivities - case libraryStories // MARK: Internal From 28e84a0bc69b5ce917a9d2eb7d18f60852456fe2 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 30 Oct 2024 14:52:54 +0100 Subject: [PATCH 51/99] =?UTF-8?q?=F0=9F=9A=B8=20(LekaApp):=20Rename=20Acti?= =?UTF-8?q?vities=20section=20to=20Educational=20Games?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/l10n/Localizable.xcstrings | 32 ++++++++--------- .../Navigation/Navigation+Category.swift | 2 +- ...ift => CategoryEducationalGamesView.swift} | 6 ++-- .../Categories/CategoryLibraryView.swift | 8 ++--- .../MainView/MainView+CategoryLabel.swift | 34 +++++++++---------- .../Views/MainView/MainView+l10n.swift | 2 +- .../Sources/Views/MainView/MainView.swift | 6 ++-- ...ory.yml => educational_games.category.yml} | 11 +++--- ....swift => Category+EducationalGames.swift} | 8 ++--- 9 files changed, 55 insertions(+), 54 deletions(-) rename Apps/LekaApp/Sources/Views/Categories/{CategoryActivitiesView.swift => CategoryEducationalGamesView.swift} (93%) rename Modules/ContentKit/Resources/Content/categories/{activities.category.yml => educational_games.category.yml} (68%) rename Modules/ContentKit/Sources/Categories/{Category+Activities.swift => Category+EducationalGames.swift} (80%) diff --git a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings index 3b7cd606d..e80bcabd2 100644 --- a/Apps/LekaApp/Resources/l10n/Localizable.xcstrings +++ b/Apps/LekaApp/Resources/l10n/Localizable.xcstrings @@ -1820,74 +1820,74 @@ } } }, - "lekaapp.main_view.sidebar.category_label.activities": { - "comment": "The title of the category 'Activities'", + "lekaapp.main_view.sidebar.category_label.caregivers": { + "comment": "The title of the category 'Caregivers'", "extractionState": "extracted_with_value", "localizations": { "en": { "stringUnit": { "state": "new", - "value": "Activities" + "value": "Caregivers" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activit\u00e9s" + "value": "Accompagnants" } } } }, - "lekaapp.main_view.sidebar.category_label.caregivers": { - "comment": "The title of the category 'Caregivers'", + "lekaapp.main_view.sidebar.category_label.carereceivers": { + "comment": "The title of the category 'Care Receivers'", "extractionState": "extracted_with_value", "localizations": { "en": { "stringUnit": { "state": "new", - "value": "Caregivers" + "value": "Care Receivers" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Accompagnants" + "value": "Personnes Accompagn\u00e9es" } } } }, - "lekaapp.main_view.sidebar.category_label.carereceivers": { - "comment": "The title of the category 'Care Receivers'", + "lekaapp.main_view.sidebar.category_label.curriculums": { + "comment": "The title of the category 'Curriculums'", "extractionState": "extracted_with_value", "localizations": { "en": { "stringUnit": { "state": "new", - "value": "Care Receivers" + "value": "Curriculums" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Personnes Accompagn\u00e9es" + "value": "Parcours" } } } }, - "lekaapp.main_view.sidebar.category_label.curriculums": { - "comment": "The title of the category 'Curriculums'", + "lekaapp.main_view.sidebar.category_label.educational_games": { + "comment": "The title of the category 'Educational Games'", "extractionState": "extracted_with_value", "localizations": { "en": { "stringUnit": { "state": "new", - "value": "Curriculums" + "value": "Educational Games" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Parcours" + "value": "Jeux \u00c9ducatifs" } } } diff --git a/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift b/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift index 688051937..3a9799bca 100644 --- a/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift +++ b/Apps/LekaApp/Sources/Navigation/Navigation+Category.swift @@ -12,7 +12,7 @@ extension Navigation { // ? Content case curriculums - case activities + case educationalGames case stories case gamepads diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryActivitiesView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryEducationalGamesView.swift similarity index 93% rename from Apps/LekaApp/Sources/Views/Categories/CategoryActivitiesView.swift rename to Apps/LekaApp/Sources/Views/Categories/CategoryEducationalGamesView.swift index 5332c2665..73c799055 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryActivitiesView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryEducationalGamesView.swift @@ -10,7 +10,7 @@ import SwiftUI // MARK: - ActivitiesView -struct CategoryActivitiesView: View { +struct CategoryEducationalGamesView: View { // MARK: Internal var body: some View { @@ -50,7 +50,7 @@ struct CategoryActivitiesView: View { // MARK: Private - private let category: CategoryActivities = .shared + private let category: CategoryEducationalGames = .shared @ObservedObject private var styleManager: StyleManager = .shared @ObservedObject private var authManagerViewModel: AuthManagerViewModel = .shared @@ -61,6 +61,6 @@ struct CategoryActivitiesView: View { NavigationSplitView { Text("Sidebar") } detail: { - CategoryActivitiesView() + CategoryEducationalGamesView() } } diff --git a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift index 20ff9c7d0..c2f7bca4e 100644 --- a/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift +++ b/Apps/LekaApp/Sources/Views/Categories/CategoryLibraryView.swift @@ -15,13 +15,13 @@ struct CategoryLibraryView: View { switch self.category { case .libraryCurriculums: LibraryCurriculumsView(viewModel: self.rootAccountViewModel) - .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.curriculums.characters)) + .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.libraryCurriculums.characters)) case .libraryStories: LibraryStoriesView(viewModel: self.rootAccountViewModel) - .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.stories.characters)) + .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.libraryStories.characters)) default: LibraryActivitiesView(viewModel: self.rootAccountViewModel) - .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.activities.characters)) + .navigationTitle(String(l10n.MainView.Sidebar.CategoryLabel.libraryActivities.characters)) } } else { Text(String(l10n.MainView.DetailView.disconnectedLibraryMessage.characters)) @@ -34,5 +34,5 @@ struct CategoryLibraryView: View { } #Preview { - CategoryLibraryView(category: .activities) + CategoryLibraryView(category: .educationalGames) } diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView+CategoryLabel.swift b/Apps/LekaApp/Sources/Views/MainView/MainView+CategoryLabel.swift index 83dc93176..ce59dd612 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView+CategoryLabel.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView+CategoryLabel.swift @@ -9,7 +9,7 @@ extension MainView { struct CategoryLabel: View { // MARK: Lifecycle - // swiftlint:disable cyclomatic_complexity body_length + // swiftlint:disable cyclomatic_complexity function_body_length init(category: Navigation.Category) { self.category = category @@ -43,8 +43,8 @@ extension MainView { self.title = String(l10n.MainView.Sidebar.CategoryLabel.curriculums.characters) self.systemImage = "graduationcap" - case .activities: - self.title = String(l10n.MainView.Sidebar.CategoryLabel.activities.characters) + case .educationalGames: + self.title = String(l10n.MainView.Sidebar.CategoryLabel.educationalGames.characters) self.systemImage = "dice" case .stories: @@ -55,6 +55,18 @@ extension MainView { self.title = String(l10n.MainView.Sidebar.CategoryLabel.gamepads.characters) self.systemImage = "gamecontroller" + case .libraryCurriculums: + self.title = String(l10n.MainView.Sidebar.CategoryLabel.libraryCurriculums.characters) + self.systemImage = "graduationcap.fill" + + case .libraryActivities: + self.title = String(l10n.MainView.Sidebar.CategoryLabel.libraryActivities.characters) + self.systemImage = "dice.fill" + + case .libraryStories: + self.title = String(l10n.MainView.Sidebar.CategoryLabel.stories.characters) + self.systemImage = "text.book.closed.fill" + case .caregivers: self.title = String(l10n.MainView.Sidebar.CategoryLabel.caregivers.characters) self.systemImage = "person.3.fill" @@ -86,22 +98,10 @@ extension MainView { case .demo: self.title = "Demo" self.systemImage = "play.rectangle" - - case .libraryCurriculums: - self.title = String(l10n.MainView.Sidebar.CategoryLabel.curriculums.characters) - self.systemImage = "graduationcap.fill" - - case .libraryActivities: - self.title = String(l10n.MainView.Sidebar.CategoryLabel.activities.characters) - self.systemImage = "dice.fill" - - case .libraryStories: - self.title = String(l10n.MainView.Sidebar.CategoryLabel.stories.characters) - self.systemImage = "text.book.closed.fill" } } - // swiftlint:enable cyclomatic_complexity body_length + // swiftlint:enable cyclomatic_complexity function_body_length // MARK: Internal @@ -117,5 +117,5 @@ extension MainView { } #Preview { - MainView.CategoryLabel(category: .activities) + MainView.CategoryLabel(category: .educationalGames) } diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift b/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift index fc9df99e3..590f2733c 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift @@ -17,7 +17,7 @@ extension l10n { static let resourcesVideo = LocalizedString("lekaapp.main_view.sidebar.category_label.resources_video", value: "Videos", comment: "The title of the resources sub category 'Videos'") static let resourcesDeepDive = LocalizedString("lekaapp.main_view.sidebar.category_label.resources_deep_dive", value: "Deep Dive", comment: "The title of the resources sub category 'DeepDive'") static let curriculums = LocalizedString("lekaapp.main_view.sidebar.category_label.curriculums", value: "Curriculums", comment: "The title of the category 'Curriculums'") - static let activities = LocalizedString("lekaapp.main_view.sidebar.category_label.activities", value: "Activities", comment: "The title of the category 'Activities'") + static let educationalGames = LocalizedString("lekaapp.main_view.sidebar.category_label.educational_games", value: "Educational Games", comment: "The title of the category 'Educational Games'") static let gamepads = LocalizedString("lekaapp.main_view.sidebar.category_label.gamepads", value: "Gamepads", comment: "The title of the category 'Gamepads'") static let stories = LocalizedString("lekaapp.main_view.sidebar.category_label.stories", value: "Stories", comment: "The title of the category 'Stories'") static let caregivers = LocalizedString("lekaapp.main_view.sidebar.category_label.caregivers", value: "Caregivers", comment: "The title of the category 'Caregivers'") diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView.swift b/Apps/LekaApp/Sources/Views/MainView/MainView.swift index 53dbe3b36..d62b045c8 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView.swift @@ -60,7 +60,7 @@ struct MainView: View { Section(String(l10n.MainView.Sidebar.sectionContent.characters)) { CategoryLabel(category: .curriculums) - CategoryLabel(category: .activities) + CategoryLabel(category: .educationalGames) CategoryLabel(category: .stories) CategoryLabel(category: .gamepads) } @@ -142,8 +142,8 @@ struct MainView: View { case .curriculums: CategoryCurriculumsView() - case .activities: - CategoryActivitiesView() + case .educationalGames: + CategoryEducationalGamesView() case .stories: CategoryStoriesView() diff --git a/Modules/ContentKit/Resources/Content/categories/activities.category.yml b/Modules/ContentKit/Resources/Content/categories/educational_games.category.yml similarity index 68% rename from Modules/ContentKit/Resources/Content/categories/activities.category.yml rename to Modules/ContentKit/Resources/Content/categories/educational_games.category.yml index 34d5aa4bb..30d8928f6 100644 --- a/Modules/ContentKit/Resources/Content/categories/activities.category.yml +++ b/Modules/ContentKit/Resources/Content/categories/educational_games.category.yml @@ -5,15 +5,16 @@ l10n: - locale: fr_FR details: - title: Activités - subtitle: Activités indépendantes, captivantes et prêtes à l’emploi pour les personnes accompagnées. - description: Découvrez des activités clé en main comme Color Bingo, Dance Freeze et Cache-Cache, parfaites pour se détendre et s'amuser après le travail. + title: Jeux éducatifs + subtitle: Jeux éducatifs indépendants, captivants et prêts à l'emploi pour les personnes accompagnées. + description: Découvrez des jeux éducatifs clé en main comme Color Bingo, Dance Freeze et Cache-Cache, parfaits pour se détendre et s'amuser après le travail. - locale: en_US details: - title: Activities - subtitle: Engaging and ready-to-use standalone activities for care receivers. + title: Educational Games + subtitle: Engaging and ready-to-use standalone educational games for care receivers. description: Explore instant favorites like Color Bingo, Dance Freeze, and Hide And Seek, ideal for relaxation and fun after work sessions. + content: - discover_leka-89CEA9FE20624659B1307B633641BC90 - dance_freeze-6E2F7D56726C419EA534C614F777D934 diff --git a/Modules/ContentKit/Sources/Categories/Category+Activities.swift b/Modules/ContentKit/Sources/Categories/Category+EducationalGames.swift similarity index 80% rename from Modules/ContentKit/Sources/Categories/Category+Activities.swift rename to Modules/ContentKit/Sources/Categories/Category+EducationalGames.swift index b17340180..a043559cc 100644 --- a/Modules/ContentKit/Sources/Categories/Category+Activities.swift +++ b/Modules/ContentKit/Sources/Categories/Category+EducationalGames.swift @@ -5,7 +5,7 @@ import Foundation import Yams -public struct CategoryActivities: CategoryProtocol { +public struct CategoryEducationalGames: CategoryProtocol { // MARK: Lifecycle public init(from decoder: Decoder) throws { @@ -25,8 +25,8 @@ public struct CategoryActivities: CategoryProtocol { // MARK: Public - public static var shared: CategoryActivities { - let path = ContentKitResources.bundle.path(forResource: "activities", ofType: ".category.yml") + public static var shared: CategoryEducationalGames { + let path = ContentKitResources.bundle.path(forResource: "educational_games", ofType: ".category.yml") let data = try? String(contentsOfFile: path!, encoding: .utf8) guard let data else { @@ -34,7 +34,7 @@ public struct CategoryActivities: CategoryProtocol { fatalError("💥 Error reading file") } - let info = try! YAMLDecoder().decode(CategoryActivities.self, from: data) // swiftlint:disable:this force_try + let info = try! YAMLDecoder().decode(CategoryEducationalGames.self, from: data) // swiftlint:disable:this force_try return info } From 5e684d009c3cc8a900f7296777bea4b5c4f6665c Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 30 Oct 2024 19:09:30 +0100 Subject: [PATCH 52/99] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20(tuis?= =?UTF-8?q?t):=20Create=20beta=20version=20of=20Leka=20App?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Project.swift | 44 +++++++++++++++---- .../AppIconBeta.appiconset/AppIconBeta.jpg | 3 ++ .../AppIconBeta.appiconset/Contents.json | 36 +++++++++++++++ .../Project+App.swift | 3 +- .../SettingsDictionary+Base.swift | 2 +- 5 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 Apps/LekaApp/Resources/Assets.xcassets/AppIconBeta.appiconset/AppIconBeta.jpg create mode 100644 Apps/LekaApp/Resources/Assets.xcassets/AppIconBeta.appiconset/Contents.json diff --git a/Apps/LekaApp/Project.swift b/Apps/LekaApp/Project.swift index e2920dab0..beea937f5 100644 --- a/Apps/LekaApp/Project.swift +++ b/Apps/LekaApp/Project.swift @@ -7,25 +7,48 @@ import ProjectDescription import ProjectDescriptionHelpers -let kLekaAppVersion: String = { - guard Environment.productionBuild.getBoolean(default: false) else { - return "999.999.999" - } +let kLekaAppVersion: String = if Environment.productionBuild.getBoolean(default: false) { + "1.13.0" +} else { + "99.00.00" +} - // ? App version - return "1.13.0" -}() +let kLekaAppBundleName: String = if Environment.productionBuild.getBoolean(default: false) { + "Leka" +} else { + "Leka Beta" +} + +let kLekaAppBundleIdentifier: String = if Environment.productionBuild.getBoolean(default: false) { + "io.leka.apf.app.LekaApp" +} else { + "io.leka.apf.app.LekaApp.beta" +} + +let kLekaAppBundleURLSchemes: String = if Environment.productionBuild.getBoolean(default: false) { + "LekaApp" +} else { + "LekaAppBeta" +} + +let kLekaAppIconName: String = if Environment.productionBuild.getBoolean(default: false) { + "AppIcon" +} else { + "AppIconBeta" +} let project = Project.app( name: "LekaApp", version: kLekaAppVersion, + bundleId: kLekaAppBundleIdentifier, infoPlist: [ "LSApplicationCategoryType": "public.app-category.education", + "CFBundleName": "\(kLekaAppBundleName)", "CFBundleURLTypes": [ [ "CFBundleTypeRole": "Editor", - "CFBundleURLName": "io.leka.apf.app.LekaApp", - "CFBundleURLSchemes": ["LekaApp"], + "CFBundleURLName": "\(kLekaAppBundleIdentifier)", + "CFBundleURLSchemes": ["\(kLekaAppBundleURLSchemes)"], ], ], "LSApplicationQueriesSchemes": ["LekaUpdater"], @@ -34,6 +57,9 @@ let project = Project.app( "audio", ], ], + settings: SettingsDictionary.extendingBase(with: [ + "ASSETCATALOG_COMPILER_APPICON_NAME": "\(kLekaAppIconName)", + ]), dependencies: [ .project(target: "AccountKit", path: Path("../../Modules/AccountKit")), .project(target: "ContentKit", path: Path("../../Modules/ContentKit")), diff --git a/Apps/LekaApp/Resources/Assets.xcassets/AppIconBeta.appiconset/AppIconBeta.jpg b/Apps/LekaApp/Resources/Assets.xcassets/AppIconBeta.appiconset/AppIconBeta.jpg new file mode 100644 index 000000000..8acee380a --- /dev/null +++ b/Apps/LekaApp/Resources/Assets.xcassets/AppIconBeta.appiconset/AppIconBeta.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b30a516423b77a8fcca40073e47af0a55fb635d838e59945bfe621e8037c0268 +size 960623 diff --git a/Apps/LekaApp/Resources/Assets.xcassets/AppIconBeta.appiconset/Contents.json b/Apps/LekaApp/Resources/Assets.xcassets/AppIconBeta.appiconset/Contents.json new file mode 100644 index 000000000..80b070763 --- /dev/null +++ b/Apps/LekaApp/Resources/Assets.xcassets/AppIconBeta.appiconset/Contents.json @@ -0,0 +1,36 @@ +{ + "images" : [ + { + "filename" : "AppIconBeta.jpg", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Tuist/ProjectDescriptionHelpers/Project+App.swift b/Tuist/ProjectDescriptionHelpers/Project+App.swift index 0f72ddeb4..17274a17b 100644 --- a/Tuist/ProjectDescriptionHelpers/Project+App.swift +++ b/Tuist/ProjectDescriptionHelpers/Project+App.swift @@ -10,6 +10,7 @@ public extension Project { static func app( name: String, version: String = "1.0.0", + bundleId: String? = nil, deploymentTargets: DeploymentTargets = .iOS("16.6"), destinations: Destinations = [.iPad, .macWithiPadDesign], infoPlist: [String: Plist.Value] = [:], @@ -22,7 +23,7 @@ public extension Project { name: name, destinations: destinations, product: .app, - bundleId: "io.leka.apf.app.\(name)", + bundleId: bundleId ?? "io.leka.apf.app.\(name)", deploymentTargets: deploymentTargets, infoPlist: .extendingDefault(with: InfoPlist.extendingBase(version: version, with: infoPlist)), sources: ["Sources/**"], diff --git a/Tuist/ProjectDescriptionHelpers/SettingsDictionary+Base.swift b/Tuist/ProjectDescriptionHelpers/SettingsDictionary+Base.swift index 82f00ab51..eaaa8e682 100644 --- a/Tuist/ProjectDescriptionHelpers/SettingsDictionary+Base.swift +++ b/Tuist/ProjectDescriptionHelpers/SettingsDictionary+Base.swift @@ -6,7 +6,7 @@ import ProjectDescription -extension SettingsDictionary { +public extension SettingsDictionary { static var base: SettingsDictionary { var settings: SettingsDictionary = [ "DEVELOPMENT_TEAM": "GKQJXACKX7", From b04fb2b77a7a04d9d0a67f04d84c9c4ea00f2edd Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 30 Oct 2024 19:23:56 +0100 Subject: [PATCH 53/99] =?UTF-8?q?=F0=9F=93=8C=20(fastlane):=20Upgrade=20to?= =?UTF-8?q?=20v2.225.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile | 2 +- Gemfile.lock | 52 ++++++++++++++++++++++++++++------------------------ 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/Gemfile b/Gemfile index 045e13f43..239c154ef 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,6 @@ source 'https://rubygems.org' # Copyright APF France handicap # SPDX-License-Identifier: Apache-2.0 -gem 'fastlane', '~>2.219.0' +gem 'fastlane', '~>2.225.0' gem 'rubocop' diff --git a/Gemfile.lock b/Gemfile.lock index d3eefc903..2fa0d2fc8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,20 +11,20 @@ GEM ast (2.4.2) atomos (0.1.3) aws-eventstream (1.3.0) - aws-partitions (1.977.0) - aws-sdk-core (3.206.0) + aws-partitions (1.998.0) + aws-sdk-core (3.211.0) aws-eventstream (~> 1, >= 1.3.0) - aws-partitions (~> 1, >= 1.651.0) + aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.91.0) - aws-sdk-core (~> 3, >= 3.205.0) + aws-sdk-kms (1.95.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.163.0) - aws-sdk-core (~> 3, >= 3.205.0) + aws-sdk-s3 (1.169.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.10.0) + aws-sigv4 (1.10.1) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) base64 (0.2.0) @@ -39,8 +39,8 @@ GEM domain_name (0.6.20240107) dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.111.0) - faraday (1.10.3) + excon (0.112.0) + faraday (1.10.4) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) faraday-excon (~> 1.1) @@ -66,17 +66,17 @@ GEM faraday-patron (1.0.0) faraday-rack (1.0.0) faraday-retry (1.0.3) - faraday_middleware (1.2.0) + faraday_middleware (1.2.1) faraday (~> 1.0) fastimage (2.3.1) - fastlane (2.219.0) + fastlane (2.225.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) aws-sdk-s3 (~> 1.0) babosa (>= 1.0.3, < 2.0.0) bundler (>= 1.12.0, < 3.0.0) - colored + colored (~> 1.2) commander (~> 4.6) dotenv (>= 2.1.1, < 3.0.0) emoji_regex (>= 0.1, < 4.0) @@ -85,6 +85,7 @@ GEM faraday-cookie_jar (~> 0.0.6) faraday_middleware (~> 1.0) fastimage (>= 2.1.0, < 3.0.0) + fastlane-sirp (>= 1.0.0) gh_inspector (>= 1.1.2, < 2.0.0) google-apis-androidpublisher_v3 (~> 0.3) google-apis-playcustomapp_v1 (~> 0.1) @@ -97,10 +98,10 @@ GEM mini_magick (>= 4.9.4, < 5.0.0) multipart-post (>= 2.0.0, < 3.0.0) naturally (~> 2.2) - optparse (>= 0.1.1) + optparse (>= 0.1.1, < 1.0.0) plist (>= 3.1.0, < 4.0.0) rubyzip (>= 2.0.0, < 3.0.0) - security (= 0.1.3) + security (= 0.1.5) simctl (~> 1.6.3) terminal-notifier (>= 2.0.0, < 3.0.0) terminal-table (~> 3) @@ -109,7 +110,9 @@ GEM word_wrap (~> 1.0.0) xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) - xcpretty-travis-formatter (>= 0.0.3) + xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) + fastlane-sirp (1.0.0) + sysrandom (~> 1.0) gh_inspector (1.1.3) google-apis-androidpublisher_v3 (0.54.0) google-apis-core (>= 0.11.0, < 2.a) @@ -153,14 +156,14 @@ GEM httpclient (2.8.3) jmespath (1.6.2) json (2.7.2) - jwt (2.9.0) + jwt (2.9.3) base64 language_server-protocol (3.17.0.3) mini_magick (4.13.2) mini_mime (1.1.5) multi_json (1.15.0) multipart-post (2.4.1) - nanaimo (0.3.0) + nanaimo (0.4.0) naturally (2.2.1) nkf (0.2.0) optparse (0.5.0) @@ -180,7 +183,7 @@ GEM trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.3.7) + rexml (3.3.9) rouge (2.0.7) rubocop (1.66.1) json (~> 2.3) @@ -197,7 +200,7 @@ GEM ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) rubyzip (2.3.2) - security (0.1.3) + security (0.1.5) signet (0.19.0) addressable (~> 2.8) faraday (>= 0.17.5, < 3.a) @@ -206,6 +209,7 @@ GEM simctl (1.6.10) CFPropertyList naturally + sysrandom (1.0.5) terminal-notifier (2.0.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) @@ -217,13 +221,13 @@ GEM uber (0.1.0) unicode-display_width (2.6.0) word_wrap (1.0.0) - xcodeproj (1.25.0) + xcodeproj (1.26.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) - nanaimo (~> 0.3.0) - rexml (>= 3.3.2, < 4.0) + nanaimo (~> 0.4.0) + rexml (>= 3.3.6, < 4.0) xcpretty (0.3.0) rouge (~> 2.0.7) xcpretty-travis-formatter (1.0.1) @@ -234,7 +238,7 @@ PLATFORMS ruby DEPENDENCIES - fastlane (~> 2.219.0) + fastlane (~> 2.225.0) rubocop BUNDLED WITH From e7f69ec49009a6af044959a23119f161e8bfae9f Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Wed, 30 Oct 2024 19:24:33 +0100 Subject: [PATCH 54/99] =?UTF-8?q?=F0=9F=91=B7=20(fastlane):=20Release=20Le?= =?UTF-8?q?ka=20App=20Beta=20to=20TestFlight?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ci-fastlane-release_beta_internal.yml | 2 +- .../SettingsDictionary+Base.swift | 6 ++--- fastlane/Fastfile | 25 +++++++++++-------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci-fastlane-release_beta_internal.yml b/.github/workflows/ci-fastlane-release_beta_internal.yml index 17598c3ca..7c1668e71 100644 --- a/.github/workflows/ci-fastlane-release_beta_internal.yml +++ b/.github/workflows/ci-fastlane-release_beta_internal.yml @@ -111,7 +111,7 @@ jobs: - name: remove label if: always() && github.event_name == 'pull_request' && contains(github.event.label.name, 'fastlane:beta') - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | diff --git a/Tuist/ProjectDescriptionHelpers/SettingsDictionary+Base.swift b/Tuist/ProjectDescriptionHelpers/SettingsDictionary+Base.swift index eaaa8e682..42e2f1b68 100644 --- a/Tuist/ProjectDescriptionHelpers/SettingsDictionary+Base.swift +++ b/Tuist/ProjectDescriptionHelpers/SettingsDictionary+Base.swift @@ -37,13 +37,13 @@ public extension SettingsDictionary { } if Environment.fastlaneBuild.getBoolean(default: false) { - let app = Environment.fastlaneAppName.getString(default: "") + let bundleId = Environment.fastlaneMatchAppBundleId.getString(default: "") - guard app != "" else { + guard bundleId != "" else { fatalError("You must provide a certificate app name") } - settings = settings.manualCodeSigning(identity: "Apple Distribution", provisioningProfileSpecifier: "match AppStore io.leka.apf.app.\(app)") + settings = settings.manualCodeSigning(identity: "Apple Distribution", provisioningProfileSpecifier: "match AppStore \(bundleId)") } else { settings = settings.manualCodeSigning(provisioningProfileSpecifier: "match Development io.leka.apf.*") } diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 523f9372e..7bbb2358f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -18,6 +18,7 @@ GIT_BASE_REF = ENV.fetch('BASE_REF', 'develop') RELEASE_BUNDLE_IDS = [ 'io.leka.apf.app.LekaApp', + 'io.leka.apf.app.LekaApp.beta', 'io.leka.apf.app.LekaUpdater' ].freeze @@ -98,7 +99,11 @@ platform :ios do UI.important apps.to_s apps.each do |app| - UI.header "Step: Generate, build & upload target: #{app}" + app_bundle_id = "io.leka.apf.app.#{app}.beta" + app_xcodeproj = "#{ROOT_DIR}/Apps/#{app}/#{app}.xcodeproj" + + UI.header "Step: Generate, build & upload target: #{app} / #{app_bundle_id} / #{app_xcodeproj}" + Dir.chdir('..') do ENV['TUIST_TURN_OFF_LINTERS'] = 'TRUE' ENV['TUIST_GENERATE_MODULES_AS_FRAMEWORKS_FOR_DEBUG'] = 'FALSE' @@ -108,13 +113,10 @@ platform :ios do ENV['TUIST_TESTFLIGHT_BUILD'] = 'TRUE' ENV['TUIST_PRODUCTION_BUILD'] = 'FALSE' ENV['TUIST_FASTLANE_BUILD'] = 'TRUE' - ENV['TUIST_FASTLANE_APP_NAME'] = app.to_s + ENV['TUIST_FASTLANE_MATCH_APP_BUNDLE_ID'] = app_bundle_id.to_s system('tuist', 'generate', '--no-open', '--no-binary-cache', app.to_s) end - app_id = "io.leka.apf.app.#{app}" - app_xcodeproj = "#{ROOT_DIR}/Apps/#{app}/#{app}.xcodeproj" - begin if ENV['CI'] app_store_connect_api_key( @@ -146,12 +148,12 @@ platform :ios do UI.header 'Step: Create verson and new build number' - latest_build_number = latest_testflight_build_number(app_identifier: app_id.to_s).to_s + latest_build_number = latest_testflight_build_number(app_identifier: app_bundle_id.to_s).to_s new_build_number = create_new_build_number(latest_build_number: latest_build_number) version_number = get_version_number(xcodeproj: app_xcodeproj.to_s) build_date = Time.new.strftime('%Y_%m_%d') - UI.important "Next release for: #{app}" + UI.important "Next release for: #{app_bundle_id}" UI.important "Version number: #{version_number}" UI.important "Build number: #{new_build_number}" @@ -175,20 +177,21 @@ platform :ios do export_method: 'app-store', export_options: { provisioningProfiles: { - "io.leka.apf.app.#{app}" => "match AppStore io.leka.apf.app.#{app}" + app_bundle_id.to_s => "match AppStore #{app_bundle_id}" } }, workspace: 'ios-monorepo.xcworkspace', scheme: app, output_directory: './.build', - output_name: "#{build_date}-#{app}-v#{version_number}-#{new_build_number}" + output_name: "#{build_date}-#{app}-beta-v#{version_number}-#{new_build_number}" ) upload_to_testflight( - app_identifier: app_id.to_s, + app_identifier: app_bundle_id.to_s, + ipa: "./.build/#{build_date}-#{app}-beta-v#{version_number}-#{new_build_number}.ipa", skip_waiting_for_build_processing: true, distribute_external: false, - groups: %w[LekaTeam ClubExpert], + groups: %w[LekaTeam], changelog: testflight_changelog ) ensure From abacbdf7225785bd9a6e2d45f5b7eef59c3465db Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Wed, 30 Oct 2024 16:49:47 +0100 Subject: [PATCH 55/99] =?UTF-8?q?=E2=9C=A8=20(AccountKit):=20Add=20Analyti?= =?UTF-8?q?csManager=20w/=203=20basic=20calls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Managers/Analytics/AnalyticsManager.swift | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift new file mode 100644 index 000000000..3880056b7 --- /dev/null +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -0,0 +1,35 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import Combine +import FirebaseAnalytics + +public class AnalyticsManager { + // MARK: Lifecycle + + private init() { + // Nothing to do + } + + // MARK: Public + + public static let shared = AnalyticsManager() + + // MARK: Public Methods + + public func logEvent(name: String, parameters: [String: Any]? = nil) { + Analytics.logEvent(name, parameters: parameters) + } + + public func setUserProperty(value: String, forName name: String) { + Analytics.setUserProperty(value, forName: name) + } + + public func logScreenView(screenName: String, screenClass: String? = nil) { + Analytics.logEvent(AnalyticsEventScreenView, parameters: [ + AnalyticsParameterScreenName: screenName, + AnalyticsParameterScreenClass: screenClass ?? screenName, + ]) + } +} From fb4925f798d8e3927ecc5c042becd3d96c05fd79 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Thu, 31 Oct 2024 11:29:18 +0100 Subject: [PATCH 56/99] =?UTF-8?q?=F0=9F=94=8A=20(LekaApp):=20Add=20Analyti?= =?UTF-8?q?cs=20launchArguments=20to=20scheme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Project.swift | 17 +++++++++++++++++ .../ProjectDescriptionHelpers/Project+App.swift | 4 +++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Apps/LekaApp/Project.swift b/Apps/LekaApp/Project.swift index beea937f5..df6d21aef 100644 --- a/Apps/LekaApp/Project.swift +++ b/Apps/LekaApp/Project.swift @@ -37,6 +37,22 @@ let kLekaAppIconName: String = if Environment.productionBuild.getBoolean(default "AppIconBeta" } +let kLekaAppLaunchArguments: [LaunchArgument] = if Environment.productionBuild.getBoolean(default: false) { + [ + .launchArgument(name: "-FIRDebugEnabled", isEnabled: false), + .launchArgument(name: "-FIRDebugDisabled", isEnabled: true), + .launchArgument(name: "-FIRAnalyticsDebugEnabled", isEnabled: false), + .launchArgument(name: "-FIRAnalyticsDebugDisabled", isEnabled: true), + ] +} else { + [ + .launchArgument(name: "-FIRDebugEnabled", isEnabled: true), + .launchArgument(name: "-FIRDebugDisabled", isEnabled: false), + .launchArgument(name: "-FIRAnalyticsDebugEnabled", isEnabled: true), + .launchArgument(name: "-FIRAnalyticsDebugDisabled", isEnabled: false), + ] +} + let project = Project.app( name: "LekaApp", version: kLekaAppVersion, @@ -60,6 +76,7 @@ let project = Project.app( settings: SettingsDictionary.extendingBase(with: [ "ASSETCATALOG_COMPILER_APPICON_NAME": "\(kLekaAppIconName)", ]), + launchArguments: kLekaAppLaunchArguments, dependencies: [ .project(target: "AccountKit", path: Path("../../Modules/AccountKit")), .project(target: "ContentKit", path: Path("../../Modules/ContentKit")), diff --git a/Tuist/ProjectDescriptionHelpers/Project+App.swift b/Tuist/ProjectDescriptionHelpers/Project+App.swift index 17274a17b..e45ce4779 100644 --- a/Tuist/ProjectDescriptionHelpers/Project+App.swift +++ b/Tuist/ProjectDescriptionHelpers/Project+App.swift @@ -15,6 +15,7 @@ public extension Project { destinations: Destinations = [.iPad, .macWithiPadDesign], infoPlist: [String: Plist.Value] = [:], settings: SettingsDictionary = [:], + launchArguments: [LaunchArgument] = [], options: Options = .options(), dependencies: [TargetDependency] = [], schemes: [Scheme] = [] @@ -33,7 +34,8 @@ public extension Project { settings: .settings(base: .extendingBase(with: settings)), environmentVariables: [ "IDEPreferLogStreaming": "YES", - ] + ], + launchArguments: launchArguments ) let testTarget = Target.target( From f77a16be62a04b2b9457207c6915cb20209ce921 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 31 Oct 2024 16:26:55 +0100 Subject: [PATCH 57/99] =?UTF-8?q?=F0=9F=93=88=20(LekaApp):=20Add=20screen?= =?UTF-8?q?=5Fview=20events=20to=20MainView's=20details=20view?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/MainView/MainView.swift | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView.swift b/Apps/LekaApp/Sources/Views/MainView/MainView.swift index d62b045c8..c3d391915 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView.swift @@ -126,36 +126,69 @@ struct MainView: View { switch self.navigation.selectedCategory { case .home: CategoryHome() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_home") + } case .search: CategorySearchView() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_search") + } case .resourcesFirstSteps: CategoryResourcesFirstStepsView() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_resources_first_steps") + } case .resourcesVideo: CategoryResourcesVideosView() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_resources_video") + } case .resourcesDeepDive: CategoryResourcesDeepDiveView() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_resources_deep_dive") + } case .curriculums: CategoryCurriculumsView() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_catergory_curriculums") + } case .educationalGames: CategoryEducationalGamesView() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_educational_games") + } case .stories: CategoryStoriesView() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_stories") + } case .gamepads: CategoryGamepadsView() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_gamepads") + } case .caregivers: CaregiverList() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_caregivers") + } case .carereceivers: CarereceiverList() + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_carereceivers") + } // ? DEVELOPER_MODE + TESTFLIGHT_BUILD case .allPublishedActivities: @@ -183,12 +216,21 @@ struct MainView: View { case .libraryCurriculums: CategoryLibraryView(category: .libraryCurriculums) + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_library_curriculums") + } case .libraryActivities: CategoryLibraryView(category: .libraryActivities) + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_library_activities") + } case .libraryStories: CategoryLibraryView(category: .libraryStories) + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_category_library_stories") + } case .none: Text(l10n.MainView.Sidebar.CategoryLabel.home) From 4580c9b6c0c96e2c35ee2933023144cb758ed180 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 11:15:01 +0100 Subject: [PATCH 58/99] =?UTF-8?q?=F0=9F=94=A7=20(LekaApp):=20Remove=20Anal?= =?UTF-8?q?ytics=20launchArguments=20from=20project?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Project.swift | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Apps/LekaApp/Project.swift b/Apps/LekaApp/Project.swift index df6d21aef..beea937f5 100644 --- a/Apps/LekaApp/Project.swift +++ b/Apps/LekaApp/Project.swift @@ -37,22 +37,6 @@ let kLekaAppIconName: String = if Environment.productionBuild.getBoolean(default "AppIconBeta" } -let kLekaAppLaunchArguments: [LaunchArgument] = if Environment.productionBuild.getBoolean(default: false) { - [ - .launchArgument(name: "-FIRDebugEnabled", isEnabled: false), - .launchArgument(name: "-FIRDebugDisabled", isEnabled: true), - .launchArgument(name: "-FIRAnalyticsDebugEnabled", isEnabled: false), - .launchArgument(name: "-FIRAnalyticsDebugDisabled", isEnabled: true), - ] -} else { - [ - .launchArgument(name: "-FIRDebugEnabled", isEnabled: true), - .launchArgument(name: "-FIRDebugDisabled", isEnabled: false), - .launchArgument(name: "-FIRAnalyticsDebugEnabled", isEnabled: true), - .launchArgument(name: "-FIRAnalyticsDebugDisabled", isEnabled: false), - ] -} - let project = Project.app( name: "LekaApp", version: kLekaAppVersion, @@ -76,7 +60,6 @@ let project = Project.app( settings: SettingsDictionary.extendingBase(with: [ "ASSETCATALOG_COMPILER_APPICON_NAME": "\(kLekaAppIconName)", ]), - launchArguments: kLekaAppLaunchArguments, dependencies: [ .project(target: "AccountKit", path: Path("../../Modules/AccountKit")), .project(target: "ContentKit", path: Path("../../Modules/ContentKit")), From e5c263967820e8967a2c5c17ac2495104c243151 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Wed, 6 Nov 2024 18:54:26 +0200 Subject: [PATCH 59/99] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20(Leka?= =?UTF-8?q?App):=20Set=20Firebase=20DebugView=20flag=20on=20Testflight,Dev?= =?UTF-8?q?eloper=20Build?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit see https://blog.gruby.com/2020/11/02/debugging-firebase-analytics-on-ios/ --- Apps/LekaApp/Sources/MainApp.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Apps/LekaApp/Sources/MainApp.swift b/Apps/LekaApp/Sources/MainApp.swift index faa157cf7..00e3048c1 100644 --- a/Apps/LekaApp/Sources/MainApp.swift +++ b/Apps/LekaApp/Sources/MainApp.swift @@ -21,6 +21,7 @@ struct LekaApp: App { // MARK: Lifecycle init() { + // ? Set GoogleService-Info.plist based on the build configuration #if PRODUCTION_BUILD log.warning("PRODUCTION_BUILD") let googleServiceInfoPlistName = "GoogleServiceInfo+PROD" @@ -35,6 +36,14 @@ struct LekaApp: App { let googleServiceInfoPlistName = "GoogleServiceInfo+NOT_FOUND" #endif + // ? Enable Firebase Analytics DebugView for TestFlight/Developer mode + #if TESTFLIGHT_BUILD || DEVELOPER_MODE + var args = ProcessInfo.processInfo.arguments + args.append("-FIRDebugEnabled") + args.append("-FIRAnalyticsDebugEnabled") + ProcessInfo.processInfo.setValue(args, forKey: "arguments") + #endif + guard let googleServiceInfoPlistPath = Bundle.main.path(forResource: googleServiceInfoPlistName, ofType: "plist"), let options = FirebaseOptions(contentsOfFile: googleServiceInfoPlistPath) else { From 2206fd924cbfdf730d806989a88e64ea4ea66c82 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 11:19:53 +0100 Subject: [PATCH 60/99] =?UTF-8?q?=F0=9F=90=9B=20(LekaApp):=20Resources=20-?= =?UTF-8?q?=20fix=20broken=20video=20link?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Content/categories/resources_deep_dive.category.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/ContentKit/Resources/Content/categories/resources_deep_dive.category.yml b/Modules/ContentKit/Resources/Content/categories/resources_deep_dive.category.yml index 013e12471..1bcd44c37 100644 --- a/Modules/ContentKit/Resources/Content/categories/resources_deep_dive.category.yml +++ b/Modules/ContentKit/Resources/Content/categories/resources_deep_dive.category.yml @@ -80,7 +80,7 @@ content: details: icon: book.and.wrench title: L'utilisation de la carte "STOP" - value: https://www.youtube.com/watch?v=5rBmfCZtoX8 + value: https://www.youtube.com/watch?v=nVAotKJs8cM type: video - locale: en_US details: From 12a46508e398c69bcb1038cdb2fc812f325e7436 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 11:46:10 +0100 Subject: [PATCH 61/99] =?UTF-8?q?=F0=9F=91=B7=20(ci):=20Cache=20gems=20for?= =?UTF-8?q?=20release=20workflows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-fastlane-release_app_store.yml | 8 ++++++++ .github/workflows/ci-fastlane-release_beta_internal.yml | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/.github/workflows/ci-fastlane-release_app_store.yml b/.github/workflows/ci-fastlane-release_app_store.yml index 154f08c3b..abe16b0d1 100644 --- a/.github/workflows/ci-fastlane-release_app_store.yml +++ b/.github/workflows/ci-fastlane-release_app_store.yml @@ -49,8 +49,16 @@ jobs: run: | echo "$HOME/.local/share/mise/shims" >> $GITHUB_PATH + - uses: actions/cache@v4 + with: + path: vendor/bundle + key: ${{ runner.name }}-${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: | + ${{ runner.name }}-${{ runner.os }}-gems- + - name: bundle install run: | + bundle config path vendor/bundle bundle install - name: tuist install diff --git a/.github/workflows/ci-fastlane-release_beta_internal.yml b/.github/workflows/ci-fastlane-release_beta_internal.yml index 7c1668e71..141ba94ef 100644 --- a/.github/workflows/ci-fastlane-release_beta_internal.yml +++ b/.github/workflows/ci-fastlane-release_beta_internal.yml @@ -63,8 +63,16 @@ jobs: run: | echo "$HOME/.local/share/mise/shims" >> $GITHUB_PATH + - uses: actions/cache@v4 + with: + path: vendor/bundle + key: ${{ runner.name }}-${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + restore-keys: | + ${{ runner.name }}-${{ runner.os }}-gems- + - name: bundle install run: | + bundle config path vendor/bundle bundle install - name: tuist install From b9aa6179797b7dc712b68049945e8fbb8648ba34 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 13:59:15 +0100 Subject: [PATCH 62/99] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(AccountKit):=20Care?= =?UTF-8?q?receiverManager=20-=20make=20current=20value=20subjects=20publi?= =?UTF-8?q?c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Carereceivers/CarereceiverManager.swift | 27 +++++-------------- .../CarereceiverManagerViewModel.swift | 6 ++--- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/Modules/AccountKit/Sources/Managers/Carereceivers/CarereceiverManager.swift b/Modules/AccountKit/Sources/Managers/Carereceivers/CarereceiverManager.swift index f2c8932fe..98d65ee09 100644 --- a/Modules/AccountKit/Sources/Managers/Carereceivers/CarereceiverManager.swift +++ b/Modules/AccountKit/Sources/Managers/Carereceivers/CarereceiverManager.swift @@ -15,11 +15,15 @@ public class CarereceiverManager { public static let shared = CarereceiverManager() + public var carereceiverList = CurrentValueSubject<[Carereceiver], Never>([]) + public var currentCarereceivers = CurrentValueSubject<[Carereceiver], Never>([]) + public var fetchError = PassthroughSubject() + public func initializeCarereceiversListener() { self.dbOps.observeAll(from: .carereceivers) .sink(receiveCompletion: { [weak self] completion in if case let .failure(error) = completion { - self?.fetchErrorSubject.send(error) + self?.fetchError.send(error) } }, receiveValue: { [weak self] fetchedCarereceivers in self?.carereceiverList.send(fetchedCarereceivers) @@ -49,7 +53,7 @@ public class CarereceiverManager { self.dbOps.update(data: carereceiver, in: .carereceivers) .sink(receiveCompletion: { completion in if case let .failure(error) = completion { - self.fetchErrorSubject.send(error) + self.fetchError.send(error) } }, receiveValue: { // Nothing to do @@ -61,7 +65,7 @@ public class CarereceiverManager { self.dbOps.delete(from: .carereceivers, documentID: documentID) .sink(receiveCompletion: { completion in if case let .failure(error) = completion { - self.fetchErrorSubject.send(error) + self.fetchError.send(error) } }, receiveValue: { // Nothing to do @@ -81,25 +85,8 @@ public class CarereceiverManager { self.cancellables.removeAll() } - // MARK: Internal - - var carereceiversPublisher: AnyPublisher<[Carereceiver], Never> { - self.carereceiverList.eraseToAnyPublisher() - } - - var currentCarereceiversPublisher: AnyPublisher<[Carereceiver], Never> { - self.currentCarereceivers.eraseToAnyPublisher() - } - - var fetchErrorPublisher: AnyPublisher { - self.fetchErrorSubject.eraseToAnyPublisher() - } - // MARK: Private - private var carereceiverList = CurrentValueSubject<[Carereceiver], Never>([]) - private var currentCarereceivers = CurrentValueSubject<[Carereceiver], Never>([]) - private var fetchErrorSubject = PassthroughSubject() private let dbOps = DatabaseOperations.shared private var cancellables = Set() } diff --git a/Modules/AccountKit/Sources/Managers/Carereceivers/CarereceiverManagerViewModel.swift b/Modules/AccountKit/Sources/Managers/Carereceivers/CarereceiverManagerViewModel.swift index 1a2893db4..645859d43 100644 --- a/Modules/AccountKit/Sources/Managers/Carereceivers/CarereceiverManagerViewModel.swift +++ b/Modules/AccountKit/Sources/Managers/Carereceivers/CarereceiverManagerViewModel.swift @@ -25,21 +25,21 @@ public class CarereceiverManagerViewModel: ObservableObject { private let carereceiverManager = CarereceiverManager.shared private func subscribeToManager() { - self.carereceiverManager.carereceiversPublisher + self.carereceiverManager.carereceiverList .receive(on: DispatchQueue.main) .sink(receiveValue: { [weak self] fetchedCarereceivers in self?.carereceivers = fetchedCarereceivers }) .store(in: &self.cancellables) - self.carereceiverManager.currentCarereceiversPublisher + self.carereceiverManager.currentCarereceivers .receive(on: DispatchQueue.main) .sink(receiveValue: { [weak self] fetchedCarereceivers in self?.currentCarereceivers = fetchedCarereceivers }) .store(in: &self.cancellables) - self.carereceiverManager.fetchErrorPublisher + self.carereceiverManager.fetchError .receive(on: DispatchQueue.main) .sink(receiveValue: { [weak self] error in self?.handleError(error) From 6e00264c07e483a1f03762b97f23267fe2d82ddb Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 14:08:04 +0100 Subject: [PATCH 63/99] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(AccountKit):=20Care?= =?UTF-8?q?regiverManager=20-=20make=20current=20value=20subjects=20public?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Caregivers/CaregiverManager.swift | 37 +++++-------------- .../CaregiverManagerViewModel.swift | 8 ++-- 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManager.swift b/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManager.swift index b79128da3..932d1cd5a 100644 --- a/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManager.swift +++ b/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManager.swift @@ -15,12 +15,17 @@ public class CaregiverManager { public static let shared = CaregiverManager() + public var caregiverList = CurrentValueSubject<[Caregiver], Never>([]) + public var currentCaregiver = CurrentValueSubject(nil) + public let isLoading = PassthroughSubject() + public var fetchError = PassthroughSubject() + public func initializeCaregiversListener() { self.dbOps.observeAll(from: .caregivers) - .handleLoadingState(using: self.loadingStatePublisher) + .handleLoadingState(using: self.isLoading) .sink(receiveCompletion: { [weak self] completion in if case let .failure(error) = completion { - self?.fetchErrorSubject.send(error) + self?.fetchError.send(error) } }, receiveValue: { [weak self] fetchedCaregivers in guard let self else { return } @@ -36,7 +41,7 @@ public class CaregiverManager { self.dbOps.read(from: .caregivers, documentID: documentID) .sink(receiveCompletion: { [weak self] completion in if case let .failure(error) = completion { - self?.fetchErrorSubject.send(error) + self?.fetchError.send(error) } }, receiveValue: { [weak self] fetchedCaregiver in self?.currentCaregiver.send(fetchedCaregiver) @@ -66,7 +71,7 @@ public class CaregiverManager { self.dbOps.update(data: caregiver, in: .caregivers) .sink(receiveCompletion: { completion in if case let .failure(error) = completion { - self.fetchErrorSubject.send(error) + self.fetchError.send(error) } }, receiveValue: { _ in // Nothing to do @@ -78,7 +83,7 @@ public class CaregiverManager { self.dbOps.delete(from: .caregivers, documentID: documentID) .sink(receiveCompletion: { completion in if case let .failure(error) = completion { - self.fetchErrorSubject.send(error) + self.fetchError.send(error) } }, receiveValue: { // Nothing to do @@ -106,30 +111,8 @@ public class CaregiverManager { self.cancellables.removeAll() } - // MARK: Internal - - var currentCaregiverPublisher: AnyPublisher { - self.currentCaregiver.eraseToAnyPublisher() - } - - var caregiversPublisher: AnyPublisher<[Caregiver], Never> { - self.caregiverList.eraseToAnyPublisher() - } - - var isLoadingPublisher: AnyPublisher { - self.loadingStatePublisher.eraseToAnyPublisher() - } - - var fetchErrorPublisher: AnyPublisher { - self.fetchErrorSubject.eraseToAnyPublisher() - } - // MARK: Private - private var caregiverList = CurrentValueSubject<[Caregiver], Never>([]) - private var currentCaregiver = CurrentValueSubject(nil) - private let loadingStatePublisher = PassthroughSubject() - private var fetchErrorSubject = PassthroughSubject() private let dbOps = DatabaseOperations.shared private var cancellables = Set() } diff --git a/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManagerViewModel.swift b/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManagerViewModel.swift index 797033e48..9574b924c 100644 --- a/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManagerViewModel.swift +++ b/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManagerViewModel.swift @@ -26,28 +26,28 @@ public class CaregiverManagerViewModel: ObservableObject { private let caregiverManager = CaregiverManager.shared private func subscribeToManager() { - self.caregiverManager.caregiversPublisher + self.caregiverManager.caregiverList .receive(on: DispatchQueue.main) .sink(receiveValue: { [weak self] fetchedCaregivers in self?.caregivers = fetchedCaregivers }) .store(in: &self.cancellables) - self.caregiverManager.currentCaregiverPublisher + self.caregiverManager.currentCaregiver .receive(on: DispatchQueue.main) .sink(receiveValue: { [weak self] caregiver in self?.currentCaregiver = caregiver }) .store(in: &self.cancellables) - self.caregiverManager.isLoadingPublisher + self.caregiverManager.isLoading .receive(on: DispatchQueue.main) .sink { [weak self] isLoading in self?.isLoading = isLoading } .store(in: &self.cancellables) - self.caregiverManager.fetchErrorPublisher + self.caregiverManager.fetchError .receive(on: DispatchQueue.main) .sink(receiveValue: { [weak self] error in self?.handleError(error) From 2b7dfe2a59a3f5010c27d17f4b342848a9a73199 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 16:21:02 +0100 Subject: [PATCH 64/99] =?UTF-8?q?=F0=9F=91=B7=20(ci):=20Rename=20gems=20ca?= =?UTF-8?q?che=20keys?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-fastlane-release_app_store.yml | 5 +++-- .github/workflows/ci-fastlane-release_beta_internal.yml | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-fastlane-release_app_store.yml b/.github/workflows/ci-fastlane-release_app_store.yml index abe16b0d1..1ea420f4a 100644 --- a/.github/workflows/ci-fastlane-release_app_store.yml +++ b/.github/workflows/ci-fastlane-release_app_store.yml @@ -52,9 +52,10 @@ jobs: - uses: actions/cache@v4 with: path: vendor/bundle - key: ${{ runner.name }}-${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + key: ${{ runner.os }}-gems-${{ runner.name }}-${{ hashFiles('**/Gemfile.lock') }} restore-keys: | - ${{ runner.name }}-${{ runner.os }}-gems- + ${{ runner.os }}-gems-${{ runner.name }}- + ${{ runner.os }}-gems- - name: bundle install run: | diff --git a/.github/workflows/ci-fastlane-release_beta_internal.yml b/.github/workflows/ci-fastlane-release_beta_internal.yml index 141ba94ef..939d91f44 100644 --- a/.github/workflows/ci-fastlane-release_beta_internal.yml +++ b/.github/workflows/ci-fastlane-release_beta_internal.yml @@ -66,9 +66,10 @@ jobs: - uses: actions/cache@v4 with: path: vendor/bundle - key: ${{ runner.name }}-${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} + key: ${{ runner.os }}-gems-${{ runner.name }}-${{ hashFiles('**/Gemfile.lock') }} restore-keys: | - ${{ runner.name }}-${{ runner.os }}-gems- + ${{ runner.os }}-gems-${{ runner.name }}- + ${{ runner.os }}-gems- - name: bundle install run: | From a1bae0c8d15db06fbc911186641de08b42179867 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 16:17:18 +0100 Subject: [PATCH 65/99] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20(Leka?= =?UTF-8?q?App):=20Try=20to=20fix=20DebugView=20in=20TestFlight=20builds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Sources/MainApp.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Apps/LekaApp/Sources/MainApp.swift b/Apps/LekaApp/Sources/MainApp.swift index 00e3048c1..782691ac5 100644 --- a/Apps/LekaApp/Sources/MainApp.swift +++ b/Apps/LekaApp/Sources/MainApp.swift @@ -38,10 +38,8 @@ struct LekaApp: App { // ? Enable Firebase Analytics DebugView for TestFlight/Developer mode #if TESTFLIGHT_BUILD || DEVELOPER_MODE - var args = ProcessInfo.processInfo.arguments - args.append("-FIRDebugEnabled") - args.append("-FIRAnalyticsDebugEnabled") - ProcessInfo.processInfo.setValue(args, forKey: "arguments") + UserDefaults.standard.set(true, forKey: "/google/firebase/debug_mode") + UserDefaults.standard.set(true, forKey: "/google/measurement/debug_mode") #endif guard let googleServiceInfoPlistPath = Bundle.main.path(forResource: googleServiceInfoPlistName, ofType: "plist"), @@ -53,6 +51,7 @@ struct LekaApp: App { log.warning("Firebase: \(googleServiceInfoPlistName)") log.warning("Firebase options: \(options)") + FirebaseApp.configure(options: options) } From 100251087cc6836b916230128eba2f73b0251b49 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sat, 2 Nov 2024 12:12:08 +0100 Subject: [PATCH 66/99] =?UTF-8?q?=E2=9C=A8=20(AccountKit):=20Update=20Anal?= =?UTF-8?q?yticsMngr=20w/=20defaultParameters=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Managers/Analytics/AnalyticsManager.swift | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift index 3880056b7..f0203b9bc 100644 --- a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -22,14 +22,18 @@ public class AnalyticsManager { Analytics.logEvent(name, parameters: parameters) } - public func setUserProperty(value: String, forName name: String) { - Analytics.setUserProperty(value, forName: name) - } - public func logScreenView(screenName: String, screenClass: String? = nil) { Analytics.logEvent(AnalyticsEventScreenView, parameters: [ AnalyticsParameterScreenName: screenName, AnalyticsParameterScreenClass: screenClass ?? screenName, ]) } + + public func setDefaultEventParameters(_ parameters: [String: Any]?) { + Analytics.setDefaultEventParameters(parameters) + } + + public func clearDefaultEventParameters() { + self.setDefaultEventParameters(nil) + } } From 32ab9c4733399e91fe046348341b42f76bdb00fc Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sat, 2 Nov 2024 13:22:27 +0100 Subject: [PATCH 67/99] =?UTF-8?q?=F0=9F=93=88=20(ContentKit):=20Add=20scre?= =?UTF-8?q?en=5Fview=20to=20Cur,=20Acts=20&=20Strs=20DetailsViews?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modules/ContentKit/Sources/Views/ActivityDetailsView.swift | 3 +++ Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift | 3 +++ Modules/ContentKit/Sources/Views/StoryDetailsView.swift | 3 +++ 3 files changed, 9 insertions(+) diff --git a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift index ed573455b..ccfac4b63 100644 --- a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift @@ -116,6 +116,9 @@ public struct ActivityDetailsView: View { .markdownTheme(.gitHub) } } + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_activity_details_view") + } .toolbar { #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { diff --git a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift index 94f6371a3..f9c91e2a1 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift @@ -141,6 +141,9 @@ public struct CurriculumDetailsView: View { } } } + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_curriculum_details_view") + } .toolbar { #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { diff --git a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift index 51250e433..2e59c8e9f 100644 --- a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift @@ -107,6 +107,9 @@ public struct StoryDetailsView: View { .markdownTheme(.gitHub) } } + .onAppear { + AnalyticsManager.shared.logScreenView(screenName: "view_story_details_view") + } .toolbar { #if DEVELOPER_MODE || TESTFLIGHT_BUILD if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { From 6daf235c7b615be0ecf92aa70af15ec80c47ce67 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sat, 2 Nov 2024 16:49:33 +0100 Subject: [PATCH 68/99] =?UTF-8?q?=F0=9F=93=88=20(AccountKit):=20Set/reset?= =?UTF-8?q?=20current=5Fcaregiver=20default=20parameter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Managers/Caregivers/CaregiverManager.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManager.swift b/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManager.swift index 932d1cd5a..3498f3d3d 100644 --- a/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManager.swift +++ b/Modules/AccountKit/Sources/Managers/Caregivers/CaregiverManager.swift @@ -93,14 +93,21 @@ public class CaregiverManager { public func setCurrentCaregiver(to caregiver: Caregiver) { self.currentCaregiver.send(caregiver) + AnalyticsManager.shared.setDefaultEventParameters( + ["caregiver_id": caregiver.id ?? "no_id"] + ) } public func setCurrentCaregiver(byID id: String) { self.currentCaregiver.send(self.caregiverList.value.first { $0.id == id }) + AnalyticsManager.shared.setDefaultEventParameters( + ["caregiver_id": id] + ) } public func resetCurrentCaregiver() { self.currentCaregiver.send(nil) + AnalyticsManager.shared.setDefaultEventParameters(["caregiver_id": "no_id"]) } public func resetData() { @@ -109,6 +116,7 @@ public class CaregiverManager { self.dbOps.clearAllListeners() self.cancellables.forEach { $0.cancel() } self.cancellables.removeAll() + AnalyticsManager.shared.setDefaultEventParameters(["caregiver_id": "no_id"]) } // MARK: Private From b567b962a27d29e011bdc8e9fc0859afe6eef17e Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Sat, 2 Nov 2024 16:54:03 +0100 Subject: [PATCH 69/99] =?UTF-8?q?=F0=9F=93=88=20(LekaApp):=20Clear=20defau?= =?UTF-8?q?lt=20parameters=20on=20SignOut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Sources/Views/Settings/SettingsView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift b/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift index b043087e9..d468c7174 100644 --- a/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift +++ b/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift @@ -220,6 +220,7 @@ struct SettingsView: View { self.rootAccountViewModel.resetData() self.styleManager.accentColor = DesignKitAsset.Colors.lekaDarkBlue.swiftUIColor self.styleManager.colorScheme = .light + AnalyticsManager.shared.clearDefaultEventParameters() } private var errorAlertTitle: String { From 0879c84a75a3336eee3aa55ec8e86bad273b085f Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Wed, 6 Nov 2024 10:34:38 +0200 Subject: [PATCH 70/99] =?UTF-8?q?=F0=9F=93=88=20(LekaApp):=20LogEvents=20S?= =?UTF-8?q?ignIn,=20SignUp=20&=20skip=20authentication?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/AccountCreation/AccountCreationView.swift | 1 + Apps/LekaApp/Sources/Views/ConnectionView.swift | 1 + Apps/LekaApp/Sources/Views/WelcomeView.swift | 1 + .../Sources/Managers/Analytics/AnalyticsManager.swift | 10 ++++++++++ 4 files changed, 13 insertions(+) diff --git a/Apps/LekaApp/Sources/Views/AccountCreation/AccountCreationView.swift b/Apps/LekaApp/Sources/Views/AccountCreation/AccountCreationView.swift index 0b59c2e1d..96d48f91e 100644 --- a/Apps/LekaApp/Sources/Views/AccountCreation/AccountCreationView.swift +++ b/Apps/LekaApp/Sources/Views/AccountCreation/AccountCreationView.swift @@ -65,6 +65,7 @@ struct AccountCreationView: View { Alert(title: Text(l10n.AccountCreationView.EmailVerificationAlert.title), message: Text(l10n.AccountCreationView.EmailVerificationAlert.message), dismissButton: .default(Text(l10n.AccountCreationView.EmailVerificationAlert.dismissButton)) { + AnalyticsManager.shared.logSignUpEvent() self.navigation.navigateToAccountCreationProcess = true }) } diff --git a/Apps/LekaApp/Sources/Views/ConnectionView.swift b/Apps/LekaApp/Sources/Views/ConnectionView.swift index f3748bcaf..f5311577a 100644 --- a/Apps/LekaApp/Sources/Views/ConnectionView.swift +++ b/Apps/LekaApp/Sources/Views/ConnectionView.swift @@ -78,6 +78,7 @@ struct ConnectionView: View { self.caregiverManager.initializeCaregiversListener() self.carereceiverManager.initializeCarereceiversListener() self.rootAccountManager.initializeRootAccountListener() + AnalyticsManager.shared.logLoginEvent() self.authManagerViewModel.userAction = .none self.navigation.fullScreenCoverContent = nil } diff --git a/Apps/LekaApp/Sources/Views/WelcomeView.swift b/Apps/LekaApp/Sources/Views/WelcomeView.swift index d5402328c..53b4ed184 100644 --- a/Apps/LekaApp/Sources/Views/WelcomeView.swift +++ b/Apps/LekaApp/Sources/Views/WelcomeView.swift @@ -46,6 +46,7 @@ struct WelcomeView: View { .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button(String(l10n.WelcomeView.skipStepButton.characters)) { + AnalyticsManager.shared.logEvent(name: "skip_authentication") self.dismiss() } } diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift index f0203b9bc..003c37266 100644 --- a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -36,4 +36,14 @@ public class AnalyticsManager { public func clearDefaultEventParameters() { self.setDefaultEventParameters(nil) } + + // Recommended events methods + + public func logLoginEvent() { + Analytics.logEvent(AnalyticsEventLogin, parameters: nil) + } + + public func logSignUpEvent() { + Analytics.logEvent(AnalyticsEventSignUp, parameters: nil) + } } From ad44ac7662341e9577b2329ace04ec908e454335 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Wed, 6 Nov 2024 10:37:39 +0200 Subject: [PATCH 71/99] =?UTF-8?q?=F0=9F=93=88=20(LekaApp):=20LogEvent=20Si?= =?UTF-8?q?gnOut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Sources/Views/Settings/SettingsView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift b/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift index d468c7174..865d0f1aa 100644 --- a/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift +++ b/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift @@ -95,6 +95,7 @@ struct SettingsView: View { { Button(role: .destructive) { self.dismiss() + AnalyticsManager.shared.logEvent(name: "sign_out") self.authManager.signOut() self.persistentDataManager.clearUserData() self.reset() From 4317fd811ed8644a65336c0e38a1876ec8a26634 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 17:07:18 +0100 Subject: [PATCH 72/99] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(Analytics):=20Renam?= =?UTF-8?q?e,=20refactor=20logEventScreenView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/MainView/MainView.swift | 28 +++++++++---------- .../Managers/Analytics/AnalyticsManager.swift | 13 ++++++--- .../Sources/Views/ActivityDetailsView.swift | 2 +- .../Sources/Views/CurriculumDetailsView.swift | 2 +- .../Sources/Views/StoryDetailsView.swift | 2 +- 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/Apps/LekaApp/Sources/Views/MainView/MainView.swift b/Apps/LekaApp/Sources/Views/MainView/MainView.swift index c3d391915..847edf138 100644 --- a/Apps/LekaApp/Sources/Views/MainView/MainView.swift +++ b/Apps/LekaApp/Sources/Views/MainView/MainView.swift @@ -127,67 +127,67 @@ struct MainView: View { case .home: CategoryHome() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_home") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_home") } case .search: CategorySearchView() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_search") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_search") } case .resourcesFirstSteps: CategoryResourcesFirstStepsView() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_resources_first_steps") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_resources_first_steps") } case .resourcesVideo: CategoryResourcesVideosView() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_resources_video") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_resources_video") } case .resourcesDeepDive: CategoryResourcesDeepDiveView() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_resources_deep_dive") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_resources_deep_dive") } case .curriculums: CategoryCurriculumsView() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_catergory_curriculums") + AnalyticsManager.shared.logEventScreenView(screenName: "view_catergory_curriculums") } case .educationalGames: CategoryEducationalGamesView() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_educational_games") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_educational_games") } case .stories: CategoryStoriesView() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_stories") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_stories") } case .gamepads: CategoryGamepadsView() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_gamepads") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_gamepads") } case .caregivers: CaregiverList() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_caregivers") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_caregivers") } case .carereceivers: CarereceiverList() .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_carereceivers") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_carereceivers") } // ? DEVELOPER_MODE + TESTFLIGHT_BUILD @@ -217,19 +217,19 @@ struct MainView: View { case .libraryCurriculums: CategoryLibraryView(category: .libraryCurriculums) .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_library_curriculums") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_library_curriculums") } case .libraryActivities: CategoryLibraryView(category: .libraryActivities) .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_library_activities") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_library_activities") } case .libraryStories: CategoryLibraryView(category: .libraryStories) .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_category_library_stories") + AnalyticsManager.shared.logEventScreenView(screenName: "view_category_library_stories") } case .none: diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift index 003c37266..8e1e06ef0 100644 --- a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -22,11 +22,16 @@ public class AnalyticsManager { Analytics.logEvent(name, parameters: parameters) } - public func logScreenView(screenName: String, screenClass: String? = nil) { - Analytics.logEvent(AnalyticsEventScreenView, parameters: [ + public func logEventScreenView(screenName: String, screenClass: String? = nil) { + var params: [String: Any] = [ AnalyticsParameterScreenName: screenName, - AnalyticsParameterScreenClass: screenClass ?? screenName, - ]) + ] + + if let screenClass { + params[AnalyticsParameterScreenClass] = screenClass + } + + Analytics.logEvent(AnalyticsEventScreenView, parameters: params) } public func setDefaultEventParameters(_ parameters: [String: Any]?) { diff --git a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift index ccfac4b63..438696e46 100644 --- a/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityDetailsView.swift @@ -117,7 +117,7 @@ public struct ActivityDetailsView: View { } } .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_activity_details_view") + AnalyticsManager.shared.logEventScreenView(screenName: "view_activity_details_view") } .toolbar { #if DEVELOPER_MODE || TESTFLIGHT_BUILD diff --git a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift index f9c91e2a1..155fbac13 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumDetailsView.swift @@ -142,7 +142,7 @@ public struct CurriculumDetailsView: View { } } .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_curriculum_details_view") + AnalyticsManager.shared.logEventScreenView(screenName: "view_curriculum_details_view") } .toolbar { #if DEVELOPER_MODE || TESTFLIGHT_BUILD diff --git a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift index 2e59c8e9f..4e02058fc 100644 --- a/Modules/ContentKit/Sources/Views/StoryDetailsView.swift +++ b/Modules/ContentKit/Sources/Views/StoryDetailsView.swift @@ -108,7 +108,7 @@ public struct StoryDetailsView: View { } } .onAppear { - AnalyticsManager.shared.logScreenView(screenName: "view_story_details_view") + AnalyticsManager.shared.logEventScreenView(screenName: "view_story_details_view") } .toolbar { #if DEVELOPER_MODE || TESTFLIGHT_BUILD From 2290547fa814d0b03708df316edb39043cd7c570 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 17:12:49 +0100 Subject: [PATCH 73/99] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(Analytics):=20Renam?= =?UTF-8?q?e=20logEventLogin,SignUp=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/AccountCreation/AccountCreationView.swift | 2 +- Apps/LekaApp/Sources/Views/ConnectionView.swift | 2 +- .../Sources/Managers/Analytics/AnalyticsManager.swift | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Apps/LekaApp/Sources/Views/AccountCreation/AccountCreationView.swift b/Apps/LekaApp/Sources/Views/AccountCreation/AccountCreationView.swift index 96d48f91e..07f3de973 100644 --- a/Apps/LekaApp/Sources/Views/AccountCreation/AccountCreationView.swift +++ b/Apps/LekaApp/Sources/Views/AccountCreation/AccountCreationView.swift @@ -65,7 +65,7 @@ struct AccountCreationView: View { Alert(title: Text(l10n.AccountCreationView.EmailVerificationAlert.title), message: Text(l10n.AccountCreationView.EmailVerificationAlert.message), dismissButton: .default(Text(l10n.AccountCreationView.EmailVerificationAlert.dismissButton)) { - AnalyticsManager.shared.logSignUpEvent() + AnalyticsManager.shared.logEventSignUp() self.navigation.navigateToAccountCreationProcess = true }) } diff --git a/Apps/LekaApp/Sources/Views/ConnectionView.swift b/Apps/LekaApp/Sources/Views/ConnectionView.swift index f5311577a..d1db2a2b6 100644 --- a/Apps/LekaApp/Sources/Views/ConnectionView.swift +++ b/Apps/LekaApp/Sources/Views/ConnectionView.swift @@ -78,7 +78,7 @@ struct ConnectionView: View { self.caregiverManager.initializeCaregiversListener() self.carereceiverManager.initializeCarereceiversListener() self.rootAccountManager.initializeRootAccountListener() - AnalyticsManager.shared.logLoginEvent() + AnalyticsManager.shared.logEventLogin() self.authManagerViewModel.userAction = .none self.navigation.fullScreenCoverContent = nil } diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift index 8e1e06ef0..a7ec765cf 100644 --- a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -44,11 +44,11 @@ public class AnalyticsManager { // Recommended events methods - public func logLoginEvent() { + public func logEventLogin() { Analytics.logEvent(AnalyticsEventLogin, parameters: nil) } - public func logSignUpEvent() { + public func logEventSignUp() { Analytics.logEvent(AnalyticsEventSignUp, parameters: nil) } } From 69ea94670dbcf9f27130b43fc3da07c6e9349eeb Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 17:13:32 +0100 Subject: [PATCH 74/99] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(Analytics):=20Add?= =?UTF-8?q?=20logEventLogout=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Sources/Views/Settings/SettingsView.swift | 2 +- .../Sources/Managers/Analytics/AnalyticsManager.swift | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift b/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift index 865d0f1aa..fb9c077b5 100644 --- a/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift +++ b/Apps/LekaApp/Sources/Views/Settings/SettingsView.swift @@ -95,10 +95,10 @@ struct SettingsView: View { { Button(role: .destructive) { self.dismiss() - AnalyticsManager.shared.logEvent(name: "sign_out") self.authManager.signOut() self.persistentDataManager.clearUserData() self.reset() + AnalyticsManager.shared.logEventLogout() } label: { Text(l10n.SettingsView.AccountSection.LogOut.alertButtonLabel) } diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift index a7ec765cf..c07cf71ed 100644 --- a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -48,6 +48,10 @@ public class AnalyticsManager { Analytics.logEvent(AnalyticsEventLogin, parameters: nil) } + public func logEventLogout() { + Analytics.logEvent("logout", parameters: nil) + } + public func logEventSignUp() { Analytics.logEvent(AnalyticsEventSignUp, parameters: nil) } From 053c9029275b20c99195b002d2edb77acf099309 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Thu, 7 Nov 2024 19:01:30 +0200 Subject: [PATCH 75/99] =?UTF-8?q?=F0=9F=93=88=20(AccountKit):=20Add=20root?= =?UTF-8?q?=5Fowner=5Fuid=20as=20Analytics=20dflt=20parameter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Managers/RootAccounts/RootAccountManager.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManager.swift b/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManager.swift index 4d1a460e0..5eb4dff58 100644 --- a/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManager.swift +++ b/Modules/AccountKit/Sources/Managers/RootAccounts/RootAccountManager.swift @@ -25,6 +25,7 @@ public class RootAccountManager { }, receiveValue: { [weak self] rootAccount in guard let self else { return } self.currentRootAccount.send(rootAccount) + AnalyticsManager.shared.setDefaultEventParameters(["root_owner_uid": rootAccount.rootOwnerUid]) }) .store(in: &self.cancellables) } @@ -198,6 +199,7 @@ public class RootAccountManager { self.dbOps.clearAllListeners() self.cancellables.forEach { $0.cancel() } self.cancellables.removeAll() + AnalyticsManager.shared.setDefaultEventParameters(["root_owner_uid": "no_id"]) } // MARK: Internal From 173774f7e80ad16c2b5ef8615d87863a3fb445df Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Thu, 7 Nov 2024 10:52:42 +0200 Subject: [PATCH 76/99] =?UTF-8?q?=F0=9F=93=88=20(GEK):=20LogEvents=20Activ?= =?UTF-8?q?ity=5Fstart=20&=20Activity=5Fend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OldSystem/Views/Activity/ActivityView.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift b/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift index 2dd61f498..cc9424668 100644 --- a/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift +++ b/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift @@ -155,6 +155,7 @@ public struct ActivityView: View { .onAppear { Robot.shared.stop() UIApplication.shared.isIdleTimerDisabled = true + self.logActivityAnalytics(event: "activity_start") } .onDisappear { Robot.shared.stop() @@ -174,6 +175,8 @@ public struct ActivityView: View { @StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel() @StateObject private var carereceiverManagerViewModel = CarereceiverManagerViewModel() + private var carereceiverManager: CarereceiverManager = .shared + @State private var isAlertPresented: Bool = false @State private var opacity: Double = 1 @@ -214,6 +217,7 @@ public struct ActivityView: View { if self.viewModel.isLastExercise { self.viewModel.scorePanelEnabled ? self.viewModel.moveToActivityEnd() : self.dismiss() self.saveActivityCompletion() + self.logActivityAnalytics(event: "activity_end") } else { self.viewModel.moveToNextExercise() } @@ -402,6 +406,16 @@ public struct ActivityView: View { let carereceiverIDs = self.carereceiverManagerViewModel.currentCarereceivers.compactMap(\.id) self.viewModel.saveActivityCompletion(caregiverID: caregiverID, carereceiverIDs: carereceiverIDs) } + + private func logActivityAnalytics(event: String) { + let carereceiverIDs = self.carereceiverManager.currentCarereceivers.value.compactMap(\.id) + let carereceiverIDsString = carereceiverIDs.joined(separator: ",") + AnalyticsManager.shared.logEvent(name: event, parameters: [ + "activity_id": self.viewModel.currentActivity.id, + "activity_name": self.viewModel.currentActivity.name, + "carereceiver_ids": carereceiverIDsString, + ]) + } } // swiftlint:enable cyclomatic_complexity void_function_in_ternary function_body_length From 05fe4f5c552cb6c6d40cf9962d02c9940a74bca2 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Thu, 7 Nov 2024 20:26:39 +0100 Subject: [PATCH 77/99] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(Analytics):=20Creat?= =?UTF-8?q?e=20logEventActivityStart/End=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Managers/Analytics/AnalyticsManager.swift | 18 +++++++++++-- .../Views/Activity/ActivityView.swift | 26 ++++++++++--------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift index c07cf71ed..a35c54e9a 100644 --- a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -42,8 +42,6 @@ public class AnalyticsManager { self.setDefaultEventParameters(nil) } - // Recommended events methods - public func logEventLogin() { Analytics.logEvent(AnalyticsEventLogin, parameters: nil) } @@ -55,4 +53,20 @@ public class AnalyticsManager { public func logEventSignUp() { Analytics.logEvent(AnalyticsEventSignUp, parameters: nil) } + + public func logEventActivityStart(id: String, name: String, carereceiverIDs: String) { + Analytics.logEvent("activity_start", parameters: [ + "activity_id": id, + "activity_name": name, + "carereceiver_ids": carereceiverIDs, + ]) + } + + public func logEventActivityEnd(id: String, name: String, carereceiverIDs: String) { + Analytics.logEvent("activity_end", parameters: [ + "activity_id": id, + "activity_name": name, + "carereceiver_ids": carereceiverIDs, + ]) + } } diff --git a/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift b/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift index cc9424668..d666a8f6f 100644 --- a/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift +++ b/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift @@ -155,7 +155,13 @@ public struct ActivityView: View { .onAppear { Robot.shared.stop() UIApplication.shared.isIdleTimerDisabled = true - self.logActivityAnalytics(event: "activity_start") + + AnalyticsManager.shared + .logEventActivityStart( + id: self.viewModel.currentActivity.id, + name: self.viewModel.currentActivity.name, + carereceiverIDs: self.carereceiverManager.currentCarereceivers.value.compactMap(\.id).joined(separator: ",") + ) } .onDisappear { Robot.shared.stop() @@ -217,7 +223,13 @@ public struct ActivityView: View { if self.viewModel.isLastExercise { self.viewModel.scorePanelEnabled ? self.viewModel.moveToActivityEnd() : self.dismiss() self.saveActivityCompletion() - self.logActivityAnalytics(event: "activity_end") + + AnalyticsManager.shared + .logEventActivityEnd( + id: self.viewModel.currentActivity.id, + name: self.viewModel.currentActivity.name, + carereceiverIDs: self.carereceiverManager.currentCarereceivers.value.compactMap(\.id).joined(separator: ",") + ) } else { self.viewModel.moveToNextExercise() } @@ -406,16 +418,6 @@ public struct ActivityView: View { let carereceiverIDs = self.carereceiverManagerViewModel.currentCarereceivers.compactMap(\.id) self.viewModel.saveActivityCompletion(caregiverID: caregiverID, carereceiverIDs: carereceiverIDs) } - - private func logActivityAnalytics(event: String) { - let carereceiverIDs = self.carereceiverManager.currentCarereceivers.value.compactMap(\.id) - let carereceiverIDsString = carereceiverIDs.joined(separator: ",") - AnalyticsManager.shared.logEvent(name: event, parameters: [ - "activity_id": self.viewModel.currentActivity.id, - "activity_name": self.viewModel.currentActivity.name, - "carereceiver_ids": carereceiverIDsString, - ]) - } } // swiftlint:enable cyclomatic_complexity void_function_in_ternary function_body_length From f910e5819673879faebd8955daf50a7a2e52c4c3 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Fri, 8 Nov 2024 09:28:01 +0100 Subject: [PATCH 78/99] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(LekaApp):=20Refacto?= =?UTF-8?q?r=20Project=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Project.swift | 56 ++++++++----------- .../Project+App.swift | 28 ++++++++++ 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/Apps/LekaApp/Project.swift b/Apps/LekaApp/Project.swift index beea937f5..69535b633 100644 --- a/Apps/LekaApp/Project.swift +++ b/Apps/LekaApp/Project.swift @@ -7,48 +7,38 @@ import ProjectDescription import ProjectDescriptionHelpers -let kLekaAppVersion: String = if Environment.productionBuild.getBoolean(default: false) { - "1.13.0" +let kLekaApp: App = if Environment.productionBuild.getBoolean( + default: false +) { + .init( + version: "1.13.0", + bundleId: "io.leka.apf.app.LekaApp", + name: "Leka", + urlSchemes: "LekaApp", + appIcon: "AppIcon" + ) } else { - "99.00.00" -} - -let kLekaAppBundleName: String = if Environment.productionBuild.getBoolean(default: false) { - "Leka" -} else { - "Leka Beta" -} - -let kLekaAppBundleIdentifier: String = if Environment.productionBuild.getBoolean(default: false) { - "io.leka.apf.app.LekaApp" -} else { - "io.leka.apf.app.LekaApp.beta" -} - -let kLekaAppBundleURLSchemes: String = if Environment.productionBuild.getBoolean(default: false) { - "LekaApp" -} else { - "LekaAppBeta" -} - -let kLekaAppIconName: String = if Environment.productionBuild.getBoolean(default: false) { - "AppIcon" -} else { - "AppIconBeta" + .init( + version: "99.00.00", + bundleId: "io.leka.apf.app.LekaApp.beta", + name: "Leka Beta", + urlSchemes: "LekaAppBeta", + appIcon: "AppIconBeta" + ) } let project = Project.app( name: "LekaApp", - version: kLekaAppVersion, - bundleId: kLekaAppBundleIdentifier, + version: kLekaApp.version, + bundleId: kLekaApp.bundleId, infoPlist: [ "LSApplicationCategoryType": "public.app-category.education", - "CFBundleName": "\(kLekaAppBundleName)", + "CFBundleName": "\(kLekaApp.name)", "CFBundleURLTypes": [ [ "CFBundleTypeRole": "Editor", - "CFBundleURLName": "\(kLekaAppBundleIdentifier)", - "CFBundleURLSchemes": ["\(kLekaAppBundleURLSchemes)"], + "CFBundleURLName": "\(kLekaApp.bundleId)", + "CFBundleURLSchemes": ["\(kLekaApp.urlSchemes)"], ], ], "LSApplicationQueriesSchemes": ["LekaUpdater"], @@ -58,7 +48,7 @@ let project = Project.app( ], ], settings: SettingsDictionary.extendingBase(with: [ - "ASSETCATALOG_COMPILER_APPICON_NAME": "\(kLekaAppIconName)", + "ASSETCATALOG_COMPILER_APPICON_NAME": "\(kLekaApp.appIcon)", ]), dependencies: [ .project(target: "AccountKit", path: Path("../../Modules/AccountKit")), diff --git a/Tuist/ProjectDescriptionHelpers/Project+App.swift b/Tuist/ProjectDescriptionHelpers/Project+App.swift index e45ce4779..ff601abe7 100644 --- a/Tuist/ProjectDescriptionHelpers/Project+App.swift +++ b/Tuist/ProjectDescriptionHelpers/Project+App.swift @@ -6,6 +6,34 @@ import ProjectDescription +// MARK: - App + +public struct App: Sendable { + // MARK: Lifecycle + + public init( + version: String, + bundleId: String, + name: String, + urlSchemes: String, + appIcon: String + ) { + self.version = version + self.bundleId = bundleId + self.name = name + self.urlSchemes = urlSchemes + self.appIcon = appIcon + } + + // MARK: Public + + public let version: String + public let bundleId: String + public let name: String + public let urlSchemes: String + public let appIcon: String +} + public extension Project { static func app( name: String, From 62a1d2209b850960ec254ae4801765850fb0a65b Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Fri, 8 Nov 2024 09:28:54 +0100 Subject: [PATCH 79/99] =?UTF-8?q?=F0=9F=93=88=20(LekaApp):=20Turn=20off=20?= =?UTF-8?q?automatic=20screen=20recording?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Project.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Apps/LekaApp/Project.swift b/Apps/LekaApp/Project.swift index 69535b633..7f246eb03 100644 --- a/Apps/LekaApp/Project.swift +++ b/Apps/LekaApp/Project.swift @@ -46,6 +46,7 @@ let project = Project.app( "bluetooth-central", "audio", ], + "FirebaseAutomaticScreenReportingEnabled": "NO", ], settings: SettingsDictionary.extendingBase(with: [ "ASSETCATALOG_COMPILER_APPICON_NAME": "\(kLekaApp.appIcon)", From c4b8ea205257da97f938b738a2aade955ba1224a Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Fri, 8 Nov 2024 10:03:53 +0200 Subject: [PATCH 80/99] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20(AccountKit):=20A?= =?UTF-8?q?dd=20ContentType=20and=20ContentOrigin=20enums?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Managers/Analytics/AnalyticsManager.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift index a35c54e9a..c9a8e6849 100644 --- a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -14,6 +14,24 @@ public class AnalyticsManager { // MARK: Public + public enum ContentType: String { + case curriculum + case activity + case educationalGame = "educational_game" + case story + case gamepad + case resource + } + + public enum ContentOrigin: String { + case generalLibrary = "general_library" + case personalLibrary = "personal_library" + case searchResults = "search_results" + case resourcesFirstSteps = "resources_first_steps" + case resourcesVideos = "resources_videos" + case resourcesDeepDive = "resources_deep_dive" + } + public static let shared = AnalyticsManager() // MARK: Public Methods From c819e7d64bcc971df8255c20c125924bccd393c8 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Fri, 8 Nov 2024 10:06:03 +0200 Subject: [PATCH 81/99] =?UTF-8?q?=F0=9F=93=88=20(AccountKit):=20Add=20logE?= =?UTF-8?q?ventSelectContent=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Managers/Analytics/AnalyticsManager.swift | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift index c9a8e6849..f35142232 100644 --- a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -87,4 +87,25 @@ public class AnalyticsManager { "carereceiver_ids": carereceiverIDs, ]) } + + public func logEventSelectContent( + type: ContentType, + id: String, + name: String, + origin: ContentOrigin, + additionalParameters: [String: Any]? = nil + ) { + var parameters: [String: Any] = [ + AnalyticsParameterContentType: type.rawValue, + AnalyticsParameterItemID: id, + AnalyticsParameterItemName: name, + "content_origin": origin.rawValue, + ] + + if let additionalParameters { + parameters.merge(additionalParameters) { _, new in new } + } + + Analytics.logEvent(AnalyticsEventSelectContent, parameters: parameters) + } } From 7cbf179816c2c5cd0459f004d7d8124cc0f2bd34 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Fri, 8 Nov 2024 11:56:09 +0200 Subject: [PATCH 82/99] =?UTF-8?q?=F0=9F=93=88=20(LekaApp):=20Log=20Activit?= =?UTF-8?q?ies,=20Stories=20&=20Gamepads=20EventsSelect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library+ActivitiesView.swift | 2 +- .../Sources/Views/ActivityGridView.swift | 9 + .../Sources/Views/ActivityListView.swift | 8 + .../Sources/Views/GamepadGridView.swift | 9 + .../Views/LibraryActivityListView.swift | 168 ++++++++++++++++++ .../Sources/Views/StoryGridView.swift | 9 + .../Sources/Views/StoryListView.swift | 8 + 7 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 Modules/ContentKit/Sources/Views/LibraryActivityListView.swift diff --git a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift index bcfd05abe..c9190c5e7 100644 --- a/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift +++ b/Apps/LekaApp/Sources/Views/PersonalLibrary/Library+ActivitiesView.swift @@ -23,7 +23,7 @@ struct LibraryActivitiesView: View { EmptyLibraryPlaceholderView(icon: .activities) } else { ScrollView(showsIndicators: true) { - ActivityListView(activities: self.activities) { activity in + LibraryActivityListView(activities: self.activities) { activity in self.navigation.currentActivity = activity self.navigation.fullScreenCoverContent = .activityView(carereceivers: []) } diff --git a/Modules/ContentKit/Sources/Views/ActivityGridView.swift b/Modules/ContentKit/Sources/Views/ActivityGridView.swift index aa08e5338..bd9e2b2ac 100644 --- a/Modules/ContentKit/Sources/Views/ActivityGridView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityGridView.swift @@ -2,6 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 +import AccountKit import DesignKit import SwiftUI @@ -22,6 +23,14 @@ public struct ActivityGridView: View { ForEach(self.activities) { activity in NavigationLink(destination: ActivityDetailsView(activity: activity, onStartActivity: self.onStartActivity) + .onAppear { + AnalyticsManager.shared.logEventSelectContent( + type: .educationalGame, + id: activity.id, + name: activity.name, + origin: .generalLibrary + ) + } ) { VStack { Image(uiImage: activity.details.iconImage) diff --git a/Modules/ContentKit/Sources/Views/ActivityListView.swift b/Modules/ContentKit/Sources/Views/ActivityListView.swift index 2fa972875..4be040f3f 100644 --- a/Modules/ContentKit/Sources/Views/ActivityListView.swift +++ b/Modules/ContentKit/Sources/Views/ActivityListView.swift @@ -24,6 +24,14 @@ public struct ActivityListView: View { ForEach(self.activities) { activity in NavigationLink(destination: ActivityDetailsView(activity: activity, onStartActivity: self.onStartActivity) + .onAppear { + AnalyticsManager.shared.logEventSelectContent( + type: .activity, + id: activity.id, + name: activity.name, + origin: .generalLibrary + ) + } ) { HStack(alignment: .center) { Image(uiImage: activity.details.iconImage) diff --git a/Modules/ContentKit/Sources/Views/GamepadGridView.swift b/Modules/ContentKit/Sources/Views/GamepadGridView.swift index dc3ad84fb..0a1edacd3 100644 --- a/Modules/ContentKit/Sources/Views/GamepadGridView.swift +++ b/Modules/ContentKit/Sources/Views/GamepadGridView.swift @@ -2,6 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 +import AccountKit import DesignKit import SwiftUI @@ -22,6 +23,14 @@ public struct GamepadGridView: View { ForEach(self.gamepads) { activity in NavigationLink(destination: ActivityDetailsView(activity: activity, onStartActivity: self.onStartGamepad) + .onAppear { + AnalyticsManager.shared.logEventSelectContent( + type: .gamepad, + id: activity.id, + name: activity.name, + origin: .generalLibrary + ) + } ) { VStack { Image(uiImage: activity.details.iconImage) diff --git a/Modules/ContentKit/Sources/Views/LibraryActivityListView.swift b/Modules/ContentKit/Sources/Views/LibraryActivityListView.swift new file mode 100644 index 000000000..6632d1924 --- /dev/null +++ b/Modules/ContentKit/Sources/Views/LibraryActivityListView.swift @@ -0,0 +1,168 @@ +// Leka - iOS Monorepo +// Copyright APF France handicap +// SPDX-License-Identifier: Apache-2.0 + +import AccountKit +import DesignKit +import LocalizationKit +import SwiftUI + +// MARK: - ActivityListView + +public struct LibraryActivityListView: View { + // MARK: Lifecycle + + public init(activities: [Activity]? = nil, onStartActivity: ((Activity) -> Void)?) { + self.activities = activities ?? [] + self.onStartActivity = onStartActivity + } + + // MARK: Public + + public var body: some View { + LazyVStack(alignment: .leading, spacing: 20) { + ForEach(self.activities) { activity in + NavigationLink(destination: + ActivityDetailsView(activity: activity, onStartActivity: self.onStartActivity) + .onAppear { + AnalyticsManager.shared.logEventSelectContent( + type: .activity, + id: activity.id, + name: activity.name, + origin: .personalLibrary + ) + } + ) { + HStack(alignment: .center) { + Image(uiImage: activity.details.iconImage) + .resizable() + .scaledToFit() + .clipShape(Circle()) + .frame(width: 50) + .overlay( + Circle() + .stroke(self.styleManager.accentColor!, lineWidth: 1) + ) + + VStack(alignment: .leading) { + HStack { + Text(activity.details.title) + .font(.headline) + .frame(alignment: .leading) + } + + if let subtitle = activity.details.subtitle { + Text(subtitle) + .font(.subheadline) + .frame(alignment: .leading) + } + } + .padding(.vertical) + + Spacer() + + if let gestureIconUIImage = ContentKit.getGestureIconUIImage(for: activity) { + IconImageView(image: gestureIconUIImage) + } + + if let earFocusIconUIImage = ContentKit.getFocusIconUIImage(for: activity, ofType: .ears) { + IconImageView(image: earFocusIconUIImage) + } + + if let robotFocusIconUIImage = ContentKit.getFocusIconUIImage(for: activity, ofType: .robot) { + IconImageView(image: robotFocusIconUIImage) + } + + if let templateIconUIImage = ContentKit.getTemplateIconUIImage(for: activity) { + IconImageView(image: templateIconUIImage) + } + + #if DEVELOPER_MODE || TESTFLIGHT_BUILD + if let currentCaregiverID = self.caregiverManagerViewModel.currentCaregiver?.id { + Button {} label: { + Menu { + if self.rootAccountViewModel.isActivitySaved(activityID: activity.uuid) { + Button(role: .destructive) { + self.rootAccountViewModel.removeSavedActivity(activityID: activity.uuid) + } label: { + Label(String(l10n.Library.MenuActions.removeFromlibraryButtonLabel.characters), systemImage: "trash") + } + } else { + Button { + self.rootAccountViewModel.addSavedActivity( + activityID: activity.uuid, + caregiverID: currentCaregiverID + ) + } label: { + Label(String(l10n.Library.MenuActions.addTolibraryButtonLabel.characters), systemImage: "plus") + } + } + } label: { + Image(systemName: "ellipsis") + .bold() + } + .buttonStyle(TranslucentButtonStyle(color: self.styleManager.accentColor!)) + } + } + #endif + + Button { + self.onStartActivity?(activity) + } label: { + Image(systemName: "play.circle") + .font(.system(size: 24)) + .contentShape(Rectangle()) + } + .tint(.lkGreen) + .padding(.horizontal, 5) + } + .frame(maxWidth: .infinity, maxHeight: 120) + .contentShape(Rectangle()) + } + .buttonStyle(.plain) + } + } + .padding() + } + + // MARK: Internal + + let activities: [Activity] + let onStartActivity: ((Activity) -> Void)? + + // MARK: Private + + private struct IconImageView: View { + let image: UIImage? + + var body: some View { + Image(uiImage: self.image ?? UIImage()) + .resizable() + .scaledToFit() + .frame(width: 50) + .padding(.horizontal, 5) + } + } + + @ObservedObject private var styleManager: StyleManager = .shared + + @StateObject private var rootAccountViewModel = RootAccountManagerViewModel() + @StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel() +} + +#Preview { + NavigationSplitView { + Text("Sidebar") + } detail: { + NavigationStack { + ScrollView { + LibraryActivityListView( + activities: ContentKit.allActivities, + onStartActivity: { _ in + print("Activity Started") + } + ) + } + } + } +} diff --git a/Modules/ContentKit/Sources/Views/StoryGridView.swift b/Modules/ContentKit/Sources/Views/StoryGridView.swift index c00b3746f..d098bf744 100644 --- a/Modules/ContentKit/Sources/Views/StoryGridView.swift +++ b/Modules/ContentKit/Sources/Views/StoryGridView.swift @@ -2,6 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 +import AccountKit import DesignKit import SwiftUI @@ -22,6 +23,14 @@ public struct StoryGridView: View { ForEach(self.stories) { story in NavigationLink(destination: StoryDetailsView(story: story, onStartStory: self.onStartStory) + .onAppear { + AnalyticsManager.shared.logEventSelectContent( + type: .story, + id: story.id, + name: story.name, + origin: .generalLibrary + ) + } ) { VStack(spacing: 0) { Image(uiImage: story.details.iconImage) diff --git a/Modules/ContentKit/Sources/Views/StoryListView.swift b/Modules/ContentKit/Sources/Views/StoryListView.swift index 1a538546d..3133faed1 100644 --- a/Modules/ContentKit/Sources/Views/StoryListView.swift +++ b/Modules/ContentKit/Sources/Views/StoryListView.swift @@ -24,6 +24,14 @@ public struct StoryListView: View { ForEach(self.stories) { story in NavigationLink(destination: StoryDetailsView(story: story, onStartStory: self.onStartStory) + .onAppear { + AnalyticsManager.shared.logEventSelectContent( + type: .story, + id: story.id, + name: story.name, + origin: .personalLibrary + ) + } ) { HStack(alignment: .center, spacing: 30) { Image(uiImage: story.details.iconImage) From 9fe56ec23cb37a8f5d4e42a452c0aaa20f7a813f Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Fri, 8 Nov 2024 18:08:11 +0200 Subject: [PATCH 83/99] =?UTF-8?q?=F0=9F=93=88=20(ContentKit):=20Log=20curr?= =?UTF-8?q?iculums=20eventsSelect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Views/CurriculumGridView.swift | 17 +++++++++++++++-- .../Views/CurriculumHorizontalListView.swift | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Modules/ContentKit/Sources/Views/CurriculumGridView.swift b/Modules/ContentKit/Sources/Views/CurriculumGridView.swift index e8268def2..91fbcb355 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumGridView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumGridView.swift @@ -2,6 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 +import AccountKit import DesignKit import LocalizationKit import SwiftUI @@ -21,8 +22,20 @@ public struct CurriculumGridView: View { public var body: some View { LazyVGrid(columns: self.columns) { ForEach(self.curriculums) { curriculum in - NavigationLink(destination: - CurriculumDetailsView(curriculum: curriculum, onActivitySelected: self.onActivitySelected) + NavigationLink( + destination: + CurriculumDetailsView( + curriculum: curriculum, + onActivitySelected: self.onActivitySelected + ) + .onAppear { + AnalyticsManager.shared.logEventSelectContent( + type: .curriculum, + id: curriculum.id, + name: curriculum.name, + origin: .personalLibrary + ) + } ) { CurriculumGroupboxView(curriculum: curriculum) } diff --git a/Modules/ContentKit/Sources/Views/CurriculumHorizontalListView.swift b/Modules/ContentKit/Sources/Views/CurriculumHorizontalListView.swift index 381c9560a..438293e55 100644 --- a/Modules/ContentKit/Sources/Views/CurriculumHorizontalListView.swift +++ b/Modules/ContentKit/Sources/Views/CurriculumHorizontalListView.swift @@ -2,6 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 +import AccountKit import DesignKit import LocalizationKit import SwiftUI @@ -22,8 +23,20 @@ public struct CurriculumHorizontalListView: View { ScrollView(.horizontal) { HStack(alignment: .firstTextBaseline) { ForEach(self.curriculums) { curriculum in - NavigationLink(destination: - CurriculumDetailsView(curriculum: curriculum, onActivitySelected: self.onActivitySelected) + NavigationLink( + destination: + CurriculumDetailsView( + curriculum: curriculum, + onActivitySelected: self.onActivitySelected + ) + .onAppear { + AnalyticsManager.shared.logEventSelectContent( + type: .curriculum, + id: curriculum.id, + name: curriculum.name, + origin: .generalLibrary + ) + } ) { CurriculumGroupboxView(curriculum: curriculum) } From 72cc53c2ce80fbef3adcad52afc6828b476a6520 Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Fri, 8 Nov 2024 18:46:32 +0200 Subject: [PATCH 84/99] =?UTF-8?q?=F0=9F=93=88=20(AccountKit):=20Add=20comp?= =?UTF-8?q?letion=20parameter=20to=20logEventActivityEnd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Managers/Analytics/AnalyticsManager.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift index f35142232..6e146af8e 100644 --- a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -80,11 +80,17 @@ public class AnalyticsManager { ]) } - public func logEventActivityEnd(id: String, name: String, carereceiverIDs: String) { + public func logEventActivityEnd( + id: String, + name: String, + carereceiverIDs: String, + completion: String? = "completed" + ) { Analytics.logEvent("activity_end", parameters: [ "activity_id": id, "activity_name": name, "carereceiver_ids": carereceiverIDs, + "activity_completion": completion!, ]) } From be3108893070fa5885ff682ee9498cfd4e90e8ec Mon Sep 17 00:00:00 2001 From: "mathieu J." Date: Fri, 8 Nov 2024 19:00:21 +0200 Subject: [PATCH 85/99] =?UTF-8?q?=F0=9F=93=88=20(GEK):=20Log=20ActivityEnd?= =?UTF-8?q?=20as=20abandoned=20on=20quit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OldSystem/Views/Activity/ActivityView.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift b/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift index d666a8f6f..90224c050 100644 --- a/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift +++ b/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift @@ -2,7 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 -// swiftlint:disable cyclomatic_complexity void_function_in_ternary function_body_length +// swiftlint:disable cyclomatic_complexity void_function_in_ternary function_body_length type_body_length import AccountKit import Combine @@ -141,6 +141,13 @@ public struct ActivityView: View { }) Button(String(l10n.GameEngineKit.ActivityView.QuitActivityAlert.quitButtonLabel.characters), role: .destructive, action: { self.saveActivityCompletion() + AnalyticsManager.shared + .logEventActivityEnd( + id: self.viewModel.currentActivity.id, + name: self.viewModel.currentActivity.name, + carereceiverIDs: self.carereceiverManager.currentCarereceivers.value.compactMap(\.id).joined(separator: ","), + completion: "Abandoned" + ) self.dismiss() }) } message: { @@ -420,7 +427,7 @@ public struct ActivityView: View { } } -// swiftlint:enable cyclomatic_complexity void_function_in_ternary function_body_length +// swiftlint:enable cyclomatic_complexity void_function_in_ternary function_body_length type_body_length #Preview { NavigationStack { From 0da3cea89b7297043ca221a5bc2fa6cf2281ea27 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Mon, 11 Nov 2024 15:20:45 +0100 Subject: [PATCH 86/99] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(Analytics):=20Event?= =?UTF-8?q?=20activity=5Fend=20-=20use=20enum=20for=20reason?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Managers/Analytics/AnalyticsManager.swift | 9 +++++++-- .../Sources/OldSystem/Views/Activity/ActivityView.swift | 5 +++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift index 6e146af8e..e4e7f1bb7 100644 --- a/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift +++ b/Modules/AccountKit/Sources/Managers/Analytics/AnalyticsManager.swift @@ -32,6 +32,11 @@ public class AnalyticsManager { case resourcesDeepDive = "resources_deep_dive" } + public enum ActivityEndReason: String { + case userCompleted = "user_completed" + case userExited = "user_exited" + } + public static let shared = AnalyticsManager() // MARK: Public Methods @@ -84,13 +89,13 @@ public class AnalyticsManager { id: String, name: String, carereceiverIDs: String, - completion: String? = "completed" + reason: ActivityEndReason ) { Analytics.logEvent("activity_end", parameters: [ "activity_id": id, "activity_name": name, "carereceiver_ids": carereceiverIDs, - "activity_completion": completion!, + "activity_end_reason": reason.rawValue, ]) } diff --git a/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift b/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift index 90224c050..08884c308 100644 --- a/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift +++ b/Modules/GameEngineKit/Sources/OldSystem/Views/Activity/ActivityView.swift @@ -146,7 +146,7 @@ public struct ActivityView: View { id: self.viewModel.currentActivity.id, name: self.viewModel.currentActivity.name, carereceiverIDs: self.carereceiverManager.currentCarereceivers.value.compactMap(\.id).joined(separator: ","), - completion: "Abandoned" + reason: .userExited ) self.dismiss() }) @@ -235,7 +235,8 @@ public struct ActivityView: View { .logEventActivityEnd( id: self.viewModel.currentActivity.id, name: self.viewModel.currentActivity.name, - carereceiverIDs: self.carereceiverManager.currentCarereceivers.value.compactMap(\.id).joined(separator: ",") + carereceiverIDs: self.carereceiverManager.currentCarereceivers.value.compactMap(\.id).joined(separator: ","), + reason: .userCompleted ) } else { self.viewModel.moveToNextExercise() From a7b1976f788b85fac442829cd6d9c0537842a7d1 Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Wed, 30 Oct 2024 14:58:23 +0100 Subject: [PATCH 87/99] =?UTF-8?q?=E2=9C=A8=20(RobotKit):=20Add=20reboot=20?= =?UTF-8?q?command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modules/RobotKit/Sources/Robot.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Modules/RobotKit/Sources/Robot.swift b/Modules/RobotKit/Sources/Robot.swift index 75f0572e1..8df137d2c 100644 --- a/Modules/RobotKit/Sources/Robot.swift +++ b/Modules/RobotKit/Sources/Robot.swift @@ -67,6 +67,14 @@ public class Robot { public func reboot() { log.trace("🤖 REBOOT 💫") + let data = Data([1]) + + let rebootCharacteristic = CharacteristicModelWriteOnly( + characteristicUUID: BLESpecs.Monitoring.Characteristics.hardReboot, + serviceUUID: BLESpecs.Monitoring.service + ) + + self.connectedPeripheral?.send(data, forCharacteristic: rebootCharacteristic) } // MARK: - Magic Cards From 28d8824c7827c0161280f423e7aea3a1f8b70ca3 Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Wed, 30 Oct 2024 15:01:01 +0100 Subject: [PATCH 88/99] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20(Robo?= =?UTF-8?q?tKitExample):=20Add=20NavigationStack=20to=20access=20robot=20c?= =?UTF-8?q?onnection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RobotKit/Examples/RobotKitExample/Sources/MainView.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/RobotKit/Examples/RobotKitExample/Sources/MainView.swift b/Modules/RobotKit/Examples/RobotKitExample/Sources/MainView.swift index 00549719e..c9a79a24b 100644 --- a/Modules/RobotKit/Examples/RobotKitExample/Sources/MainView.swift +++ b/Modules/RobotKit/Examples/RobotKitExample/Sources/MainView.swift @@ -19,7 +19,9 @@ struct MainView: View { Text("Connect robot") } .fullScreenCover(isPresented: self.$presentRobotConnection) { - RobotConnectionView(viewModel: RobotConnectionViewModel()) + NavigationStack { + RobotConnectionView(viewModel: RobotConnectionViewModel()) + } } NavigationLink( From abb31ee8e8447f83f386b06fd38f32a187c5cfcc Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Wed, 30 Oct 2024 15:02:34 +0100 Subject: [PATCH 89/99] =?UTF-8?q?=F0=9F=9A=9A=20(RobotKit):=20Generalize?= =?UTF-8?q?=20deepsleeping=20into=20rebooting=20var?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/UI/ViewModels/RobotConnectionViewModel.swift | 8 ++++---- .../RobotKit/Sources/UI/Views/RobotConnectionView.swift | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/RobotKit/Sources/UI/ViewModels/RobotConnectionViewModel.swift b/Modules/RobotKit/Sources/UI/ViewModels/RobotConnectionViewModel.swift index cd3add014..f09fec23b 100644 --- a/Modules/RobotKit/Sources/UI/ViewModels/RobotConnectionViewModel.swift +++ b/Modules/RobotKit/Sources/UI/ViewModels/RobotConnectionViewModel.swift @@ -57,7 +57,7 @@ public class RobotConnectionViewModel: ObservableObject { return } - if discovery.isDeepSleeping, !self.connectingToDeepSleepingRobot { + if discovery.isDeepSleeping, !self.connectingToRebootingRobot { self.connectToRobotInDeepSleep() return } @@ -71,7 +71,7 @@ public class RobotConnectionViewModel: ObservableObject { self.robot.connectedPeripheral = peripheral self.connectedDiscovery = discovery self.selectedDiscovery = nil - self.connectingToDeepSleepingRobot = false + self.connectingToRebootingRobot = false log.info("🔵 BLE - Connected to \(self.robot.name.value)") } .store(in: &self.cancellables) @@ -82,7 +82,7 @@ public class RobotConnectionViewModel: ObservableObject { return } - self.connectingToDeepSleepingRobot = true + self.connectingToRebootingRobot = true self.bleManager.connect(discovery) .receive(on: DispatchQueue.main) @@ -120,7 +120,7 @@ public class RobotConnectionViewModel: ObservableObject { @Published var selectedDiscovery: RobotDiscoveryModel? @Published var connected: Bool = false - @Published var connectingToDeepSleepingRobot: Bool = false + @Published var connectingToRebootingRobot: Bool = false @Published var managerState: CBManagerState = .unknown @Published var connectedDiscovery: RobotDiscoveryModel? { diff --git a/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift b/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift index c33167bb3..7905d3303 100644 --- a/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift +++ b/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift @@ -19,7 +19,7 @@ public struct RobotConnectionView: View { public var body: some View { VStack(spacing: 10) { - if self.viewModel.connectingToDeepSleepingRobot { + if self.viewModel.connectingToRebootingRobot { ProgressView() Text(l10n.RobotKit.RobotConnectionView.rebootingDeepSleepingRobotText) } else if self.viewModel.connected { From c21c538fff446f3ec06ea77e97733a464dba293c Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Wed, 30 Oct 2024 17:39:44 +0100 Subject: [PATCH 90/99] =?UTF-8?q?=E2=9C=A8=20(RobotKit):=20Add=20robot=20r?= =?UTF-8?q?enaming=20feature?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/UI/Views/ConnectedRobotView.swift | 80 +++++++++++++++++-- .../UI/Views/RobotConnectionView.swift | 1 + 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift b/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift index 257ff30e4..15e0d18a0 100644 --- a/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift +++ b/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift @@ -22,12 +22,42 @@ public struct ConnectedRobotView: View { DesignKitAsset.Colors.lekaGreen.swiftUIColor, in: Circle().inset(by: -20.0) ) + VStack(alignment: .leading, spacing: 5) { - Text(self.connectedRobotInformationViewModel.name) - .font(.title) - .lineLimit(1) - .truncationMode(.tail) - .foregroundColor(.primary) + VStack { + if self.isEditingName { + TextField("Enter new name", text: self.$currentRobotName, onCommit: { + self.triggerRebootAlertPresented = true + self.focusedNameEdition = false + self.isEditingName = false + }) + .font(.title) + .lineLimit(1) + .truncationMode(.tail) + .foregroundColor(.primary) + .textFieldStyle(.roundedBorder) + .autocorrectionDisabled() + .focused(self.$focusedNameEdition) + .frame(maxWidth: 300) + } else { + HStack { + Text(self.connectedRobotInformationViewModel.name) + .font(.title) + .lineLimit(1) + .truncationMode(.tail) + .foregroundColor(.primary) + Image(systemName: "pencil.circle.fill") + .foregroundColor(.gray) + .font(.title) + } + .onTapGesture { + self.isEditingName = true + self.currentRobotName = self.connectedRobotInformationViewModel.name + self.focusedNameEdition = true + } + } + } + Text(l10n.ConnectedRobotView.serialNumberLabel(self.connectedRobotInformationViewModel.serialNumber)) .font(.caption) .lineLimit(1) @@ -88,17 +118,41 @@ public struct ConnectedRobotView: View { } } .navigationTitle(String(l10n.ConnectedRobotView.navigationTitle.characters)) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .contentShape(Rectangle()) + .simultaneousGesture(TapGesture().onEnded { + self.focusedNameEdition = false + self.isEditingName = false + }) + .alert(isPresented: self.$triggerRebootAlertPresented) { + Alert( + title: Text(self.waitingForRebootAlertPresented ? "Wait for reboot" : "Warning"), + message: Text("Your robot will reboot to set the new name"), + primaryButton: .default(Text("Reboot"), action: { + self.isEditingName = false + self.rename(in: self.currentRobotName) + self.waitingForRebootAlertPresented = true + }), + secondaryButton: .cancel() + ) + } } // MARK: Internal @StateObject var connectedRobotInformationViewModel: ConnectedRobotInformationViewModel = .init() @StateObject var viewModel: RobotConnectionViewModel + @State private var currentRobotName: String = "" + @State private var isEditingName: Bool = false + @State private var triggerRebootAlertPresented: Bool = false + @State private var waitingForRebootAlertPresented: Bool = false // swiftlint:disable:next force_cast private let isNotLekaUpdater = Bundle.main.infoDictionary?[kCFBundleNameKey as String] as! String != "LekaUpdater" + @FocusState private var focusedNameEdition: Bool @State private var showNotUpToDateAlert: Bool = false + private var robotNotUpToDate: Bool { guard let osVersion = Version(tolerant: self.connectedRobotInformationViewModel.osVersion) else { return false @@ -144,6 +198,22 @@ public struct ConnectedRobotView: View { .monospacedDigit() } } + + private func rename(in name: String) { + let dataName = name.data(using: .utf8)! + let robotNameCharacteristic = CharacteristicModelWriteOnly( + characteristicUUID: BLESpecs.Config.Characteristics.robotName, + serviceUUID: BLESpecs.Config.service, + onWrite: { + self.viewModel.selectedDiscovery = self.viewModel.connectedDiscovery + self.viewModel.connectingToRebootingRobot = true + DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: self.viewModel.connectToRobot) + self.connectedRobotInformationViewModel.robot.reboot() + } + ) + + self.connectedRobotInformationViewModel.robot.connectedPeripheral?.send(dataName, forCharacteristic: robotNameCharacteristic) + } } // MARK: - l10n.ConnectedRobotView diff --git a/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift b/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift index 7905d3303..f17f4f2bc 100644 --- a/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift +++ b/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift @@ -83,6 +83,7 @@ public struct RobotConnectionView: View { .opacity(self.viewModel.connected ? 0 : 1) } } + .interactiveDismissDisabled(self.viewModel.connectingToRebootingRobot) } // MARK: Internal From aae6c84bf3fbf203a4b01d7bbdc01ab99bb682e3 Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Wed, 30 Oct 2024 17:47:12 +0100 Subject: [PATCH 91/99] =?UTF-8?q?=F0=9F=9A=B8=20(RobotKit):=20Hide=20Conne?= =?UTF-8?q?ct=20button=20while=20connecting=20to=20rebooting=20robot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/UI/Views/RobotConnectionView.swift | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift b/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift index f17f4f2bc..ba42ba251 100644 --- a/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift +++ b/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift @@ -73,14 +73,16 @@ public struct RobotConnectionView: View { Text(l10n.RobotKit.RobotConnectionView.closeButton) } } - ToolbarItem(placement: .topBarTrailing) { - Button { - self.viewModel.connectToRobot() - } label: { - Text(l10n.RobotKit.RobotConnectionView.connectButton) + if !self.viewModel.connectingToRebootingRobot { + ToolbarItem(placement: .topBarTrailing) { + Button { + self.viewModel.connectToRobot() + } label: { + Text(l10n.RobotKit.RobotConnectionView.connectButton) + } + .disabled(self.viewModel.selectedDiscovery == nil) + .opacity(self.viewModel.connected ? 0 : 1) } - .disabled(self.viewModel.selectedDiscovery == nil) - .opacity(self.viewModel.connected ? 0 : 1) } } .interactiveDismissDisabled(self.viewModel.connectingToRebootingRobot) From 2615465d0e07ad7b07eeb36c329a64d9f3ea7de4 Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Thu, 31 Oct 2024 12:40:35 +0100 Subject: [PATCH 92/99] =?UTF-8?q?=F0=9F=9A=B8=20(RobotKit):=20Remove=20rec?= =?UTF-8?q?onnection=20process?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RobotKit/Sources/UI/Views/ConnectedRobotView.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift b/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift index 15e0d18a0..bef78e51a 100644 --- a/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift +++ b/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift @@ -131,7 +131,6 @@ public struct ConnectedRobotView: View { primaryButton: .default(Text("Reboot"), action: { self.isEditingName = false self.rename(in: self.currentRobotName) - self.waitingForRebootAlertPresented = true }), secondaryButton: .cancel() ) @@ -145,7 +144,6 @@ public struct ConnectedRobotView: View { @State private var currentRobotName: String = "" @State private var isEditingName: Bool = false @State private var triggerRebootAlertPresented: Bool = false - @State private var waitingForRebootAlertPresented: Bool = false // swiftlint:disable:next force_cast private let isNotLekaUpdater = Bundle.main.infoDictionary?[kCFBundleNameKey as String] as! String != "LekaUpdater" @@ -205,10 +203,10 @@ public struct ConnectedRobotView: View { characteristicUUID: BLESpecs.Config.Characteristics.robotName, serviceUUID: BLESpecs.Config.service, onWrite: { - self.viewModel.selectedDiscovery = self.viewModel.connectedDiscovery - self.viewModel.connectingToRebootingRobot = true - DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: self.viewModel.connectToRobot) self.connectedRobotInformationViewModel.robot.reboot() + self.viewModel.connectedDiscovery = nil + self.viewModel.selectedDiscovery = nil + self.dismiss() } ) From dc12d629d428d3489ef6e5437e362a565c54c5e8 Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Thu, 31 Oct 2024 12:42:19 +0100 Subject: [PATCH 93/99] =?UTF-8?q?=F0=9F=8C=90=20(RobotKit):=20Add=20rename?= =?UTF-8?q?=20alert=20l10n=20text?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RobotKit/Resources/Localizable.xcstrings | 36 +++++++++++++++++++ .../Sources/UI/Views/ConnectedRobotView.swift | 27 ++++++++++++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/Modules/RobotKit/Resources/Localizable.xcstrings b/Modules/RobotKit/Resources/Localizable.xcstrings index 9984d21d6..763b89171 100644 --- a/Modules/RobotKit/Resources/Localizable.xcstrings +++ b/Modules/RobotKit/Resources/Localizable.xcstrings @@ -38,6 +38,42 @@ } } }, + "robotkit.connected_robot_view.rename_alert_button_label": { + "comment": "The button label of the alert when renaming the robot", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Reboot" + } + } + } + }, + "robotkit.connected_robot_view.rename_alert_message": { + "comment": "The message of the alert when renaming the robot", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Your robot need to reboot to be renamed, please reconnect after the reboot" + } + } + } + }, + "robotkit.connected_robot_view.rename_alert_title": { + "comment": "The title of the alert when renaming the robot", + "extractionState": "extracted_with_value", + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "Warning" + } + } + } + }, "robotkit.connected_robot_view.robot_not_up_to_date_alert": { "comment": "Update is available alert", "extractionState": "extracted_with_value", diff --git a/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift b/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift index bef78e51a..8c5c1e1cf 100644 --- a/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift +++ b/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift @@ -126,9 +126,9 @@ public struct ConnectedRobotView: View { }) .alert(isPresented: self.$triggerRebootAlertPresented) { Alert( - title: Text(self.waitingForRebootAlertPresented ? "Wait for reboot" : "Warning"), - message: Text("Your robot will reboot to set the new name"), - primaryButton: .default(Text("Reboot"), action: { + title: Text(l10n.ConnectedRobotView.renameAlertTitle), + message: Text(l10n.ConnectedRobotView.renameAlertMessage), + primaryButton: .default(Text(l10n.ConnectedRobotView.renameAlertButtonLabel), action: { self.isEditingName = false self.rename(in: self.currentRobotName) }), @@ -238,6 +238,27 @@ extension l10n { value: "An update for Leka is available", comment: "Update is available alert" ) + + static let renameAlertTitle = LocalizedString( + "robotkit.connected_robot_view.rename_alert_title", + bundle: RobotKitResources.bundle, + value: "Warning", + comment: "The title of the alert when renaming the robot" + ) + + static let renameAlertMessage = LocalizedString( + "robotkit.connected_robot_view.rename_alert_message", + bundle: RobotKitResources.bundle, + value: "Your robot need to reboot to be renamed, please reconnect after the reboot", + comment: "The message of the alert when renaming the robot" + ) + + static let renameAlertButtonLabel = LocalizedString( + "robotkit.connected_robot_view.rename_alert_button_label", + bundle: RobotKitResources.bundle, + value: "Reboot", + comment: "The button label of the alert when renaming the robot" + ) } } From edde82a9c424d117f99e45b1c6afa94fc15208c7 Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Thu, 31 Oct 2024 16:50:32 +0100 Subject: [PATCH 94/99] =?UTF-8?q?=F0=9F=92=84=20(RobotKit):=20Improve=20re?= =?UTF-8?q?name=20button=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift b/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift index 8c5c1e1cf..35e75a19f 100644 --- a/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift +++ b/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift @@ -46,9 +46,9 @@ public struct ConnectedRobotView: View { .lineLimit(1) .truncationMode(.tail) .foregroundColor(.primary) - Image(systemName: "pencil.circle.fill") - .foregroundColor(.gray) - .font(.title) + Image(systemName: "pencil.circle") + .foregroundColor(self.styleManager.accentColor!) + .font(.title2) } .onTapGesture { self.isEditingName = true @@ -139,6 +139,7 @@ public struct ConnectedRobotView: View { // MARK: Internal + @StateObject private var styleManager: StyleManager = .shared @StateObject var connectedRobotInformationViewModel: ConnectedRobotInformationViewModel = .init() @StateObject var viewModel: RobotConnectionViewModel @State private var currentRobotName: String = "" From 591f106dc51b6bdbf7f4888a747798dc748aa60d Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Thu, 31 Oct 2024 16:52:06 +0100 Subject: [PATCH 95/99] =?UTF-8?q?=F0=9F=9A=9A=20(RobotKit):=20Move=20renam?= =?UTF-8?q?e=20function=20into=20Robot=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modules/RobotKit/Sources/Robot.swift | 13 +++++++++++++ .../Sources/UI/Views/ConnectedRobotView.swift | 19 ++----------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Modules/RobotKit/Sources/Robot.swift b/Modules/RobotKit/Sources/Robot.swift index 8df137d2c..63e4ac494 100644 --- a/Modules/RobotKit/Sources/Robot.swift +++ b/Modules/RobotKit/Sources/Robot.swift @@ -65,6 +65,19 @@ public class Robot { stopMotion() } + public func rename(in name: String) { + let dataName = name.data(using: .utf8)! + let robotNameCharacteristic = CharacteristicModelWriteOnly( + characteristicUUID: BLESpecs.Config.Characteristics.robotName, + serviceUUID: BLESpecs.Config.service, + onWrite: { + self.reboot() + } + ) + + self.connectedPeripheral?.send(dataName, forCharacteristic: robotNameCharacteristic) + } + public func reboot() { log.trace("🤖 REBOOT 💫") let data = Data([1]) diff --git a/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift b/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift index 35e75a19f..da7c67770 100644 --- a/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift +++ b/Modules/RobotKit/Sources/UI/Views/ConnectedRobotView.swift @@ -130,7 +130,8 @@ public struct ConnectedRobotView: View { message: Text(l10n.ConnectedRobotView.renameAlertMessage), primaryButton: .default(Text(l10n.ConnectedRobotView.renameAlertButtonLabel), action: { self.isEditingName = false - self.rename(in: self.currentRobotName) + self.connectedRobotInformationViewModel.robot.rename(in: self.currentRobotName) + self.dismiss() }), secondaryButton: .cancel() ) @@ -197,22 +198,6 @@ public struct ConnectedRobotView: View { .monospacedDigit() } } - - private func rename(in name: String) { - let dataName = name.data(using: .utf8)! - let robotNameCharacteristic = CharacteristicModelWriteOnly( - characteristicUUID: BLESpecs.Config.Characteristics.robotName, - serviceUUID: BLESpecs.Config.service, - onWrite: { - self.connectedRobotInformationViewModel.robot.reboot() - self.viewModel.connectedDiscovery = nil - self.viewModel.selectedDiscovery = nil - self.dismiss() - } - ) - - self.connectedRobotInformationViewModel.robot.connectedPeripheral?.send(dataName, forCharacteristic: robotNameCharacteristic) - } } // MARK: - l10n.ConnectedRobotView From 47432e634b10ab9c63a5e4d87d8d1322b54f15c1 Mon Sep 17 00:00:00 2001 From: Hugo Pezziardi Date: Thu, 31 Oct 2024 17:07:05 +0100 Subject: [PATCH 96/99] =?UTF-8?q?=F0=9F=90=9B=20(RobotKit):=20Fix=20robot?= =?UTF-8?q?=20connection=20display=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RobotKit/Sources/UI/Views/RobotConnectionView.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift b/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift index ba42ba251..49a77c3ff 100644 --- a/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift +++ b/Modules/RobotKit/Sources/UI/Views/RobotConnectionView.swift @@ -22,7 +22,7 @@ public struct RobotConnectionView: View { if self.viewModel.connectingToRebootingRobot { ProgressView() Text(l10n.RobotKit.RobotConnectionView.rebootingDeepSleepingRobotText) - } else if self.viewModel.connected { + } else if self.robotViewModel.isConnected { ConnectedRobotView(viewModel: self.viewModel) } else { switch self.viewModel.managerState { @@ -81,7 +81,7 @@ public struct RobotConnectionView: View { Text(l10n.RobotKit.RobotConnectionView.connectButton) } .disabled(self.viewModel.selectedDiscovery == nil) - .opacity(self.viewModel.connected ? 0 : 1) + .opacity(self.robotViewModel.isConnected ? 0 : 1) } } } @@ -93,11 +93,12 @@ public struct RobotConnectionView: View { @Environment(\.scenePhase) var scenePhase @StateObject var viewModel: RobotConnectionViewModel - @Environment(\.dismiss) var dismiss // MARK: Private + @StateObject private var robotViewModel: ConnectedRobotInformationViewModel = .init() + private let columns: [GridItem] = [ GridItem(), GridItem(), From b63b87e801f53c229d25e804ad549bbe1fbfe71e Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Tue, 12 Nov 2024 00:20:25 +0100 Subject: [PATCH 97/99] =?UTF-8?q?=F0=9F=91=B7=20(fastlane):=20Refactor=20r?= =?UTF-8?q?elease=20lane=20like=20beta=5Finternal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastlane/Fastfile | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 7bbb2358f..f832fd2f8 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -214,7 +214,11 @@ platform :ios do UI.header 'Step: Set target to build' UI.important "The following targets will be built: #{app}" - UI.header "Step: Generate, build & upload target: #{app}" + app_bundle_id = "io.leka.apf.app.#{app}" + app_xcodeproj = "#{ROOT_DIR}/Apps/#{app}/#{app}.xcodeproj" + + UI.header "Step: Generate, build & upload target: #{app} / #{app_bundle_id} / #{app_xcodeproj}" + Dir.chdir('..') do ENV['TUIST_TURN_OFF_LINTERS'] = 'TRUE' ENV['TUIST_GENERATE_MODULES_AS_FRAMEWORKS_FOR_DEBUG'] = 'FALSE' @@ -224,13 +228,10 @@ platform :ios do ENV['TUIST_TESTFLIGHT_BUILD'] = 'FALSE' ENV['TUIST_PRODUCTION_BUILD'] = 'TRUE' ENV['TUIST_FASTLANE_BUILD'] = 'TRUE' - ENV['TUIST_FASTLANE_APP_NAME'] = app.to_s - system('tuist', 'generate', '--no-open', app.to_s) + ENV['TUIST_FASTLANE_MATCH_APP_BUNDLE_ID'] = app_bundle_id.to_s + system('tuist', 'generate', '--no-open', '--no-binary-cache', app.to_s) end - app_id = "io.leka.apf.app.#{app}" - app_xcodeproj = "#{ROOT_DIR}/Apps/#{app}/#{app}.xcodeproj" - begin if ENV['CI'] app_store_connect_api_key( @@ -262,12 +263,12 @@ platform :ios do UI.header 'Step: Create verson and new build number' - latest_build_number = latest_testflight_build_number(app_identifier: app_id.to_s).to_s + latest_build_number = latest_testflight_build_number(app_identifier: app_bundle_id.to_s).to_s new_build_number = create_new_build_number(latest_build_number: latest_build_number) version_number = get_version_number(xcodeproj: app_xcodeproj.to_s) build_date = Time.new.strftime('%Y_%m_%d') - UI.important "Next release for: #{app}" + UI.important "Next release for: #{app_bundle_id}" UI.important "Version number: #{version_number}" UI.important "Build number: #{new_build_number}" UI.important "Metadata path: #{ROOT_DIR}/fastlane/release/#{app}/metadata" @@ -292,18 +293,19 @@ platform :ios do export_method: 'app-store', export_options: { provisioningProfiles: { - "io.leka.apf.app.#{app}" => "match AppStore io.leka.apf.app.#{app}" + app_bundle_id.to_s => "match AppStore #{app_bundle_id}" } }, workspace: 'ios-monorepo.xcworkspace', scheme: app, output_directory: './.build', - output_name: "#{build_date}-#{app}-v#{version_number}-#{new_build_number}" + output_name: "#{build_date}-#{app}-release-v#{version_number}-#{new_build_number}" ) upload_to_app_store( force: true, - app_identifier: app_id.to_s, + app_identifier: app_bundle_id.to_s, + ipa: "./.build/#{build_date}-#{app}-release-v#{version_number}-#{new_build_number}.ipa", metadata_path: "#{ROOT_DIR}/fastlane/release/#{app}/metadata", screenshots_path: "#{ROOT_DIR}/fastlane/release/#{app}/screenshots", reject_if_possible: true, From b01bd7941ff39cc7714a4b6e5878c7fd46a06428 Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Tue, 12 Nov 2024 12:10:59 +0100 Subject: [PATCH 98/99] =?UTF-8?q?=F0=9F=94=A8=20(fastlane):=20Get=20latest?= =?UTF-8?q?=20build=20number=20of=20specific=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastlane/Fastfile | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index f832fd2f8..e7ff187d2 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -148,9 +148,12 @@ platform :ios do UI.header 'Step: Create verson and new build number' - latest_build_number = latest_testflight_build_number(app_identifier: app_bundle_id.to_s).to_s - new_build_number = create_new_build_number(latest_build_number: latest_build_number) version_number = get_version_number(xcodeproj: app_xcodeproj.to_s) + latest_build_number = latest_testflight_build_number( + app_identifier: app_bundle_id.to_s, + version: version_number + ).to_s + new_build_number = create_new_build_number(latest_build_number: latest_build_number) build_date = Time.new.strftime('%Y_%m_%d') UI.important "Next release for: #{app_bundle_id}" @@ -263,9 +266,12 @@ platform :ios do UI.header 'Step: Create verson and new build number' - latest_build_number = latest_testflight_build_number(app_identifier: app_bundle_id.to_s).to_s - new_build_number = create_new_build_number(latest_build_number: latest_build_number) version_number = get_version_number(xcodeproj: app_xcodeproj.to_s) + latest_build_number = latest_testflight_build_number( + app_identifier: app_bundle_id.to_s, + version: version_number + ).to_s + new_build_number = create_new_build_number(latest_build_number: latest_build_number) build_date = Time.new.strftime('%Y_%m_%d') UI.important "Next release for: #{app_bundle_id}" From 233342e8844acb12cbdc711c751b679ff7b2031c Mon Sep 17 00:00:00 2001 From: Ladislas de Toldi Date: Tue, 12 Nov 2024 00:01:17 +0100 Subject: [PATCH 99/99] =?UTF-8?q?=F0=9F=94=96=20(LekaApp):=20Bump=20versio?= =?UTF-8?q?n=20to=20v1.14.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apps/LekaApp/Project.swift | 2 +- .../LekaApp/metadata/en-US/release_notes.txt | 14 +++++++++----- .../LekaApp/metadata/fr-FR/release_notes.txt | 14 +++++++++----- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Apps/LekaApp/Project.swift b/Apps/LekaApp/Project.swift index 7f246eb03..9f3f89e78 100644 --- a/Apps/LekaApp/Project.swift +++ b/Apps/LekaApp/Project.swift @@ -11,7 +11,7 @@ let kLekaApp: App = if Environment.productionBuild.getBoolean( default: false ) { .init( - version: "1.13.0", + version: "1.14.0", bundleId: "io.leka.apf.app.LekaApp", name: "Leka", urlSchemes: "LekaApp", diff --git a/fastlane/release/LekaApp/metadata/en-US/release_notes.txt b/fastlane/release/LekaApp/metadata/en-US/release_notes.txt index 7e5352a25..faf5b90f3 100644 --- a/fastlane/release/LekaApp/metadata/en-US/release_notes.txt +++ b/fastlane/release/LekaApp/metadata/en-US/release_notes.txt @@ -1,13 +1,17 @@ ### New Features -- Reinforcer Picker in Care Receiver Creation: Users can now select a reinforcer when creating a care receiver, personalizing the experience. +- Robot Renaming: You can now rename your robot directly within the app for a more personalized experience. ### Improvements -- Dance Freeze Auto Mode: Improved the auto mode behavior in the Dance Freeze activity for a smoother experience. -- User Interface Updates: Updated the robot action button icon and improved the overall UI in various sections. +- Update Alerts: The app will now notify you when a new update is available, ensuring you always have the latest features and improvements. +- User Interface Enhancements: Updated gesture icons for a better visual experience, reorganized sidebar content for easier navigation, and renamed the "Activities" section to "Educational Games" for clarity. ### Bug Fixes -- Resource Link Fix: Updated a dead link in the "Stop Card" video resource. -- Curriculum Assets: Fixed issues with assets in curriculums to ensure proper display. +- Resource Link Fix: Fixed a broken video link in the Resources section. +- Robot Connection Display Bug: Resolved an issue where the robot connection status was not displayed correctly. + +### Other + +- App Performance and Analytics: Implemented behind-the-scenes improvements to enhance app performance and gather user feedback for future updates. diff --git a/fastlane/release/LekaApp/metadata/fr-FR/release_notes.txt b/fastlane/release/LekaApp/metadata/fr-FR/release_notes.txt index 6570d2244..90b30b37e 100644 --- a/fastlane/release/LekaApp/metadata/fr-FR/release_notes.txt +++ b/fastlane/release/LekaApp/metadata/fr-FR/release_notes.txt @@ -1,13 +1,17 @@ ### Nouvelles Fonctionnalités -- Sélecteur de Renforçateur lors de la Création du Bénéficiaire de Soins : Les utilisateurs peuvent désormais sélectionner un renforçateur lors de la création d'un bénéficiaire de soins, personnalisant ainsi l'expérience. +- Renommage du Robot : Vous pouvez désormais renommer votre robot directement depuis l'application pour une expérience plus personnalisée. ### Améliorations -- Mode Automatique de Dance Freeze : Amélioration du comportement du mode automatique dans l'activité Dance Freeze pour une expérience plus fluide. -- Mises à Jour de l'Interface Utilisateur : Actualisation de l'icône du bouton d'action du robot et amélioration de l'interface utilisateur dans diverses sections. +- Alertes de Mise à Jour : L'application vous notifiera lorsqu'une nouvelle mise à jour est disponible, vous assurant ainsi de toujours bénéficier des dernières fonctionnalités et améliorations. +- Améliorations de l'Interface Utilisateur : Mise à jour des icônes de gestes pour une meilleure expérience visuelle, réorganisation du contenu de la barre latérale pour une navigation plus facile, et renommage de la section "Activités" en "Jeux Éducatifs" pour plus de clarté. ### Corrections de Bugs -- Correction du Lien de Ressource : Mise à jour d'un lien mort dans la ressource vidéo "Carte Stop". -- Assets du Curriculum : Correction de problèmes avec les assets dans les curriculums pour assurer un affichage correct. +- Correction de Lien de Ressource : Correction d'un lien vidéo cassé dans la section Ressources. +- Bug d'Affichage de la Connexion du Robot : Résolution d'un problème où le statut de connexion du robot n'était pas affiché correctement. + +### Autre + +- Performances de l'Application et Analytics : Mise en place d'améliorations en arrière-plan pour optimiser les performances de l'application et recueillir des retours utilisateurs pour les futures mises à jour.