From c4b7e38c1c96fb184fae7d5b3fbe4d7359bc331e Mon Sep 17 00:00:00 2001 From: VawnDao <134820492+VawnDao@users.noreply.github.com> Date: Mon, 2 Dec 2024 22:18:49 +0700 Subject: [PATCH] =?UTF-8?q?feat(study):=20hi=E1=BB=87n=20bottom=20sheet=20?= =?UTF-8?q?h=E1=BB=8Fi=20ng=C6=B0=E1=BB=9Di=20d=C3=B9ng=20khi=20h=E1=BB=8D?= =?UTF-8?q?=20khi=20ch=C6=B0a=20h=E1=BB=8Dc=20xong=20(#86)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daocon <134820492+Daocon@users.noreply.github.com> --- .../detail/component/StudySetDetailTopBar.kt | 5 +- .../UnfinishedLearningBottomSheet.kt | 83 +++++++++++++++++++ .../studies/flip/FlipFlashCardScreen.kt | 32 ++++++- .../studies/quiz/LearnByQuizScreen.kt | 30 ++++++- .../true_false/LearnByTrueFalseScreen.kt | 31 ++++++- .../studies/write/LearnByWriteScreen.kt | 30 ++++++- 6 files changed, 196 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/component/UnfinishedLearningBottomSheet.kt diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/component/StudySetDetailTopBar.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/component/StudySetDetailTopBar.kt index 9affc45a..daf18daf 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/component/StudySetDetailTopBar.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/component/StudySetDetailTopBar.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape @@ -111,7 +110,7 @@ fun StudySetDetailTopAppBar( VerticalDivider( modifier = Modifier .padding(horizontal = 8.dp) - .height(16.dp) + .size(16.dp) ) Text( when (flashCardCount) { @@ -130,7 +129,7 @@ fun StudySetDetailTopAppBar( colors = TopAppBarDefaults.topAppBarColors( containerColor = Color.Transparent, ), - expandedHeight = if (isAIGenerated) 165.dp else 120.dp, + expandedHeight = if(isAIGenerated) 165.dp else 120.dp, collapsedHeight = 56.dp, navigationIcon = { IconButton( diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/component/UnfinishedLearningBottomSheet.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/component/UnfinishedLearningBottomSheet.kt new file mode 100644 index 00000000..c4d83334 --- /dev/null +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/component/UnfinishedLearningBottomSheet.kt @@ -0,0 +1,83 @@ +package com.pwhs.quickmem.presentation.app.study_set.studies.component + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme.colorScheme +import androidx.compose.material3.MaterialTheme.shapes +import androidx.compose.material3.MaterialTheme.typography +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.SheetState +import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun UnfinishedLearningBottomSheet( + modifier: Modifier = Modifier, + onDismissRequest: () -> Unit = {}, + onKeepLearningClick: () -> Unit = {}, + onEndSessionClick: () -> Unit = {}, + showUnfinishedLearningBottomSheet: Boolean = false, + sheetShowMoreState: SheetState = rememberModalBottomSheetState(), +) { + if (showUnfinishedLearningBottomSheet) { + ModalBottomSheet( + modifier = modifier, + onDismissRequest = onDismissRequest, + sheetState = sheetShowMoreState + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = "Wait, don't go yet! You'll miss out on completing this study set!", + style = typography.titleLarge, + modifier = Modifier.padding(bottom = 16.dp) + ) + Button( + onClick = onKeepLearningClick, + modifier = Modifier + .fillMaxWidth(), + shape = shapes.medium + ) { + Text( + text = "Keep Learning", + style = typography.bodyMedium.copy( + fontWeight = FontWeight.Bold + ) + ) + } + OutlinedButton( + onClick = onEndSessionClick, + colors = ButtonDefaults.outlinedButtonColors( + contentColor = colorScheme.onSurface.copy(alpha = 0.6f) + ), + modifier = Modifier + .padding(top = 4.dp) + .fillMaxWidth(), + shape = shapes.medium + ) { + Text( + text = "End Session", + style = typography.bodyMedium.copy( + fontWeight = FontWeight.Bold + ) + ) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/FlipFlashCardScreen.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/FlipFlashCardScreen.kt index bf83f502..fe336fcd 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/FlipFlashCardScreen.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/FlipFlashCardScreen.kt @@ -49,6 +49,7 @@ import com.pwhs.quickmem.presentation.app.study_set.studies.flip.component.FlipF import com.pwhs.quickmem.presentation.app.study_set.studies.flip.component.FlipFlashCardStatusRow import com.pwhs.quickmem.presentation.app.study_set.studies.flip.component.StudyFlipFlashCard import com.pwhs.quickmem.presentation.app.study_set.studies.component.StudyTopAppBar +import com.pwhs.quickmem.presentation.app.study_set.studies.component.UnfinishedLearningBottomSheet import com.pwhs.quickmem.presentation.component.LoadingOverlay import com.pwhs.quickmem.ui.theme.QuickMemTheme import com.pwhs.quickmem.util.toColor @@ -69,6 +70,7 @@ fun FlipFlashCardScreen( ) { val uiState by viewModel.uiState.collectAsState() val context = LocalContext.current + LaunchedEffect(key1 = true) { viewModel.uiEvent.collect { event -> when (event) { @@ -91,7 +93,7 @@ fun FlipFlashCardScreen( isSwipingRight = uiState.isSwipingRight, isEndOfList = uiState.isEndOfList, learningTime = uiState.learningTime, - onBackClicked = { + onEndSessionClick = { viewModel.onEvent(FlipFlashCardUiAction.OnBackClicked) }, currentCardIndex = uiState.currentCardIndex, @@ -141,7 +143,7 @@ fun FlipFlashCard( isSwipingRight: Boolean = false, isEndOfList: Boolean = false, learningTime: Long = 0L, - onBackClicked: () -> Unit = { }, + onEndSessionClick: () -> Unit = { }, onUpdatedCardIndex: (Int) -> Unit = { }, onSwipeRight: (Boolean) -> Unit = { }, onSwipeLeft: (Boolean) -> Unit = { }, @@ -158,6 +160,7 @@ fun FlipFlashCard( } val hintBottomSheetState = rememberModalBottomSheetState() val explanationBottomSheetState = rememberModalBottomSheetState() + var showUnfinishedLearningBottomSheet by remember { mutableStateOf(false) } val stillLearningColor = Color(0xffd05700) val knownColor = Color(0xff18ae79) val stackState = rememberStackState() @@ -181,7 +184,13 @@ fun FlipFlashCard( StudyTopAppBar( currentCardIndex = currentCardIndex, totalCards = flashCards.size, - onBackClicked = onBackClicked, + onBackClicked = { + if (isEndOfList) { + onEndSessionClick() + } else { + showUnfinishedLearningBottomSheet = true + } + }, isEnOfSet = isEndOfList, onRestartClicked = { onRestartClicked() @@ -424,6 +433,23 @@ fun FlipFlashCard( isShowBottomSheet = showExplanationBottomSheet, sheetState = explanationBottomSheetState ) + + if (showUnfinishedLearningBottomSheet) { + UnfinishedLearningBottomSheet( + showUnfinishedLearningBottomSheet = showUnfinishedLearningBottomSheet, + onDismissRequest = { + showUnfinishedLearningBottomSheet = false + }, + onKeepLearningClick = { + showUnfinishedLearningBottomSheet = false + }, + onEndSessionClick = { + onEndSessionClick() + showUnfinishedLearningBottomSheet = false + } + ) + } + } @Preview(showBackground = true, device = Devices.PIXEL_7_PRO) diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/LearnByQuizScreen.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/LearnByQuizScreen.kt index 06f7b7ec..196b4d21 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/LearnByQuizScreen.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/LearnByQuizScreen.kt @@ -43,6 +43,7 @@ import com.pwhs.quickmem.core.data.enums.QuizStatus import com.pwhs.quickmem.core.data.states.RandomAnswer import com.pwhs.quickmem.core.data.states.WrongAnswer import com.pwhs.quickmem.domain.model.flashcard.FlashCardResponseModel +import com.pwhs.quickmem.presentation.app.study_set.studies.component.UnfinishedLearningBottomSheet import com.pwhs.quickmem.presentation.app.study_set.studies.quiz.component.QuizFlashCardFinish import com.pwhs.quickmem.presentation.app.study_set.studies.quiz.component.QuizView import com.pwhs.quickmem.presentation.component.LoadingOverlay @@ -83,7 +84,7 @@ fun LearnByQuizScreen( LearnByQuiz( modifier = modifier, isLoading = uiState.isLoading, - onNavigateBack = { + onEndSessionClick = { resultNavigator.navigateBack(true) }, wrongAnswerCount = uiState.wrongAnswerCount, @@ -120,7 +121,7 @@ fun LearnByQuizScreen( @Composable fun LearnByQuiz( modifier: Modifier = Modifier, - onNavigateBack: () -> Unit = {}, + onEndSessionClick: () -> Unit = {}, isLoading: Boolean = false, wrongAnswerCount: Int = 0, listWrongAnswer: List = emptyList(), @@ -139,6 +140,7 @@ fun LearnByQuiz( var canResetState by remember { mutableStateOf(false) } val showHintBottomSheet = remember { mutableStateOf(false) } val hintBottomSheetState = rememberModalBottomSheetState() + var showUnfinishedLearningBottomSheet by remember { mutableStateOf(false) } var selectedAnswer by remember { mutableStateOf(null) } val scope = rememberCoroutineScope() var debounceJob: Job? = null @@ -156,7 +158,13 @@ fun LearnByQuiz( }, navigationIcon = { IconButton( - onClick = onNavigateBack + onClick = { + if (isEndOfList) { + onEndSessionClick() + } else { + showUnfinishedLearningBottomSheet = true + } + } ) { Icon( imageVector = Default.Clear, @@ -306,6 +314,22 @@ fun LearnByQuiz( } } } + + if (showUnfinishedLearningBottomSheet) { + UnfinishedLearningBottomSheet( + showUnfinishedLearningBottomSheet = showUnfinishedLearningBottomSheet, + onDismissRequest = { + showUnfinishedLearningBottomSheet = false + }, + onKeepLearningClick = { + showUnfinishedLearningBottomSheet = false + }, + onEndSessionClick = { + onEndSessionClick() + showUnfinishedLearningBottomSheet = false + } + ) + } } } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseScreen.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseScreen.kt index 9dbd88ed..f251ed25 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseScreen.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseScreen.kt @@ -46,6 +46,7 @@ import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import coil.compose.AsyncImage import com.pwhs.quickmem.domain.model.flashcard.FlashCardResponseModel +import com.pwhs.quickmem.presentation.app.study_set.studies.component.UnfinishedLearningBottomSheet import com.pwhs.quickmem.presentation.app.study_set.studies.true_false.component.TrueFalseButton import com.pwhs.quickmem.presentation.app.study_set.studies.true_false.component.TrueFalseFlashcardFinish import com.pwhs.quickmem.presentation.component.LoadingOverlay @@ -82,7 +83,7 @@ fun LearnByTrueFalseScreen( } LearnByTrueFalse( modifier = modifier, - onNavigateBack = { + onEndSessionClick = { viewModel.onEvent(LearnByTrueFalseUiAction.OnBackClicked) }, isLoading = uiState.isLoading, @@ -121,7 +122,7 @@ fun LearnByTrueFalse( studySetColor: Color = MaterialTheme.colorScheme.primary, flashCardList: List = emptyList(), randomQuestion: TrueFalseQuestion? = null, - onNavigateBack: () -> Unit = {}, + onEndSessionClick: () -> Unit = {}, onRestart: () -> Unit = {}, onAnswer: (Boolean, String) -> Unit = { _, _ -> }, wrongAnswerCount: Int = 0, @@ -131,6 +132,8 @@ fun LearnByTrueFalse( ) { var isImageViewerOpen by remember { mutableStateOf(false) } var definitionImageUri by remember { mutableStateOf("") } + var showUnfinishedLearningBottomSheet by remember { mutableStateOf(false) } + Scaffold( topBar = { CenterAlignedTopAppBar( @@ -145,7 +148,13 @@ fun LearnByTrueFalse( }, navigationIcon = { IconButton( - onClick = onNavigateBack + onClick = { + if (isEndOfList) { + onEndSessionClick() + } else { + showUnfinishedLearningBottomSheet = true + } + } ) { Icon( imageVector = Default.Clear, @@ -358,6 +367,22 @@ fun LearnByTrueFalse( } ) } + + if (showUnfinishedLearningBottomSheet) { + UnfinishedLearningBottomSheet( + showUnfinishedLearningBottomSheet = showUnfinishedLearningBottomSheet, + onDismissRequest = { + showUnfinishedLearningBottomSheet = false + }, + onKeepLearningClick = { + showUnfinishedLearningBottomSheet = false + }, + onEndSessionClick = { + onEndSessionClick() + showUnfinishedLearningBottomSheet = false + } + ) + } } } } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/write/LearnByWriteScreen.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/write/LearnByWriteScreen.kt index c129e810..4d57426d 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/write/LearnByWriteScreen.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/write/LearnByWriteScreen.kt @@ -63,6 +63,7 @@ import coil.compose.AsyncImage import com.pwhs.quickmem.R import com.pwhs.quickmem.core.data.enums.WriteStatus import com.pwhs.quickmem.domain.model.flashcard.FlashCardResponseModel +import com.pwhs.quickmem.presentation.app.study_set.studies.component.UnfinishedLearningBottomSheet import com.pwhs.quickmem.presentation.app.study_set.studies.write.component.WriteFlashcardFinish import com.pwhs.quickmem.presentation.component.LoadingOverlay import com.pwhs.quickmem.presentation.component.ViewImageDialog @@ -102,7 +103,7 @@ fun LearnByWriteScreen( } LearnByWrite( modifier = modifier, - onNavigateBack = { + onEndSessionClick = { viewModel.onEvent(LearnByWriteUiAction.OnBackClicked) }, isLoading = uiState.isLoading, @@ -136,7 +137,7 @@ fun LearnByWrite( studySetColor: Color = MaterialTheme.colorScheme.primary, flashCardList: List = emptyList(), writeQuestion: WriteQuestion? = null, - onNavigateBack: () -> Unit = {}, + onEndSessionClick: () -> Unit = {}, onRestart: () -> Unit = {}, wrongAnswerCount: Int = 0, learningTime: Long = 0, @@ -149,6 +150,7 @@ fun LearnByWrite( var userAnswer by rememberSaveable { mutableStateOf("") } val showHintBottomSheet = remember { mutableStateOf(false) } val hintBottomSheetState = rememberModalBottomSheetState() + var showUnfinishedLearningBottomSheet by remember { mutableStateOf(false) } val scope = rememberCoroutineScope() var debounceJob: Job? = null val imeState = rememberImeState() @@ -172,7 +174,13 @@ fun LearnByWrite( }, navigationIcon = { IconButton( - onClick = onNavigateBack + onClick = { + if (isEndOfList) { + onEndSessionClick() + } else { + showUnfinishedLearningBottomSheet = true + } + } ) { Icon( imageVector = Default.Clear, @@ -433,6 +441,22 @@ fun LearnByWrite( } } } + + if (showUnfinishedLearningBottomSheet) { + UnfinishedLearningBottomSheet( + showUnfinishedLearningBottomSheet = showUnfinishedLearningBottomSheet, + onDismissRequest = { + showUnfinishedLearningBottomSheet = false + }, + onKeepLearningClick = { + showUnfinishedLearningBottomSheet = false + }, + onEndSessionClick = { + onEndSessionClick() + showUnfinishedLearningBottomSheet = false + } + ) + } } } }