diff --git a/Apps/LekaApp/Sources/_NEWCodeBase/Views/MainView/MainView.swift b/Apps/LekaApp/Sources/_NEWCodeBase/Views/MainView/MainView.swift index 3513daa912..c1f397f7eb 100644 --- a/Apps/LekaApp/Sources/_NEWCodeBase/Views/MainView/MainView.swift +++ b/Apps/LekaApp/Sources/_NEWCodeBase/Views/MainView/MainView.swift @@ -137,9 +137,7 @@ struct MainView: View { .fullScreenCover(item: self.$navigation.currentActivity) { self.navigation.currentActivity = nil } content: { activity in - Text("Activity: \(activity.details.title)") - // TODO: (@ladislas) switch back to activity view - // ActivityView(activity: activity) + ActivityView(activity: activity) } .sheet(isPresented: self.$rootOwnerViewModel.isSettingsViewPresented) { SettingsView() diff --git a/Modules/ContentKit/Resources/Content/activities/examples/sample_1-5A670B59EB214A6AA11AB39D64D63990.activity.yml b/Modules/ContentKit/Resources/Content/activities/examples/sample_1-5A670B59EB214A6AA11AB39D64D63990.activity.yml index c4ba52ca09..275f53ea66 100644 --- a/Modules/ContentKit/Resources/Content/activities/examples/sample_1-5A670B59EB214A6AA11AB39D64D63990.activity.yml +++ b/Modules/ContentKit/Resources/Content/activities/examples/sample_1-5A670B59EB214A6AA11AB39D64D63990.activity.yml @@ -238,10 +238,10 @@ exercises_payload: type: sfsymbol - value: cloud.sun type: sfsymbol - - value: cloud.bolt.rain.fill + - value: cloud.bolt.rain type: sfsymbol isRightAnswer: true - - value: cloud.rain + - value: cloud.snow type: sfsymbol - instructions: @@ -260,5 +260,5 @@ exercises_payload: type: sfsymbol - value: airplane type: sfsymbol - - value: boat + - value: sailboat type: sfsymbol diff --git a/Modules/ContentKit/Resources/Content/activities/examples/sample_2-6102794F02D3423482E243BCBC7F8CA8.activity.yml b/Modules/ContentKit/Resources/Content/activities/examples/sample_2-6102794F02D3423482E243BCBC7F8CA8.activity.yml index d4c2ca2ee3..4abc077ff4 100644 --- a/Modules/ContentKit/Resources/Content/activities/examples/sample_2-6102794F02D3423482E243BCBC7F8CA8.activity.yml +++ b/Modules/ContentKit/Resources/Content/activities/examples/sample_2-6102794F02D3423482E243BCBC7F8CA8.activity.yml @@ -238,7 +238,7 @@ exercises_payload: type: sfsymbol - value: cloud.sun type: sfsymbol - - value: cloud.bolt.rain.fill + - value: cloud.bolt.rain type: sfsymbol isRightAnswer: true - value: cloud.rain @@ -260,5 +260,5 @@ exercises_payload: type: sfsymbol - value: airplane type: sfsymbol - - value: boat + - value: sailboat type: sfsymbol diff --git a/Modules/ContentKit/Resources/Content/activities/examples/sample_3-E7EE9CA4B13B49AF96CD77A9DF90833B.activity.yml b/Modules/ContentKit/Resources/Content/activities/examples/sample_3-E7EE9CA4B13B49AF96CD77A9DF90833B.activity.yml index 2a006e57a0..17ffe19729 100644 --- a/Modules/ContentKit/Resources/Content/activities/examples/sample_3-E7EE9CA4B13B49AF96CD77A9DF90833B.activity.yml +++ b/Modules/ContentKit/Resources/Content/activities/examples/sample_3-E7EE9CA4B13B49AF96CD77A9DF90833B.activity.yml @@ -238,7 +238,7 @@ exercises_payload: type: sfsymbol - value: cloud.sun type: sfsymbol - - value: cloud.bolt.rain.fill + - value: cloud.bolt.rain type: sfsymbol isRightAnswer: true - value: cloud.rain @@ -260,5 +260,5 @@ exercises_payload: type: sfsymbol - value: airplane type: sfsymbol - - value: boat + - value: sailboat type: sfsymbol diff --git a/Modules/ContentKit/Resources/Content/activities/examples/sample_4-81F6617499FE42ADB5B03B409462923E.activity.yml b/Modules/ContentKit/Resources/Content/activities/examples/sample_4-81F6617499FE42ADB5B03B409462923E.activity.yml index 7aacbeb5f6..6232e5ff27 100644 --- a/Modules/ContentKit/Resources/Content/activities/examples/sample_4-81F6617499FE42ADB5B03B409462923E.activity.yml +++ b/Modules/ContentKit/Resources/Content/activities/examples/sample_4-81F6617499FE42ADB5B03B409462923E.activity.yml @@ -238,7 +238,7 @@ exercises_payload: type: sfsymbol - value: cloud.sun type: sfsymbol - - value: cloud.bolt.rain.fill + - value: cloud.bolt.rain type: sfsymbol isRightAnswer: true - value: cloud.rain @@ -260,5 +260,5 @@ exercises_payload: type: sfsymbol - value: airplane type: sfsymbol - - value: boat + - value: sailboat type: sfsymbol diff --git a/Modules/ContentKit/Resources/Content/activities/examples/sample_5-725853C4DC7B4D84A45AA20385F389F1.activity.yml b/Modules/ContentKit/Resources/Content/activities/examples/sample_5-725853C4DC7B4D84A45AA20385F389F1.activity.yml index 0d76a17f37..b35aa261f1 100644 --- a/Modules/ContentKit/Resources/Content/activities/examples/sample_5-725853C4DC7B4D84A45AA20385F389F1.activity.yml +++ b/Modules/ContentKit/Resources/Content/activities/examples/sample_5-725853C4DC7B4D84A45AA20385F389F1.activity.yml @@ -238,7 +238,7 @@ exercises_payload: type: sfsymbol - value: cloud.sun type: sfsymbol - - value: cloud.bolt.rain.fill + - value: cloud.bolt.rain type: sfsymbol isRightAnswer: true - value: cloud.rain @@ -260,5 +260,5 @@ exercises_payload: type: sfsymbol - value: airplane type: sfsymbol - - value: boat + - value: sailboat type: sfsymbol diff --git a/Modules/ContentKit/Resources/Content/activities/examples/sample_6-2FE0B8BDD1B0497F87B32A390119DB98.activity.yml b/Modules/ContentKit/Resources/Content/activities/examples/sample_6-2FE0B8BDD1B0497F87B32A390119DB98.activity.yml index cec017e054..5e3ec2605a 100644 --- a/Modules/ContentKit/Resources/Content/activities/examples/sample_6-2FE0B8BDD1B0497F87B32A390119DB98.activity.yml +++ b/Modules/ContentKit/Resources/Content/activities/examples/sample_6-2FE0B8BDD1B0497F87B32A390119DB98.activity.yml @@ -238,7 +238,7 @@ exercises_payload: type: sfsymbol - value: cloud.sun type: sfsymbol - - value: cloud.bolt.rain.fill + - value: cloud.bolt.rain type: sfsymbol isRightAnswer: true - value: cloud.rain @@ -260,5 +260,5 @@ exercises_payload: type: sfsymbol - value: airplane type: sfsymbol - - value: boat + - value: sailboat type: sfsymbol diff --git a/Modules/ContentKit/Sources/Activity/Activity.swift b/Modules/ContentKit/Sources/Activity/Activity.swift index ec8700b61a..74f30a7de8 100644 --- a/Modules/ContentKit/Sources/Activity/Activity.swift +++ b/Modules/ContentKit/Sources/Activity/Activity.swift @@ -142,10 +142,10 @@ public extension Activity { public extension Activity { struct ExercisesPayload: Decodable { - // MARK: Internal + // MARK: Public - let options: Options - var exerciseGroups: [ExerciseGroup] + public let options: Options + public var exerciseGroups: [ExerciseGroup] // MARK: Private diff --git a/Modules/ContentKit/Sources/Activity/ActivityExerciseManager.swift b/Modules/ContentKit/Sources/Activity/CurrentActivityManager.swift similarity index 96% rename from Modules/ContentKit/Sources/Activity/ActivityExerciseManager.swift rename to Modules/ContentKit/Sources/Activity/CurrentActivityManager.swift index 274e36c3e7..c590643bf2 100644 --- a/Modules/ContentKit/Sources/Activity/ActivityExerciseManager.swift +++ b/Modules/ContentKit/Sources/Activity/CurrentActivityManager.swift @@ -2,7 +2,7 @@ // Copyright APF France handicap // SPDX-License-Identifier: Apache-2.0 -public class ActivityExerciseManager { +public class CurrentActivityManager { // MARK: Lifecycle public init(activity: Activity) { @@ -26,6 +26,8 @@ public class ActivityExerciseManager { public var currentGroupIndex: Int = 0 public var currentExerciseIndexInCurrentGroup: Int = 0 + public let activity: Activity + public var totalGroups: Int { self.activity.exercisePayload.exerciseGroups.count } @@ -64,8 +66,4 @@ public class ActivityExerciseManager { self.currentExerciseIndexInCurrentGroup = self.activity.exercisePayload.exerciseGroups[self.currentGroupIndex].exercises.count - 1 } } - - // MARK: Private - - private let activity: Activity } diff --git a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/ExerciseSharedData.swift b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/ExerciseSharedData.swift index 91eb4d08b0..fa81f47a8a 100644 --- a/Modules/GameEngineKit/Sources/_NewSystem/Exercises/ExerciseSharedData.swift +++ b/Modules/GameEngineKit/Sources/_NewSystem/Exercises/ExerciseSharedData.swift @@ -7,14 +7,14 @@ import SwiftUI public class ExerciseSharedData: ObservableObject { // MARK: Lifecycle - public init(sequenceIndex: Int, exerciseIndex: Int) { - self.sequenceIndex = sequenceIndex + public init(groupIndex: Int, exerciseIndex: Int) { + self.groupIndex = groupIndex self.exerciseIndex = exerciseIndex } public init() { self.exerciseIndex = 0 - self.sequenceIndex = 0 + self.groupIndex = 0 } // MARK: Internal @@ -22,7 +22,7 @@ public class ExerciseSharedData: ObservableObject { // TODO: (@HPezz): Add state setter function, and makes it private @Published var state: ExerciseState = .idle - let sequenceIndex: Int + let groupIndex: Int let exerciseIndex: Int var completionLevel: ExerciseState.CompletionLevel? { diff --git a/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityProgressBar.swift b/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityProgressBar.swift index 7c424b86e3..3d991e1504 100644 --- a/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityProgressBar.swift +++ b/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityProgressBar.swift @@ -9,24 +9,23 @@ struct ActivityProgressBar: View { // MARK: Internal @ObservedObject var viewModel: ActivityViewViewModel - let height: CGFloat = 30 var body: some View { HStack(spacing: 0) { Spacer() - ForEach(0.. Color { @@ -75,9 +76,9 @@ struct ActivityProgressBar: View { } } - private func progressBarMarkerColor(sequence: Int, exercise: Int) -> Color { + private func progressBarMarkerColor(group: Int, exercise: Int) -> Color { if let completedExerciseSharedData = self.viewModel.completedExercisesSharedData.first(where: { - $0.sequenceIndex == sequence + $0.groupIndex == group && $0.exerciseIndex == exercise }) { self.completionLevelToColor(level: completedExerciseSharedData.completionLevel) diff --git a/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityView.swift b/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityView.swift index 0da80c1d6f..b33ecf4654 100644 --- a/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityView.swift +++ b/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityView.swift @@ -16,8 +16,8 @@ import SwiftUI public struct ActivityView: View { // MARK: Lifecycle - public init(viewModel: ActivityViewViewModel) { - self.viewModel = viewModel + public init(activity: Activity) { + self._viewModel = StateObject(wrappedValue: ActivityViewViewModel(activity: activity)) } // MARK: Public @@ -32,7 +32,7 @@ public struct ActivityView: View { } if self.viewModel.isExerciseInstructionsButtonVisible { - ExerciseInstructionsButton(instructions: self.viewModel.currentExercise.instructions) + ExerciseInstructionsButton(instructions: self.viewModel.currentExercise.instructions!) } } @@ -42,7 +42,7 @@ public struct ActivityView: View { Spacer() } } - .id(self.viewModel.currentExerciseIndexInSequence) + .id(self.viewModel.currentExerciseIndexInCurrentGroup) .blur(radius: self.blurRadius) .opacity(self.opacity) .onChange(of: self.viewModel.isReinforcerAnimationVisible) { @@ -146,7 +146,8 @@ public struct ActivityView: View { @Environment(\.dismiss) var dismiss - @ObservedObject var viewModel: ActivityViewViewModel + // TODO: (@ladislas) was @ObservedObject, check why + @StateObject var viewModel: ActivityViewViewModel // MARK: Private @@ -301,6 +302,7 @@ public struct ActivityView: View { // swiftlint:enable cyclomatic_complexity void_function_in_ternary function_body_length #Preview { - let activity = ContentKit.decodeActivityDeprecated("activity-sample") - return ActivityView(viewModel: ActivityViewViewModel(activity: activity)) + NavigationStack { + ActivityView(activity: Activity.mock) + } } diff --git a/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityViewViewModel.swift b/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityViewViewModel.swift index e1ca3c6e3d..7e8fc3755f 100644 --- a/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityViewViewModel.swift +++ b/Modules/GameEngineKit/Sources/_NewSystem/Views/Activity/ActivityViewViewModel.swift @@ -6,26 +6,28 @@ import Combine import ContentKit import SwiftUI -public class ActivityViewViewModel: ObservableObject { +class ActivityViewViewModel: ObservableObject { // MARK: Lifecycle - public init(activity: ActivityDeprecated) { - self.sequenceManager = ActivityExerciseManager(activity: activity) - + init(activity: Activity) { self.currentActivity = activity - self.totalSequences = self.sequenceManager.totalSequences - self.currentSequenceIndex = self.sequenceManager.currentSequenceIndex + self.activityManager = CurrentActivityManager(activity: activity) + + self.totalGroups = self.activityManager.totalGroups + self.currentGroupIndex = self.activityManager.currentGroupIndex + + self.groupSizeEnumeration = self.activityManager.activity.exercisePayload.exerciseGroups.map(\.exercises.count) - self.totalExercisesInCurrentSequence = self.sequenceManager.totalExercisesInCurrentSequence - self.currentExerciseIndexInSequence = self.sequenceManager.currentExerciseIndexInSequence + self.totalExercisesInCurrentGroup = self.activityManager.totalExercisesInCurrentGroup + self.currentExerciseIndexInCurrentGroup = self.activityManager.currentExerciseIndexInCurrentGroup - self.currentExercise = self.sequenceManager.currentExercise - self.currentExerciseInterface = self.sequenceManager.currentExercise.interface + self.currentExercise = self.activityManager.currentExercise + self.currentExerciseInterface = self.activityManager.currentExercise.interface self.currentExerciseSharedData = ExerciseSharedData( - sequenceIndex: self.sequenceManager.currentSequenceIndex, - exerciseIndex: self.sequenceManager.currentExerciseIndexInSequence + groupIndex: self.activityManager.currentGroupIndex, + exerciseIndex: self.activityManager.currentExerciseIndexInCurrentGroup ) self.completedExercisesSharedData.append(self.currentExerciseSharedData) @@ -34,13 +36,14 @@ public class ActivityViewViewModel: ObservableObject { // MARK: Internal - @Published var currentActivity: ActivityDeprecated + @Published var currentActivity: Activity - @Published var totalSequences: Int - @Published var currentSequenceIndex: Int + @Published var totalGroups: Int + @Published var currentGroupIndex: Int + @Published var groupSizeEnumeration: [Int] - @Published var totalExercisesInCurrentSequence: Int - @Published var currentExerciseIndexInSequence: Int + @Published var totalExercisesInCurrentGroup: Int + @Published var currentExerciseIndexInCurrentGroup: Int @Published var currentExercise: Exercise @Published var currentExerciseInterface: Exercise.Interface @@ -85,28 +88,29 @@ public class ActivityViewViewModel: ObservableObject { } var isProgressBarVisible: Bool { - self.totalSequences > 1 || self.totalExercisesInCurrentSequence != 1 + self.totalGroups > 1 || self.totalExercisesInCurrentGroup != 1 } var isExerciseInstructionsButtonVisible: Bool { - !self.currentExercise.instructions.isEmpty + guard let instructions = self.currentExercise.instructions else { return false } + return !instructions.isEmpty } var isFirstExercise: Bool { - self.sequenceManager.isFirstExercise + self.activityManager.isFirstExercise } var isLastExercise: Bool { - self.sequenceManager.isLastExercise + self.activityManager.isLastExercise } func moveToNextExercise() { - self.sequenceManager.moveToNextExercise() + self.activityManager.moveToNextExercise() self.updateValues() } func moveToPreviousExercise() { - self.sequenceManager.moveToPreviousExercise() + self.activityManager.moveToPreviousExercise() self.updateValues() } @@ -116,20 +120,20 @@ public class ActivityViewViewModel: ObservableObject { // MARK: Private - private let sequenceManager: ActivityExerciseManager + private let activityManager: CurrentActivityManager private var cancellables: Set = [] private func updateValues() { - self.currentExercise = self.sequenceManager.currentExercise - self.currentExerciseInterface = self.sequenceManager.currentExercise.interface - self.currentSequenceIndex = self.sequenceManager.currentSequenceIndex - self.totalSequences = self.sequenceManager.totalSequences - self.currentExerciseIndexInSequence = self.sequenceManager.currentExerciseIndexInSequence - self.totalExercisesInCurrentSequence = self.sequenceManager.totalExercisesInCurrentSequence + self.currentExercise = self.activityManager.currentExercise + self.currentExerciseInterface = self.activityManager.currentExercise.interface + self.currentGroupIndex = self.activityManager.currentGroupIndex + self.totalGroups = self.activityManager.totalGroups + self.currentExerciseIndexInCurrentGroup = self.activityManager.currentExerciseIndexInCurrentGroup + self.totalExercisesInCurrentGroup = self.activityManager.totalExercisesInCurrentGroup self.currentExerciseSharedData = ExerciseSharedData( - sequenceIndex: self.sequenceManager.currentSequenceIndex, - exerciseIndex: self.sequenceManager.currentExerciseIndexInSequence + groupIndex: self.activityManager.currentGroupIndex, + exerciseIndex: self.activityManager.currentExerciseIndexInCurrentGroup ) self.completedExercisesSharedData.append(self.currentExerciseSharedData)