From 275ad9be1ec9d8b07f410df452bb6096e351c441 Mon Sep 17 00:00:00 2001 From: iliyangermanov Date: Fri, 31 May 2024 16:40:16 +0300 Subject: [PATCH] Add "Finish!" button on the end of the lesson --- .../kotlin/ui/screen/lesson/LessonScreen.kt | 9 ++++--- .../ui/screen/lesson/LessonViewState.kt | 2 ++ .../ui/screen/lesson/composable/CtaBar.kt | 17 +++++++++++++ .../screen/lesson/composable/LessonContent.kt | 3 +++ .../handler/OnFinishClickEventHandler.kt | 24 +++++++++++++++++++ .../lesson/mapper/LessonViewStateMapper.kt | 9 ++++++- .../learn/data/cms/lesson/demo/DemoLesson.kt | 8 +++---- .../kotlin/ivy/content/SoundsUrls.kt | 1 + 8 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 composeApp/src/commonMain/kotlin/ui/screen/lesson/handler/OnFinishClickEventHandler.kt diff --git a/composeApp/src/commonMain/kotlin/ui/screen/lesson/LessonScreen.kt b/composeApp/src/commonMain/kotlin/ui/screen/lesson/LessonScreen.kt index 1955841..5d138d1 100644 --- a/composeApp/src/commonMain/kotlin/ui/screen/lesson/LessonScreen.kt +++ b/composeApp/src/commonMain/kotlin/ui/screen/lesson/LessonScreen.kt @@ -7,10 +7,7 @@ import ivy.model.CourseId import ivy.model.LessonId import ui.navigation.Screen import ui.screen.lesson.composable.LessonContent -import ui.screen.lesson.handler.OnBackClickEventHandler -import ui.screen.lesson.handler.OnContinueClickEventHandler -import ui.screen.lesson.handler.OnSoundClickEventHandler -import ui.screen.lesson.handler.QuestionViewEventHandler +import ui.screen.lesson.handler.* import ui.screen.lesson.mapper.LessonTreeManager import ui.screen.lesson.mapper.LessonViewStateMapper @@ -28,6 +25,7 @@ class LessonScreen( register { OnContinueClickEventHandler(Di.get()) } register { QuestionViewEventHandler(Di.get()) } register { OnSoundClickEventHandler(Di.get()) } + register { OnFinishClickEventHandler(Di.get(), Di.get()) } register { LessonViewModel( courseId = courseId, @@ -40,7 +38,8 @@ class LessonScreen( Di.get(), Di.get(), Di.get(), - Di.get() + Di.get(), + Di.get(), ) ) } diff --git a/composeApp/src/commonMain/kotlin/ui/screen/lesson/LessonViewState.kt b/composeApp/src/commonMain/kotlin/ui/screen/lesson/LessonViewState.kt index 9a3a707..7c6ac08 100644 --- a/composeApp/src/commonMain/kotlin/ui/screen/lesson/LessonViewState.kt +++ b/composeApp/src/commonMain/kotlin/ui/screen/lesson/LessonViewState.kt @@ -65,6 +65,7 @@ sealed interface CtaViewState { val currentItemId: LessonItemIdViewState data class Continue(override val currentItemId: LessonItemIdViewState) : CtaViewState + data class Finish(override val currentItemId: LessonItemIdViewState) : CtaViewState } @Immutable @@ -128,6 +129,7 @@ sealed interface LessonViewEvent { data object OnBackClick : LessonViewEvent data class OnContinueClick(val currentItemId: LessonItemIdViewState) : LessonViewEvent data class OnSoundClick(val soundUrl: String) : LessonViewEvent + data class OnFinishClick(val currentItemId: LessonItemIdViewState) : LessonViewEvent } sealed interface QuestionViewEvent : LessonViewEvent { diff --git a/composeApp/src/commonMain/kotlin/ui/screen/lesson/composable/CtaBar.kt b/composeApp/src/commonMain/kotlin/ui/screen/lesson/composable/CtaBar.kt index d0c4999..0248f91 100644 --- a/composeApp/src/commonMain/kotlin/ui/screen/lesson/composable/CtaBar.kt +++ b/composeApp/src/commonMain/kotlin/ui/screen/lesson/composable/CtaBar.kt @@ -17,6 +17,7 @@ import ui.screen.lesson.LessonItemIdViewState fun CtaBar( viewState: CtaViewState, onContinueClick: (LessonItemIdViewState) -> Unit, + onFinishClick: (LessonItemIdViewState) -> Unit, modifier: Modifier = Modifier, ) { Box( @@ -29,6 +30,10 @@ fun CtaBar( is CtaViewState.Continue -> ContinueButton( onClick = { onContinueClick(viewState.currentItemId) } ) + + is CtaViewState.Finish -> FinishButton( + onClick = { onFinishClick(viewState.currentItemId) } + ) } } } @@ -43,4 +48,16 @@ private fun ContinueButton( text = "CONTINUE", onClick = onClick, ) +} + +@Composable +private fun FinishButton( + modifier: Modifier = Modifier, + onClick: () -> Unit, +) { + CtaButton( + modifier = modifier, + text = "FINISH!", + onClick = onClick, + ) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ui/screen/lesson/composable/LessonContent.kt b/composeApp/src/commonMain/kotlin/ui/screen/lesson/composable/LessonContent.kt index 541f108..a7b82b0 100644 --- a/composeApp/src/commonMain/kotlin/ui/screen/lesson/composable/LessonContent.kt +++ b/composeApp/src/commonMain/kotlin/ui/screen/lesson/composable/LessonContent.kt @@ -47,6 +47,9 @@ fun LessonContent( onContinueClick = { itemId -> onEvent(LessonViewEvent.OnContinueClick(itemId)) }, + onFinishClick = { itemId -> + onEvent(LessonViewEvent.OnFinishClick(itemId)) + } ) } } diff --git a/composeApp/src/commonMain/kotlin/ui/screen/lesson/handler/OnFinishClickEventHandler.kt b/composeApp/src/commonMain/kotlin/ui/screen/lesson/handler/OnFinishClickEventHandler.kt new file mode 100644 index 0000000..5267311 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ui/screen/lesson/handler/OnFinishClickEventHandler.kt @@ -0,0 +1,24 @@ +package ui.screen.lesson.handler + +import Platform +import ivy.content.SoundsUrls +import ui.EventHandler +import ui.navigation.Navigation +import ui.screen.lesson.LessonViewEvent +import ui.screen.lesson.LessonViewModel.LocalState +import ui.screen.lesson.LessonVmContext + +class OnFinishClickEventHandler( + private val platform: Platform, + private val navigation: Navigation, +) : + EventHandler { + override val eventTypes = setOf(LessonViewEvent.OnContinueClick::class) + + override suspend fun LessonVmContext.handleEvent( + event: LessonViewEvent.OnContinueClick + ) { + navigation.back() + platform.playSound(SoundsUrls.CompleteLesson) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ui/screen/lesson/mapper/LessonViewStateMapper.kt b/composeApp/src/commonMain/kotlin/ui/screen/lesson/mapper/LessonViewStateMapper.kt index 61cd2cc..1058a7f 100644 --- a/composeApp/src/commonMain/kotlin/ui/screen/lesson/mapper/LessonViewStateMapper.kt +++ b/composeApp/src/commonMain/kotlin/ui/screen/lesson/mapper/LessonViewStateMapper.kt @@ -29,7 +29,14 @@ class LessonViewStateMapper( null, is QuestionItem, is OpenQuestionItem, is ChoiceItem -> null - else -> CtaViewState.Continue(currentItem.id.toViewState()) + else -> { + platform.log(LogLevel.Debug, "Current item: $currentItem") + if (currentItem is LinearItem && currentItem.next == null) { + CtaViewState.Finish(currentItem.id.toViewState()) + } else { + CtaViewState.Continue(currentItem.id.toViewState()) + } + } } ) } diff --git a/server/src/main/kotlin/ivy/learn/data/cms/lesson/demo/DemoLesson.kt b/server/src/main/kotlin/ivy/learn/data/cms/lesson/demo/DemoLesson.kt index 7d55137..920abaf 100644 --- a/server/src/main/kotlin/ivy/learn/data/cms/lesson/demo/DemoLesson.kt +++ b/server/src/main/kotlin/ivy/learn/data/cms/lesson/demo/DemoLesson.kt @@ -74,14 +74,14 @@ fun demoLesson() = lessonContent { text = "Go to Question 1", onClick = LessonItemId("q1") ) - textItem("end") { - text = "End of demo lesson." - style = TextStyle.Body - } openQuestion("q2") { question = "What is the answer to the ultimate question of life, the universe, and everything?" correctAnswer = "42" } + textItem("end") { + text = "End of demo lesson." + style = TextStyle.Body + } } fun main() { diff --git a/shared/src/commonMain/kotlin/ivy/content/SoundsUrls.kt b/shared/src/commonMain/kotlin/ivy/content/SoundsUrls.kt index 80cb540..54b6a22 100644 --- a/shared/src/commonMain/kotlin/ivy/content/SoundsUrls.kt +++ b/shared/src/commonMain/kotlin/ivy/content/SoundsUrls.kt @@ -4,6 +4,7 @@ object SoundsUrls { val Ups = soundUrl("ups.wav") val Success = soundUrl("success.mp3") val Complete = soundUrl("complete.wav") + val CompleteLesson = soundUrl("complete-lesson.mp3") fun soundUrl(fileName: String): String = "https://github.com/ILIYANGERMANOV/ivy-resources/raw/master/ivy-learn/sounds/$fileName"