From 7a0a6ab15260d5a8cde3f8d8c249bc167a1b8b19 Mon Sep 17 00:00:00 2001 From: Nguyen Quang Minh Date: Sat, 14 Dec 2024 01:38:15 +0700 Subject: [PATCH] =?UTF-8?q?fix(ui):=20s=E1=BB=ADa=20l=E1=BB=97i=20giao=20d?= =?UTF-8?q?i=E1=BB=87n=20-=20s=E1=BB=ADa=20c=C3=A1c=20l=E1=BB=97i=20giao?= =?UTF-8?q?=20di=E1=BB=87n=20=E1=BB=9F=20m=C3=A0n=20h=C3=ACnh=20h=E1=BB=8D?= =?UTF-8?q?c=20-=20s=E1=BB=ADa=20l=E1=BB=97i=20giao=20di=E1=BB=87n=20c?= =?UTF-8?q?=C3=A1c=20item=20-=20s=E1=BB=ADa=20l=E1=BB=97i=20giao=20di?= =?UTF-8?q?=E1=BB=87n=20m=C3=A0n=20h=C3=ACnh=20study=20set=20detail=20-=20?= =?UTF-8?q?s=E1=BB=ADa=20l=E1=BB=97i=20giao=20di=E1=BB=87n=20m=C3=A0n=20h?= =?UTF-8?q?=C3=ACnh=20l=E1=BB=8Dc=20k=E1=BA=BFt=20qu=E1=BA=A3=20t=C3=ACm?= =?UTF-8?q?=20ki=E1=BA=BFm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quickmem/core/data/states/RandomAnswer.kt | 2 +- .../StudySetRemoteDataSourceImpl.kt | 4 +- .../data/paging/StudySetPagingSource.kt | 4 +- .../repository/StudySetRepositoryImpl.kt | 4 +- .../datasource/StudySetRemoteDataSource.kt | 4 +- .../domain/repository/StudySetRepository.kt | 4 +- .../app/home/components/ClassHomeItem.kt | 48 +++-- .../app/home/components/FolderHomeItem.kt | 46 +++-- .../app/home/components/StudySetHomeItem.kt | 7 +- .../library/classes/component/ClassItem.kt | 41 +++-- .../library/folder/component/FolderItem.kt | 35 ++-- .../study_set/component/StudySetItem.kt | 2 +- .../app/search_result/SearchResultScreen.kt | 4 +- .../app/search_result/SearchResultUiAction.kt | 4 +- .../app/search_result/SearchResultUiState.kt | 4 +- .../search_result/SearchResultViewModel.kt | 4 +- .../component/FilterStudySetBottomSheet.kt | 170 +++++++++--------- .../SearchResultCreatorEnum.kt | 2 +- .../{enum => enums}/SearchResultSizeEnum.kt | 2 +- .../detail/component/StudySetDetailTopBar.kt | 11 +- .../detail/material/StudySetFlipCard.kt | 42 ++++- .../detail/progress/StudySetDonutChart.kt | 27 ++- .../studies/component/StudyTopAppBar.kt | 3 +- .../studies/flip/FlipFlashCardViewModel.kt | 124 +++++++------ .../flip/component/FlipFlashCardFinish.kt | 1 + .../studies/flip/component/StudyFlipCard.kt | 135 ++++++++++---- .../studies/quiz/LearnByQuizScreen.kt | 28 ++- .../studies/quiz/LearnByQuizViewModel.kt | 4 +- .../quiz/component/LearnQuizCardAnswer.kt | 12 +- .../studies/quiz/component/QuizView.kt | 55 +++++- .../true_false/LearnByTrueFalseScreen.kt | 137 +++++++++----- .../true_false/LearnByTrueFalseUiState.kt | 1 + .../true_false/LearnByTrueFalseViewModel.kt | 10 +- .../true_false/component/TrueFalseButton.kt | 5 +- .../studies/write/LearnByWriteScreen.kt | 24 ++- app/src/main/res/drawable/ic_image_error.xml | 11 ++ app/src/main/res/values-vi/strings.xml | 11 +- app/src/main/res/values/strings.xml | 5 +- 38 files changed, 641 insertions(+), 396 deletions(-) rename app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/{enum => enums}/SearchResultCreatorEnum.kt (96%) rename app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/{enum => enums}/SearchResultSizeEnum.kt (97%) create mode 100644 app/src/main/res/drawable/ic_image_error.xml diff --git a/app/src/main/java/com/pwhs/quickmem/core/data/states/RandomAnswer.kt b/app/src/main/java/com/pwhs/quickmem/core/data/states/RandomAnswer.kt index 346957a7..22ffdf66 100644 --- a/app/src/main/java/com/pwhs/quickmem/core/data/states/RandomAnswer.kt +++ b/app/src/main/java/com/pwhs/quickmem/core/data/states/RandomAnswer.kt @@ -3,5 +3,5 @@ package com.pwhs.quickmem.core.data.states data class RandomAnswer( val answer: String = "", val isCorrect: Boolean = false, - val imageURL: String = "", + val answerImage: String = "", ) diff --git a/app/src/main/java/com/pwhs/quickmem/data/datasource/StudySetRemoteDataSourceImpl.kt b/app/src/main/java/com/pwhs/quickmem/data/datasource/StudySetRemoteDataSourceImpl.kt index 3a57f26c..36bb8d43 100644 --- a/app/src/main/java/com/pwhs/quickmem/data/datasource/StudySetRemoteDataSourceImpl.kt +++ b/app/src/main/java/com/pwhs/quickmem/data/datasource/StudySetRemoteDataSourceImpl.kt @@ -4,8 +4,8 @@ import com.pwhs.quickmem.data.mapper.study_set.toModel import com.pwhs.quickmem.data.remote.ApiService import com.pwhs.quickmem.domain.datasource.StudySetRemoteDataSource import com.pwhs.quickmem.domain.model.study_set.GetStudySetResponseModel -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultCreatorEnum -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultSizeEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultCreatorEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultSizeEnum import timber.log.Timber class StudySetRemoteDataSourceImpl( diff --git a/app/src/main/java/com/pwhs/quickmem/data/paging/StudySetPagingSource.kt b/app/src/main/java/com/pwhs/quickmem/data/paging/StudySetPagingSource.kt index 63c2208c..c2e328ba 100644 --- a/app/src/main/java/com/pwhs/quickmem/data/paging/StudySetPagingSource.kt +++ b/app/src/main/java/com/pwhs/quickmem/data/paging/StudySetPagingSource.kt @@ -4,8 +4,8 @@ import androidx.paging.PagingSource import androidx.paging.PagingState import com.pwhs.quickmem.domain.datasource.StudySetRemoteDataSource import com.pwhs.quickmem.domain.model.study_set.GetStudySetResponseModel -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultCreatorEnum -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultSizeEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultCreatorEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultSizeEnum import retrofit2.HttpException import java.io.IOException diff --git a/app/src/main/java/com/pwhs/quickmem/data/remote/repository/StudySetRepositoryImpl.kt b/app/src/main/java/com/pwhs/quickmem/data/remote/repository/StudySetRepositoryImpl.kt index eed6e092..ab89e5f3 100644 --- a/app/src/main/java/com/pwhs/quickmem/data/remote/repository/StudySetRepositoryImpl.kt +++ b/app/src/main/java/com/pwhs/quickmem/data/remote/repository/StudySetRepositoryImpl.kt @@ -29,8 +29,8 @@ import com.pwhs.quickmem.domain.model.study_set.UpdateStudySetRequestModel import com.pwhs.quickmem.domain.model.study_set.UpdateStudySetResponseModel import com.pwhs.quickmem.domain.model.subject.GetTop5SubjectResponseModel import com.pwhs.quickmem.domain.repository.StudySetRepository -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultCreatorEnum -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultSizeEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultCreatorEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultSizeEnum import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flow diff --git a/app/src/main/java/com/pwhs/quickmem/domain/datasource/StudySetRemoteDataSource.kt b/app/src/main/java/com/pwhs/quickmem/domain/datasource/StudySetRemoteDataSource.kt index ad426ed3..9e464b75 100644 --- a/app/src/main/java/com/pwhs/quickmem/domain/datasource/StudySetRemoteDataSource.kt +++ b/app/src/main/java/com/pwhs/quickmem/domain/datasource/StudySetRemoteDataSource.kt @@ -1,8 +1,8 @@ package com.pwhs.quickmem.domain.datasource import com.pwhs.quickmem.domain.model.study_set.GetStudySetResponseModel -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultCreatorEnum -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultSizeEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultCreatorEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultSizeEnum interface StudySetRemoteDataSource { suspend fun getSearchResultStudySets( diff --git a/app/src/main/java/com/pwhs/quickmem/domain/repository/StudySetRepository.kt b/app/src/main/java/com/pwhs/quickmem/domain/repository/StudySetRepository.kt index 4e12b256..021c63ae 100644 --- a/app/src/main/java/com/pwhs/quickmem/domain/repository/StudySetRepository.kt +++ b/app/src/main/java/com/pwhs/quickmem/domain/repository/StudySetRepository.kt @@ -16,8 +16,8 @@ import com.pwhs.quickmem.domain.model.study_set.SaveRecentAccessStudySetRequestM import com.pwhs.quickmem.domain.model.study_set.UpdateStudySetRequestModel import com.pwhs.quickmem.domain.model.study_set.UpdateStudySetResponseModel import com.pwhs.quickmem.domain.model.subject.GetTop5SubjectResponseModel -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultCreatorEnum -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultSizeEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultCreatorEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultSizeEnum import kotlinx.coroutines.flow.Flow interface StudySetRepository { diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/ClassHomeItem.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/ClassHomeItem.kt index 30005c26..12707b82 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/ClassHomeItem.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/ClassHomeItem.kt @@ -84,44 +84,42 @@ fun ClassHomeItem( } Row( modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { Text( text = when (classItem?.memberCount) { 0 -> stringResource(R.string.txt_no_members) 1 -> stringResource(R.string.txt_one_member) - else -> stringResource(R.string.txt_nums_members, classItem?.memberCount ?: 0) + else -> stringResource( + R.string.txt_nums_members, + classItem?.memberCount ?: 0 + ) }, style = typography.bodyMedium ) VerticalDivider( modifier = Modifier - .height(16.dp) - .padding(horizontal = 8.dp), + .height(16.dp), thickness = 1.dp, color = colorScheme.onSurface.copy(alpha = 0.12f) ) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - AsyncImage( - model = classItem?.owner?.avatarUrl, - contentDescription = stringResource(R.string.txt_user_avatar), - modifier = Modifier - .size(24.dp) - .clip(CircleShape), - contentScale = ContentScale.Crop - ) - Text( - text = classItem?.owner?.username ?: "", - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = typography.bodyMedium.copy( - fontWeight = FontWeight.Bold - ) + AsyncImage( + model = classItem?.owner?.avatarUrl, + contentDescription = stringResource(R.string.txt_user_avatar), + modifier = Modifier + .size(24.dp) + .clip(CircleShape), + contentScale = ContentScale.Crop + ) + Text( + text = classItem?.owner?.username ?: "", + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = typography.bodyMedium.copy( + fontWeight = FontWeight.Bold ) - } + ) } } } @@ -132,7 +130,7 @@ fun ClassHomeItem( private fun ClassItemPreview() { QuickMemTheme { Scaffold { - LazyRow ( + LazyRow( modifier = Modifier .padding(it) ) { diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/FolderHomeItem.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/FolderHomeItem.kt index 5feabbde..179f29dc 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/FolderHomeItem.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/FolderHomeItem.kt @@ -106,34 +106,28 @@ fun FolderHomeItem( ) VerticalDivider( modifier = Modifier - .height(16.dp) - .padding(horizontal = 8.dp), - thickness = 1.dp, + .height(16.dp), color = colorScheme.onSurface.copy(alpha = 0.12f) ) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - AsyncImage( - model = userResponseModel.avatarUrl, - contentDescription = stringResource(R.string.txt_user_avatar), - modifier = Modifier - .size(24.dp) - .clip(CircleShape) - .background(colorScheme.primary.copy(alpha = 0.1f)), - contentScale = ContentScale.Crop - ) - Text( - text = userResponseModel.username, - style = typography.bodyMedium.copy( - fontWeight = FontWeight.Bold, - color = colorScheme.onSurface, - ), - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } + AsyncImage( + model = userResponseModel.avatarUrl, + contentDescription = stringResource(R.string.txt_user_avatar), + modifier = Modifier + .size(24.dp) + .clip(CircleShape) + .background(colorScheme.primary.copy(alpha = 0.1f)), + contentScale = ContentScale.Crop + ) + Text( + text = userResponseModel.username, + style = typography.bodyMedium.copy( + fontWeight = FontWeight.Bold, + color = colorScheme.onSurface, + ), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } } } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/StudySetHomeItem.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/StudySetHomeItem.kt index 937007a6..a1a915a5 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/StudySetHomeItem.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/home/components/StudySetHomeItem.kt @@ -91,7 +91,7 @@ fun StudySetHomeItem( style = typography.bodySmall.toSpanStyle() .copy(fontWeight = FontWeight.Normal) ) { - append(" Flashcards") + append(" ${stringResource(R.string.txt_flashcards)}") } } } @@ -101,7 +101,10 @@ fun StudySetHomeItem( horizontalArrangement = Arrangement.spacedBy(8.dp), ) { Text( - text = stringResource(studySet?.subject?.subjectName ?: SubjectModel.defaultSubjects[0].subjectName), + text = stringResource( + studySet?.subject?.subjectName + ?: SubjectModel.defaultSubjects[0].subjectName + ), style = typography.bodySmall.copy( color = colorScheme.onSurface.copy(alpha = 0.6f) ) diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/library/classes/component/ClassItem.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/library/classes/component/ClassItem.kt index 89cf0a54..5bddfa01 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/library/classes/component/ClassItem.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/library/classes/component/ClassItem.kt @@ -79,41 +79,40 @@ fun ClassItem( } Row( modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { Text( text = when (classItem?.memberCount) { 0 -> stringResource(R.string.txt_no_members) 1 -> stringResource(R.string.txt_one_member) - else -> stringResource(R.string.txt_nums_members, classItem?.memberCount ?: 0) + else -> stringResource( + R.string.txt_nums_members, + classItem?.memberCount ?: 0 + ) }, style = typography.bodyMedium ) VerticalDivider( modifier = Modifier - .height(16.dp) - .padding(horizontal = 8.dp), + .height(16.dp), thickness = 1.dp, color = colorScheme.onSurface.copy(alpha = 0.12f) ) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - AsyncImage( - model = classItem?.owner?.avatarUrl, - contentDescription = stringResource(R.string.txt_user_avatar), - modifier = Modifier - .size(24.dp) - .clip(CircleShape), - contentScale = ContentScale.Crop + + AsyncImage( + model = classItem?.owner?.avatarUrl, + contentDescription = stringResource(R.string.txt_user_avatar), + modifier = Modifier + .size(24.dp) + .clip(CircleShape), + contentScale = ContentScale.Crop + ) + if (classItem != null) { + RoleUserText( + username = classItem.owner.username, + role = classItem.owner.role, ) - if (classItem != null) { - RoleUserText( - username = classItem.owner.username, - role = classItem.owner.role, - ) - } } } } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/library/folder/component/FolderItem.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/library/folder/component/FolderItem.kt index 30eb9c53..12e5bd9a 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/library/folder/component/FolderItem.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/library/folder/component/FolderItem.kt @@ -108,29 +108,22 @@ fun FolderItem( ) VerticalDivider( modifier = Modifier - .height(16.dp) - .padding(horizontal = 8.dp), - thickness = 1.dp, + .height(16.dp), color = colorScheme.onSurface.copy(alpha = 0.12f) ) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - AsyncImage( - model = userResponseModel.avatarUrl, - contentDescription = stringResource(R.string.txt_user_avatar), - modifier = Modifier - .size(24.dp) - .clip(CircleShape) - .background(colorScheme.primary.copy(alpha = 0.1f)), - contentScale = ContentScale.Crop - ) - RoleUserText( - username = userResponseModel.username, - role = userResponseModel.role, - ) - } + AsyncImage( + model = userResponseModel.avatarUrl, + contentDescription = stringResource(R.string.txt_user_avatar), + modifier = Modifier + .size(24.dp) + .clip(CircleShape) + .background(colorScheme.primary.copy(alpha = 0.1f)), + contentScale = ContentScale.Crop + ) + RoleUserText( + username = userResponseModel.username, + role = userResponseModel.role, + ) } } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/library/study_set/component/StudySetItem.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/library/study_set/component/StudySetItem.kt index e9993055..3066640f 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/library/study_set/component/StudySetItem.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/library/study_set/component/StudySetItem.kt @@ -94,7 +94,7 @@ fun StudySetItem( style = typography.bodySmall.toSpanStyle() .copy(fontWeight = FontWeight.Normal) ) { - append(" Flashcards") + append(" ${stringResource(R.string.txt_flashcards)}") } } } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultScreen.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultScreen.kt index b4628bb5..1c09f21a 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultScreen.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultScreen.kt @@ -46,8 +46,8 @@ import com.pwhs.quickmem.presentation.app.search_result.component.TopBarSearchRe import com.pwhs.quickmem.presentation.app.search_result.folder.ListResultFolderScreen import com.pwhs.quickmem.presentation.app.search_result.study_set.ListResultStudySetScreen import com.pwhs.quickmem.presentation.app.search_result.study_set.component.FilterStudySetBottomSheet -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultCreatorEnum -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultSizeEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultCreatorEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultSizeEnum import com.pwhs.quickmem.presentation.app.search_result.user.ListResultUserScreen import com.pwhs.quickmem.presentation.component.LoadingOverlay import com.pwhs.quickmem.ui.theme.QuickMemTheme diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultUiAction.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultUiAction.kt index df0a2c65..5e224b4c 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultUiAction.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultUiAction.kt @@ -2,8 +2,8 @@ package com.pwhs.quickmem.presentation.app.search_result import com.pwhs.quickmem.domain.model.color.ColorModel import com.pwhs.quickmem.domain.model.subject.SubjectModel -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultCreatorEnum -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultSizeEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultCreatorEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultSizeEnum sealed class SearchResultUiAction() { data object Refresh : SearchResultUiAction() diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultUiState.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultUiState.kt index 6a613375..6711fd69 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultUiState.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultUiState.kt @@ -2,8 +2,8 @@ package com.pwhs.quickmem.presentation.app.search_result import com.pwhs.quickmem.domain.model.color.ColorModel import com.pwhs.quickmem.domain.model.subject.SubjectModel -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultCreatorEnum -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultSizeEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultCreatorEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultSizeEnum data class SearchResultUiState( val query: String = "", diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultViewModel.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultViewModel.kt index 22373a8e..0c519447 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultViewModel.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/SearchResultViewModel.kt @@ -16,8 +16,8 @@ import com.pwhs.quickmem.domain.repository.AuthRepository import com.pwhs.quickmem.domain.repository.ClassRepository import com.pwhs.quickmem.domain.repository.FolderRepository import com.pwhs.quickmem.domain.repository.StudySetRepository -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultCreatorEnum -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultSizeEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultCreatorEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultSizeEnum import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/component/FilterStudySetBottomSheet.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/component/FilterStudySetBottomSheet.kt index 58541cc7..4d0152ee 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/component/FilterStudySetBottomSheet.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/component/FilterStudySetBottomSheet.kt @@ -1,7 +1,12 @@ package com.pwhs.quickmem.presentation.app.search_result.study_set.component -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.* import androidx.compose.runtime.* @@ -16,8 +21,8 @@ import com.pwhs.quickmem.R import com.pwhs.quickmem.domain.model.color.ColorModel import com.pwhs.quickmem.domain.model.subject.SubjectModel import com.pwhs.quickmem.presentation.app.search_result.component.TopBarSearch -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultCreatorEnum -import com.pwhs.quickmem.presentation.app.search_result.study_set.enum.SearchResultSizeEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultCreatorEnum +import com.pwhs.quickmem.presentation.app.search_result.study_set.enums.SearchResultSizeEnum import com.pwhs.quickmem.presentation.app.study_set.component.StudySetColorInput import com.pwhs.quickmem.presentation.app.study_set.component.StudySetSubjectBottomSheet import com.pwhs.quickmem.presentation.app.study_set.component.StudySetSubjectInput @@ -48,100 +53,99 @@ fun FilterStudySetBottomSheet( stringResource(it.subjectName).contains(searchSubjectQuery, ignoreCase = true) } - LazyColumn( - modifier = modifier - .fillMaxSize() - .background(Color.White) - .padding() - .padding(16.dp) - ) { - item { + Scaffold( + topBar = { TopBarSearch( title = stringResource(R.string.txt_filters), onNavigateBack = onNavigateBack, onResetClick = onResetClick ) } + ) { innerPadding -> + LazyColumn( + modifier = modifier + .fillMaxSize() + .padding(innerPadding) + .padding(16.dp) + ) { + item { + FilterSection( + title = stringResource(R.string.txt_number_of_terms), + options = SearchResultSizeEnum.entries.map { it.title }, + selectedOption = sizeModel.title, + onOptionSelected = { selectedContent -> + val selectedSize = + SearchResultSizeEnum.entries.first { it.title == selectedContent } + onSizeChange(selectedSize) + } + ) + } - item { Spacer(modifier = Modifier.height(16.dp)) } - - item { - FilterSection( - title = stringResource(R.string.txt_number_of_terms), - options = SearchResultSizeEnum.entries.map { it.title }, - selectedOption = sizeModel.title, - onOptionSelected = { selectedContent -> - val selectedSize = - SearchResultSizeEnum.entries.first { it.title == selectedContent } - onSizeChange(selectedSize) - } - ) - } + item { + FilterSection( + title = stringResource(R.string.txt_created_by), + options = SearchResultCreatorEnum.entries.map { it.title }, + selectedOption = creatorTypeModel.title, + onOptionSelected = { + val selectedCreator = + SearchResultCreatorEnum.entries.first { entry -> entry.title == it } + onCreatorChange(selectedCreator) + } + ) + } - item { - FilterSection( - title = stringResource(R.string.txt_created_by), - options = SearchResultCreatorEnum.entries.map { it.title }, - selectedOption = creatorTypeModel.title, - onOptionSelected = { - val selectedCreator = - SearchResultCreatorEnum.entries.first { entry -> entry.title == it } - onCreatorChange(selectedCreator) + item { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = stringResource(R.string.txt_ai_generated), + fontSize = 16.sp, + fontWeight = FontWeight.Bold + ) + Switch( + checked = isAiGenerated, + onCheckedChange = { onIsAiGeneratedChange(it) }, + ) } - ) - } + } - item { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text( - text = stringResource(R.string.txt_ai_generated), - fontSize = 16.sp, - fontWeight = FontWeight.Bold + item { + StudySetSubjectInput( + subjectModel = subjectModel, + onShowBottomSheet = { + showBottomSheetCreate = true + } ) - Switch( - checked = isAiGenerated, - onCheckedChange = { onIsAiGeneratedChange(it) }, + } + item { + StudySetColorInput( + colorModel = colorModel, + onColorChange = onColorChange ) } - } - - item { - StudySetSubjectInput( - subjectModel = subjectModel, - onShowBottomSheet = { - showBottomSheetCreate = true - } - ) - } - item { - StudySetColorInput( - colorModel = colorModel, - onColorChange = onColorChange - ) - } - item { Spacer(modifier = Modifier.height(8.dp)) } + item { Spacer(modifier = Modifier.height(8.dp)) } - item { - Button( - onClick = onApplyClick, - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 16.dp) - .height(50.dp), - ) { - Text( - text = stringResource(R.string.txt_apply), - color = Color.White, - fontSize = 16.sp, - fontWeight = FontWeight.Bold - ) + item { + Button( + onClick = onApplyClick, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 16.dp) + .height(50.dp), + ) { + Text( + text = stringResource(R.string.txt_apply), + color = Color.White, + fontSize = 16.sp, + fontWeight = FontWeight.Bold + ) + } } } } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enum/SearchResultCreatorEnum.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enums/SearchResultCreatorEnum.kt similarity index 96% rename from app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enum/SearchResultCreatorEnum.kt rename to app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enums/SearchResultCreatorEnum.kt index 3b0e3251..5976b666 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enum/SearchResultCreatorEnum.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enums/SearchResultCreatorEnum.kt @@ -1,4 +1,4 @@ -package com.pwhs.quickmem.presentation.app.search_result.study_set.enum +package com.pwhs.quickmem.presentation.app.search_result.study_set.enums enum class SearchResultCreatorEnum(val title: String, val query: String) { ALL(title = "All", query = "all"), diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enum/SearchResultSizeEnum.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enums/SearchResultSizeEnum.kt similarity index 97% rename from app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enum/SearchResultSizeEnum.kt rename to app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enums/SearchResultSizeEnum.kt index 5ada5b34..fed796db 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enum/SearchResultSizeEnum.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/search_result/study_set/enums/SearchResultSizeEnum.kt @@ -1,4 +1,4 @@ -package com.pwhs.quickmem.presentation.app.search_result.study_set.enum +package com.pwhs.quickmem.presentation.app.search_result.study_set.enums enum class SearchResultSizeEnum(val title: String, val query: String) { ALL(title = "All", query = "all"), 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 daf18daf..4002f037 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,6 +5,7 @@ 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 @@ -90,12 +91,12 @@ fun StudySetDetailTopAppBar( Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Start, + horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.clickable { onNavigateToUserDetail() } ) { AsyncImage( model = userResponse.avatarUrl, - contentDescription = "User Avatar", + contentDescription = stringResource(R.string.txt_user_avatar), modifier = Modifier .size(30.dp) .clip(CircleShape) @@ -105,12 +106,10 @@ fun StudySetDetailTopAppBar( style = typography.bodyMedium.copy( color = colorScheme.secondary ), - modifier = Modifier.padding(start = 8.dp) ) VerticalDivider( modifier = Modifier - .padding(horizontal = 8.dp) - .size(16.dp) + .height(16.dp) ) Text( when (flashCardCount) { @@ -129,7 +128,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/detail/material/StudySetFlipCard.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/material/StudySetFlipCard.kt index 2573e229..e844334d 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/material/StudySetFlipCard.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/material/StudySetFlipCard.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme.colorScheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -32,6 +33,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage +import com.pwhs.quickmem.presentation.component.ShowImageDialog @Composable fun calculateDynamicFontSize(text: String): androidx.compose.ui.unit.TextUnit { @@ -52,6 +54,8 @@ fun StudySetFlipCard( var isFlipped by remember { mutableStateOf(false) } var isAnimationFinished by remember { mutableStateOf(true) } + var isImageViewerOpen by remember { mutableStateOf(false) } + var questionImageUri by remember { mutableStateOf("") } val frontTextSize = calculateDynamicFontSize(frontText) val backTextSize = calculateDynamicFontSize(backText) @@ -105,10 +109,12 @@ fun StudySetFlipCard( ) { Text( text = frontText, - fontSize = frontTextSize, - fontWeight = FontWeight.Bold, - color = colorScheme.onBackground, - textAlign = TextAlign.Center, + style = MaterialTheme.typography.bodyMedium.copy( + fontWeight = FontWeight.Bold, + fontSize = backTextSize, + color = colorScheme.onBackground, + textAlign = TextAlign.Center, + ), maxLines = 10, overflow = TextOverflow.Ellipsis ) @@ -127,10 +133,14 @@ fun StudySetFlipCard( if (backText.isNotEmpty()) { Text( text = backText, - fontSize = backTextSize, - fontWeight = FontWeight.Normal, - color = colorScheme.onBackground, - textAlign = TextAlign.Start, + style = MaterialTheme.typography.bodyMedium.copy( + fontSize = frontTextSize, + color = colorScheme.onBackground, + textAlign = when { + backImage != null -> TextAlign.Start + else -> TextAlign.Center + } + ), maxLines = 10, overflow = TextOverflow.Ellipsis, modifier = Modifier.weight(1f) @@ -144,7 +154,11 @@ fun StudySetFlipCard( modifier = Modifier .width(100.dp) .height(100.dp) - .padding(8.dp), + .padding(8.dp) + .clickable { + isImageViewerOpen = true + questionImageUri = it + }, contentScale = ContentScale.Crop ) } @@ -152,4 +166,14 @@ fun StudySetFlipCard( } } } + + if (isImageViewerOpen) { + ShowImageDialog( + definitionImageUri = questionImageUri, + onDismissRequest = { + isImageViewerOpen = false + questionImageUri = "" + } + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/progress/StudySetDonutChart.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/progress/StudySetDonutChart.kt index 1210d3e4..5b8ec8e1 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/progress/StudySetDonutChart.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/detail/progress/StudySetDonutChart.kt @@ -86,16 +86,25 @@ fun StudySetDonutChart( val strokeWidth = 45f var startAngle = -90f - animatedPercentage.forEachIndexed { index, percentage -> - val sweepAngle = percentage * 360f - drawArc( - color = colors[index], - startAngle = startAngle, - sweepAngle = sweepAngle, - useCenter = false, - style = Stroke(width = strokeWidth) + if (total > 0) { + animatedPercentage.forEachIndexed { index, percentage -> + val sweepAngle = percentage * 360f + drawArc( + color = colors[index], + startAngle = startAngle, + sweepAngle = sweepAngle, + useCenter = false, + style = Stroke(width = strokeWidth) + ) + startAngle += sweepAngle + } + } else { + drawCircle( + color = color, + radius = radius - strokeWidth / 2, + center = center, + style = Stroke(width = strokeWidth), ) - startAngle += sweepAngle } drawOval( diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/component/StudyTopAppBar.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/component/StudyTopAppBar.kt index 6bbb70bd..424f76cf 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/component/StudyTopAppBar.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/component/StudyTopAppBar.kt @@ -76,7 +76,8 @@ fun StudyTopAppBar( ) { Icon( imageVector = Default.RestartAlt, - contentDescription = stringResource(R.string.txt_restart) + contentDescription = stringResource(R.string.txt_restart), + tint = studySetColor ) } } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/FlipFlashCardViewModel.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/FlipFlashCardViewModel.kt index ee295b7c..018d8011 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/FlipFlashCardViewModel.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/FlipFlashCardViewModel.kt @@ -206,10 +206,21 @@ class FlipFlashCardViewModel @Inject constructor( } is FlipFlashCardUiAction.OnSwapCard -> { + // reset other status _uiState.update { - it.copy(isSwapCard = !it.isSwapCard) + it.copy( + isSwapCard = !it.isSwapCard, + isRandomCard = false, + isEndOfList = false, + countKnown = 0, + countStillLearning = 0, + currentCardIndex = 0, + startTime = System.currentTimeMillis(), + flashCardList = emptyList() + ) } - restartStudySet() + + getFlashCard() } } } @@ -339,91 +350,92 @@ class FlipFlashCardViewModel @Inject constructor( val learnFrom = _uiState.value.learnFrom when (learnFrom) { LearnFrom.STUDY_SET -> { + viewModelScope.launch { val token = tokenManager.accessToken.firstOrNull() ?: "" studySetRepository.resetProgress( token = token, studySetId = _uiState.value.studySetId, resetType = ResetType.FLIP_STATUS.type - ) - .collect { resource -> - when (resource) { - is Resources.Error -> { - _uiState.update { - it.copy( - isLoading = false, - isEndOfList = true, - learningTime = 0, - ) - } + ).collect { resource -> + when (resource) { + is Resources.Error -> { + _uiState.update { + it.copy( + isLoading = false, + isEndOfList = true, + learningTime = 0, + ) } + } - is Resources.Loading -> { - _uiState.update { it.copy(isLoading = true) } - } + is Resources.Loading -> { + _uiState.update { it.copy(isLoading = true) } + } - is Resources.Success -> { - _uiState.update { - it.copy( - isLoading = false, - isEndOfList = false, - countKnown = 0, - countStillLearning = 0, - currentCardIndex = 0, - startTime = System.currentTimeMillis(), - flashCardList = emptyList() - ) - } - getFlashCard() + is Resources.Success -> { + _uiState.update { + it.copy( + isLoading = false, + isEndOfList = false, + countKnown = 0, + countStillLearning = 0, + currentCardIndex = 0, + startTime = System.currentTimeMillis(), + flashCardList = emptyList() + ) } + getFlashCard() } } + } } } LearnFrom.FOLDER -> { + viewModelScope.launch { val token = tokenManager.accessToken.firstOrNull() ?: "" folderRepository.resetProgress( token = token, folderId = _uiState.value.folderId, resetType = ResetType.FLIP_STATUS.type - ) - .collect { resource -> - when (resource) { - is Resources.Error -> { - _uiState.update { - it.copy( - isLoading = false, - isEndOfList = true, - learningTime = 0, - ) - } + ).collect { resource -> + when (resource) { + is Resources.Error -> { + _uiState.update { + it.copy( + isLoading = false, + isEndOfList = true, + learningTime = 0, + ) } + } - is Resources.Loading -> { - _uiState.update { it.copy(isLoading = true) } - } + is Resources.Loading -> { + _uiState.update { it.copy(isLoading = true) } + } - is Resources.Success -> { - _uiState.update { - it.copy( - isLoading = false, - isEndOfList = false, - countKnown = 0, - countStillLearning = 0, - currentCardIndex = 0, - startTime = System.currentTimeMillis(), - flashCardList = emptyList() - ) - } - getFlashCard() + is Resources.Success -> { + _uiState.update { + it.copy( + isLoading = false, + isEndOfList = false, + countKnown = 0, + countStillLearning = 0, + currentCardIndex = 0, + startTime = System.currentTimeMillis(), + flashCardList = emptyList() + ) } + getFlashCard() } } + } } } + LearnFrom.CLASS -> TODO() } } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/component/FlipFlashCardFinish.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/component/FlipFlashCardFinish.kt index cf0b4621..3b41bd9e 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/component/FlipFlashCardFinish.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/component/FlipFlashCardFinish.kt @@ -104,6 +104,7 @@ fun FlipFlashCardFinish( style = MaterialTheme.typography.bodyMedium.copy( fontWeight = FontWeight.Bold ), + textAlign = TextAlign.Center, modifier = Modifier.padding(16.dp) ) } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/component/StudyFlipCard.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/component/StudyFlipCard.kt index 174c5dd4..8e11704f 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/component/StudyFlipCard.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/flip/component/StudyFlipCard.kt @@ -5,6 +5,7 @@ import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints @@ -29,12 +30,15 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage +import coil.request.ImageRequest import com.pwhs.quickmem.R import com.pwhs.quickmem.domain.model.flashcard.FlashCardResponseModel @@ -148,25 +152,51 @@ fun StudyFlipFlashCard( } else -> { - Text( - text = flashCard.term, - style = typography.bodyLarge.copy( - fontSize = when { - // tiny - flashCard.term.length <= 5 -> 30.sp - // small - flashCard.term.length <= 10 -> 25.sp - // medium - flashCard.term.length <= 15 -> 20.sp - // large - else -> 15.sp + LazyColumn( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier.padding(30.dp) + ) { + item { + flashCard.termImageURL?.let { url -> + if (url.isEmpty()) { + return@let + } + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(flashCard.termImageURL) + .error(R.drawable.ic_image_error) + .build(), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .size(100.dp) + .padding(16.dp), + ) } - ), - textAlign = TextAlign.Center, - modifier = Modifier - .padding(40.dp) - .wrapContentSize(Alignment.Center), - ) + } + item { + Text( + text = flashCard.term, + style = typography.bodyLarge.copy( + fontSize = when { + // tiny + flashCard.term.length <= 5 -> 28.sp + // small + flashCard.term.length <= 10 -> 22.sp + // medium + flashCard.term.length <= 15 -> 18.sp + // large + else -> 13.sp + } + ), + textAlign = TextAlign.Center, + modifier = Modifier + .padding(30.dp) + .wrapContentSize(Alignment.Center), + ) + } + } } } } @@ -313,25 +343,51 @@ fun StudyFlipFlashCard( } else -> { - Text( - text = flashCard.term, - style = typography.bodyLarge.copy( - fontSize = when { - // tiny - flashCard.term.length <= 5 -> 28.sp - // small - flashCard.term.length <= 10 -> 22.sp - // medium - flashCard.term.length <= 15 -> 18.sp - // large - else -> 13.sp + LazyColumn( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier.padding(30.dp) + ) { + item { + flashCard.termImageURL?.let { url -> + if (url.isEmpty()) { + return@let + } + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(flashCard.termImageURL) + .error(R.drawable.ic_image_error) + .build(), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .size(100.dp) + .padding(16.dp), + ) } - ), - textAlign = TextAlign.Center, - modifier = Modifier - .padding(30.dp) - .wrapContentSize(Alignment.Center), - ) + } + item { + Text( + text = flashCard.term, + style = typography.bodyLarge.copy( + fontSize = when { + // tiny + flashCard.term.length <= 5 -> 28.sp + // small + flashCard.term.length <= 10 -> 22.sp + // medium + flashCard.term.length <= 15 -> 18.sp + // large + else -> 13.sp + } + ), + textAlign = TextAlign.Center, + modifier = Modifier + .padding(30.dp) + .wrapContentSize(Alignment.Center), + ) + } + } } } } @@ -397,12 +453,15 @@ fun StudyFlipFlashCard( return@let } AsyncImage( - model = flashCard.definitionImageURL, + model = ImageRequest.Builder(LocalContext.current) + .data(flashCard.definitionImageURL) + .error(R.drawable.ic_image_error) + .build(), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier .size(100.dp) - .padding(16.dp) + .padding(16.dp), ) } } 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 63b90391..b0d6d824 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 @@ -1,7 +1,10 @@ package com.pwhs.quickmem.presentation.app.study_set.studies.quiz import android.widget.Toast +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize @@ -11,7 +14,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons.Default import androidx.compose.material.icons.automirrored.filled.NavigateNext import androidx.compose.material.icons.filled.Clear -import androidx.compose.material.icons.filled.LightMode +import androidx.compose.material.icons.filled.Lightbulb import androidx.compose.material.icons.filled.RestartAlt import androidx.compose.material3.CenterAlignedTopAppBar import androidx.compose.material3.ExperimentalMaterial3Api @@ -159,6 +162,14 @@ fun LearnByQuiz( var selectedAnswer by remember { mutableStateOf(null) } val scope = rememberCoroutineScope() var debounceJob: Job? = null + var isButtonVisible by remember { mutableStateOf(true) } + + LaunchedEffect(currentCardIndex) { + isButtonVisible = false + delay(1500) + isButtonVisible = true + } + Scaffold( topBar = { CenterAlignedTopAppBar( @@ -205,8 +216,8 @@ fun LearnByQuiz( } ) { Icon( - imageVector = Default.LightMode, - contentDescription = "Hint", + imageVector = Default.Lightbulb, + contentDescription = stringResource(R.string.txt_hint), tint = studySetColor ) } @@ -217,7 +228,7 @@ fun LearnByQuiz( ) { Icon( imageVector = Default.RestartAlt, - contentDescription = "Restart", + contentDescription = stringResource(R.string.txt_restart), tint = studySetColor ) } @@ -227,7 +238,11 @@ fun LearnByQuiz( ) }, floatingActionButton = { - if (!isEndOfList) { + AnimatedVisibility( + visible = !isEndOfList && isButtonVisible, + enter = fadeIn(), + exit = fadeOut() + ) { FloatingActionButton( onClick = { debounceJob?.cancel() @@ -245,9 +260,10 @@ fun LearnByQuiz( ) { Icon( imageVector = Icons.AutoMirrored.Filled.NavigateNext, - contentDescription = "Next Flash Card" + contentDescription = stringResource(R.string.txt_next), ) } + } } ) { innerPadding -> diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/LearnByQuizViewModel.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/LearnByQuizViewModel.kt index 362d61dc..a9548ade 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/LearnByQuizViewModel.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/LearnByQuizViewModel.kt @@ -347,7 +347,7 @@ class LearnByQuizViewModel @Inject constructor( RandomAnswer( answer = it.definition, isCorrect = false, - imageURL = it.definitionImageURL ?: "" + answerImage = it.definitionImageURL ?: "" ) } .toMutableList() @@ -356,7 +356,7 @@ class LearnByQuizViewModel @Inject constructor( RandomAnswer( answer = currentCard.definition, isCorrect = true, - imageURL = currentCard.definitionImageURL ?: "" + answerImage = currentCard.definitionImageURL ?: "" ) ) return answers.shuffled() diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/component/LearnQuizCardAnswer.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/component/LearnQuizCardAnswer.kt index 1c4a969a..6ee12b19 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/component/LearnQuizCardAnswer.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/component/LearnQuizCardAnswer.kt @@ -46,7 +46,11 @@ fun LearnQuizCardAnswer( modifier = modifier.fillMaxWidth(), enabled = !isSelected, border = BorderStroke( - width = if (isCorrect || isIncorrect) 2.dp else 0.dp, + width = when { + isCorrect -> 2.dp + isIncorrect -> 2.dp + else -> 0.5.dp + }, color = when { isCorrect -> correctColor isIncorrect -> incorrectColor @@ -92,13 +96,13 @@ fun LearnQuizCardAnswer( else -> MaterialTheme.colorScheme.onSurface } ) - if (randomAnswer.imageURL.isNotEmpty()) { + if (randomAnswer.answerImage.isNotEmpty()) { AsyncImage( - model = randomAnswer.imageURL, + model = randomAnswer.answerImage, contentDescription = null, modifier = Modifier.clickable { isImageViewerOpen = true - definitionImageUri = randomAnswer.imageURL + definitionImageUri = randomAnswer.answerImage } ) } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/component/QuizView.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/component/QuizView.kt index e5af172e..13d9b093 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/component/QuizView.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/quiz/component/QuizView.kt @@ -1,10 +1,12 @@ package com.pwhs.quickmem.presentation.app.study_set.studies.quiz.component +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.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -18,14 +20,19 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import coil.compose.AsyncImage +import coil.request.ImageRequest import com.pwhs.quickmem.R import com.pwhs.quickmem.core.data.enums.QuizStatus import com.pwhs.quickmem.core.data.states.RandomAnswer import com.pwhs.quickmem.domain.model.flashcard.FlashCardResponseModel +import com.pwhs.quickmem.presentation.component.ShowImageDialog import com.pwhs.quickmem.ui.theme.correctColor import com.pwhs.quickmem.ui.theme.incorrectColor @@ -37,9 +44,10 @@ fun QuizView( onCorrectAnswer: (QuizStatus, String) -> Unit, canResetState: Boolean = false ) { + val feedbackString = stringResource(R.string.txt_select_an_answer) var isSelectCorrectAnswer by remember { mutableStateOf(false) } var selectedAnswer by remember { mutableStateOf("") } - var feedbackMessage by remember { mutableStateOf("Select an answer") } + var feedbackMessage by remember { mutableStateOf(feedbackString) } val correctMessages = listOf( stringResource(R.string.txt_great_job), stringResource(R.string.txt_well_done), @@ -52,9 +60,11 @@ fun QuizView( stringResource(R.string.txt_not_quite), stringResource(R.string.txt_keep_trying) ) + var isImageViewerOpen by remember { mutableStateOf(false) } + var questionImageUri by remember { mutableStateOf("") } LaunchedEffect(key1 = canResetState) { selectedAnswer = "" - feedbackMessage = "Select an answer" + feedbackMessage = feedbackString isSelectCorrectAnswer = false } @@ -86,12 +96,35 @@ fun QuizView( ), modifier = Modifier.weight(1f) ) + flashCard.termImageURL?.let { url -> + if (url.isEmpty()) { + return@let + } + AsyncImage( + model = ImageRequest.Builder(LocalContext.current) + .data(flashCard.termImageURL) + .error(R.drawable.ic_image_error) + .build(), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .size(100.dp) + .padding(16.dp) + .clickable { + isImageViewerOpen = true + questionImageUri = flashCard.termImageURL + }, + ) + } } Text( text = feedbackMessage, style = MaterialTheme.typography.bodyLarge.copy( - fontWeight = FontWeight.Bold, + fontWeight = when { + isSelectCorrectAnswer -> FontWeight.Bold + else -> FontWeight.Normal + }, color = when { correctMessages.contains(feedbackMessage) -> correctColor incorrectMessages.contains(feedbackMessage) -> incorrectColor @@ -103,7 +136,10 @@ fun QuizView( if (selectedAnswer.isNotEmpty() && flashCard.explanation?.isNotEmpty() == true) { Text( - text = "Explanation: ${flashCard.explanation}", + text = stringResource( + R.string.txt_flashcard_explanation, + flashCard.explanation + ), style = MaterialTheme.typography.bodyMedium.copy( color = MaterialTheme.colorScheme.onSurface ), @@ -133,4 +169,15 @@ fun QuizView( } } } + + // Image Viewer Dialog + if (isImageViewerOpen) { + ShowImageDialog( + definitionImageUri = questionImageUri, + onDismissRequest = { + isImageViewerOpen = false + questionImageUri = "" + } + ) + } } 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 7cd14393..f1f6fc4a 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 @@ -43,6 +43,7 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -81,7 +82,11 @@ fun LearnByTrueFalseScreen( } LearnByTrueFalseUiEvent.Finished -> { - Toast.makeText(context, "Finished", Toast.LENGTH_SHORT).show() + Toast.makeText( + context, + context.getString(R.string.txt_finished), + Toast.LENGTH_SHORT + ).show() } } } @@ -146,7 +151,7 @@ fun LearnByTrueFalse( isSwapCard: Boolean = false, ) { var isImageViewerOpen by remember { mutableStateOf(false) } - var definitionImageUri by remember { mutableStateOf("") } + var imageUri by remember { mutableStateOf("") } var showUnfinishedLearningBottomSheet by remember { mutableStateOf(false) } val unFinishedLearningBottomSheetState = rememberModalBottomSheetState() @@ -195,7 +200,7 @@ fun LearnByTrueFalse( ) { Icon( imageVector = Default.RestartAlt, - contentDescription = "Restart", + contentDescription = stringResource(R.string.txt_restart), tint = studySetColor ) } @@ -241,7 +246,10 @@ fun LearnByTrueFalse( style = MaterialTheme.typography.titleMedium.copy( color = studySetColor ), - modifier = Modifier.padding(8.dp) + modifier = Modifier + .padding(8.dp) + .fillMaxWidth(), + textAlign = TextAlign.Center ) } item { @@ -262,23 +270,50 @@ fun LearnByTrueFalse( modifier = Modifier .fillMaxSize() .padding(8.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { Text( - text = randomQuestion?.term ?: "", - style = MaterialTheme.typography.titleLarge.copy( - fontSize = when (randomQuestion?.term?.length - ?: 0) { - in 0..10 -> 24.sp - in 11..20 -> 20.sp - else -> 16.sp - } + text = "${stringResource(R.string.txt_term)}:", + style = MaterialTheme.typography.titleSmall.copy( + color = MaterialTheme.colorScheme.onSurface.copy( + alpha = 0.5f + ) ), - color = studySetColor, - modifier = Modifier.padding(8.dp) + modifier = Modifier.padding(8.dp), ) + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxSize() + ) { + if (randomQuestion?.termImageUrl?.isNotEmpty() == true) { + AsyncImage( + model = randomQuestion.termImageUrl, + contentDescription = stringResource(R.string.txt_term_image), + contentScale = ContentScale.Crop, + modifier = Modifier + .size(80.dp) + .clickable { + isImageViewerOpen = true + imageUri = randomQuestion.termImageUrl + } + ) + } + Text( + text = randomQuestion?.term ?: "", + style = MaterialTheme.typography.titleLarge.copy( + fontSize = when (randomQuestion?.term?.length + ?: 0) { + in 0..10 -> 24.sp + in 11..20 -> 20.sp + else -> 16.sp + }, + textAlign = TextAlign.Center + ), + modifier = Modifier + .padding(8.dp) + .fillMaxWidth(), + ) + } } } Spacer(modifier = Modifier.padding(8.dp)) @@ -299,35 +334,49 @@ fun LearnByTrueFalse( modifier = Modifier .fillMaxSize() .padding(8.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center ) { - if (randomQuestion?.definitionImageUrl?.isNotEmpty() == true) { - AsyncImage( - model = randomQuestion.definitionImageUrl, - contentDescription = "Definition Image", - contentScale = ContentScale.Crop, - modifier = Modifier - .size(80.dp) - .clickable { - isImageViewerOpen = true - definitionImageUri = - randomQuestion.definitionImageUrl - } - ) - } Text( - text = randomQuestion?.definition ?: "", - style = MaterialTheme.typography.bodyMedium.copy( - fontSize = when (randomQuestion?.definition?.length - ?: 0) { - in 0..10 -> 16.sp - in 11..20 -> 14.sp - else -> 12.sp - } + text = "${stringResource(R.string.txt_definition)}:", + style = MaterialTheme.typography.titleSmall.copy( + color = MaterialTheme.colorScheme.onSurface.copy( + alpha = 0.5f + ) ), - modifier = Modifier.padding(8.dp) + modifier = Modifier.padding(8.dp), ) + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxSize() + ) { + if (randomQuestion?.definitionImageUrl?.isNotEmpty() == true) { + AsyncImage( + model = randomQuestion.definitionImageUrl, + contentDescription = stringResource(R.string.txt_definition_image), + contentScale = ContentScale.Crop, + modifier = Modifier + .size(80.dp) + .clickable { + isImageViewerOpen = true + imageUri = + randomQuestion.definitionImageUrl + } + ) + } + Text( + text = randomQuestion?.definition ?: "", + style = MaterialTheme.typography.titleLarge.copy( + fontSize = when (randomQuestion?.term?.length + ?: 0) { + in 0..10 -> 24.sp + in 11..20 -> 20.sp + else -> 16.sp + }, + textAlign = TextAlign.Center + ), + modifier = Modifier.padding(8.dp), + ) + } } } } @@ -388,10 +437,10 @@ fun LearnByTrueFalse( // Image Viewer Dialog if (isImageViewerOpen) { ShowImageDialog( - definitionImageUri = definitionImageUri, + definitionImageUri = imageUri, onDismissRequest = { isImageViewerOpen = false - definitionImageUri = "" + imageUri = "" } ) } diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseUiState.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseUiState.kt index e4b28fa2..ca38a42c 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseUiState.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseUiState.kt @@ -34,6 +34,7 @@ data class LearnByTrueFalseUiState( data class TrueFalseQuestion( val id: String = "", val term: String = "", + val termImageUrl: String = "", val definition: String = "", val definitionImageUrl: String = "", val originalDefinition: String = "", diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseViewModel.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseViewModel.kt index 54bf9a33..3ae20bbc 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseViewModel.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/LearnByTrueFalseViewModel.kt @@ -58,8 +58,8 @@ class LearnByTrueFalseViewModel @Inject constructor( val studySetSubjectId = savedStateHandle.get("studySetSubjectId") ?: 1 val folderId = savedStateHandle.get("folderId") ?: "" val learnFrom = savedStateHandle.get("learnFrom") ?: LearnFrom.STUDY_SET - _uiState.update { - it.copy( + _uiState.update { state -> + state.copy( folderId = folderId, learnFrom = learnFrom, studySetId = studySetId, @@ -338,10 +338,10 @@ class LearnByTrueFalseViewModel @Inject constructor( val filteredFlashCards = flashCards.filter { it.id != currentCard.id } if (filteredFlashCards.isEmpty()) { - // Handle the case where there are no other flashcards to choose from return TrueFalseQuestion( id = currentCard.id, term = currentCard.term, + termImageUrl = currentCard.termImageURL ?: "", definition = currentCard.definition, definitionImageUrl = currentCard.definitionImageURL ?: "", isRandom = false, @@ -351,13 +351,11 @@ class LearnByTrueFalseViewModel @Inject constructor( } val randomFlashCard = filteredFlashCards.random() - Timber.d("Random: $random") - Timber.d("Definition: ${randomFlashCard.definition}") - Timber.d("Definition Image Url: ${randomFlashCard.definitionImageURL}") return TrueFalseQuestion( id = currentCard.id, term = currentCard.term, + termImageUrl = currentCard.termImageURL ?: "", definition = if (random) randomFlashCard.definition else currentCard.definition, definitionImageUrl = if (random) randomFlashCard.definitionImageURL ?: "" else currentCard.definitionImageURL ?: "", diff --git a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/component/TrueFalseButton.kt b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/component/TrueFalseButton.kt index 1dad4c03..0002ff64 100644 --- a/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/component/TrueFalseButton.kt +++ b/app/src/main/java/com/pwhs/quickmem/presentation/app/study_set/studies/true_false/component/TrueFalseButton.kt @@ -49,6 +49,9 @@ fun TrueFalseButton( border = BorderStroke( width = 2.dp, color = if (isTrue) correctColor else incorrectColor + ), + elevation = CardDefaults.cardElevation( + defaultElevation = 3.dp ) ) { Box( @@ -71,6 +74,6 @@ fun TrueFalseButton( @Composable private fun TrueFalseButtonPreview() { QuickMemTheme { - TrueFalseButton(title = "True") + TrueFalseButton(title = "True", isTrue = true) } } \ No newline at end of file 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 00ece8d6..199d3049 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 @@ -26,6 +26,7 @@ import androidx.compose.material.icons.Icons.Default import androidx.compose.material.icons.filled.ArrowCircleUp import androidx.compose.material.icons.filled.Clear import androidx.compose.material.icons.filled.Lightbulb +import androidx.compose.material.icons.filled.RestartAlt import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card @@ -240,6 +241,17 @@ fun LearnByWrite( tint = if (isSwapCard) studySetColor.copy(alpha = 0.5f) else studySetColor, ) } + if (isGetAll) { + IconButton( + onClick = onRestart + ) { + Icon( + imageVector = Default.RestartAlt, + contentDescription = stringResource(R.string.txt_restart), + tint = studySetColor + ) + } + } IconButton( onClick = { showHintBottomSheet.value = true @@ -578,10 +590,12 @@ fun LearnByWrite( } item { - HorizontalDivider( - modifier = Modifier - .fillMaxWidth() - ) + if (!isGenerateHint) { + HorizontalDivider( + modifier = Modifier + .fillMaxWidth() + ) + } if (isGenerateHint) { LinearProgressIndicator( color = studySetColor, @@ -647,7 +661,7 @@ fun LearnByWrite( Spacer(modifier = Modifier.height(16.dp)) Text( - text = stringResource(R.string.txt_random_letter), + text = stringResource(R.string.txt_random_character), style = MaterialTheme.typography.bodyMedium.copy( fontWeight = FontWeight.Bold ), diff --git a/app/src/main/res/drawable/ic_image_error.xml b/app/src/main/res/drawable/ic_image_error.xml new file mode 100644 index 00000000..b4ac9be3 --- /dev/null +++ b/app/src/main/res/drawable/ic_image_error.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 3169f49c..7dbfa1b1 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -282,9 +282,9 @@ Tạo thẻ học của riêng bạn Top 5 môn học có bộ học Luyện tập mỗi ngày để không mất chuỗi! - Thử lại + Thử lại tốt hơn vào lần sau nhé! Biểu tượng thư mục - Chuỗi lửa + Chuỗi học Xem tất cả Không tìm thấy kết quả Người dùng @@ -375,7 +375,7 @@ Bạn đang làm rất tốt! Tiếp tục tập trung vào bộ học của bạn để thành thạo nó! Thẻ - Flashcards đã học + Thẻ đã học Thời gian Thời gian học Tiếp tục ôn lại %1$s thuật ngữ @@ -466,7 +466,7 @@ Câu trả lời có %1$s ký tự Gợi ý: %1$s Hiển thị thêm gợi ý - Random từng chữ: + Random từng ký tự: Gợi ý AI: Nhấn vào biểu tượng để hiển thị gợi ý nếu bạn cảm thấy bí Liên kết Google OAuth @@ -606,4 +606,7 @@ Bạn đã hoàn thành Hình ảnh định nghĩa Đổi vị trí bắt đầu của thẻ + Chọn đáp án đúng: + Giải thích: %1$s + Ảnh thuật ngữ \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3e77c956..82af2a1d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -468,7 +468,7 @@ Answer has %1$s characters Hint: %1$s Show more hint - Random letter: + Random character: AI hint Click the icon to show hint if you feel stuck Google OAuth Callback @@ -609,4 +609,7 @@ You have finished Definition image Swap card + Select an answer: + Explanation: %1$s + Term image \ No newline at end of file