From 936809ddc2ce5abe5e81014eddda0282447caa81 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Sat, 13 Jul 2024 11:32:41 +0530 Subject: [PATCH 01/21] Add collapsible functionality to classroom cards --- .../ClassroomListFragmentPresenter.kt | 11 ++++-- .../classroom/classroomlist/ClassroomList.kt | 34 +++++++++++++------ app/src/main/res/values-land/dimens.xml | 2 -- .../main/res/values-sw600dp-land/dimens.xml | 2 -- .../main/res/values-sw600dp-port/dimens.xml | 2 -- app/src/main/res/values/dimens.xml | 1 + 6 files changed, 33 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt index 7bc81fd5bdf..42e73f64fa7 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt @@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -182,8 +183,11 @@ class ClassroomListFragmentPresenter @Inject constructor( ?.plus(classroomListViewModel.topicList) ?.groupBy { it::class } val topicListSpanCount = integerResource(id = R.integer.home_span_count) + val listState = rememberLazyListState() + LazyColumn( - modifier = Modifier.testTag(CLASSROOM_LIST_SCREEN_TEST_TAG) + modifier = Modifier.testTag(CLASSROOM_LIST_SCREEN_TEST_TAG), + state = listState ) { groupedItems?.forEach { (type, items) -> when (type) { @@ -200,10 +204,11 @@ class ClassroomListFragmentPresenter @Inject constructor( ) } } - ClassroomSummaryViewModel::class -> stickyHeader { + ClassroomSummaryViewModel::class -> stickyHeader(key = "classroom_carousel") { ClassroomList( classroomSummaryList = items.map { it as ClassroomSummaryViewModel }, - classroomListViewModel.selectedClassroomId.get() ?: "" + selectedClassroomId = classroomListViewModel.selectedClassroomId.get() ?: "", + isSticky = listState.firstVisibleItemIndex >= 2 ) } AllTopicsViewModel::class -> items.forEach { _ -> diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index 5c35b3383b1..3c3a7ca0344 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -1,6 +1,9 @@ package org.oppia.android.app.classroom.classroomlist -import android.content.res.Configuration +import androidx.compose.animation.core.MutableTransitionState +import androidx.compose.animation.core.animateDp +import androidx.compose.animation.core.tween +import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -18,9 +21,10 @@ import androidx.compose.foundation.lazy.items import androidx.compose.material.Card import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource @@ -44,7 +48,8 @@ const val CLASSROOM_LIST_TEST_TAG = "TEST_TAG.classroom_list" @Composable fun ClassroomList( classroomSummaryList: List, - selectedClassroomId: String + selectedClassroomId: String, + isSticky: Boolean, ) { Column( modifier = Modifier @@ -76,7 +81,7 @@ fun ClassroomList( ), ) { items(classroomSummaryList) { - ClassroomCard(classroomSummaryViewModel = it, selectedClassroomId) + ClassroomCard(classroomSummaryViewModel = it, selectedClassroomId, isSticky) } } } @@ -86,15 +91,24 @@ fun ClassroomList( @Composable fun ClassroomCard( classroomSummaryViewModel: ClassroomSummaryViewModel, - selectedClassroomId: String + selectedClassroomId: String, + isSticky: Boolean, ) { - val screenWidth = LocalConfiguration.current.screenWidthDp - val isPortrait = LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT - val isTablet = if (isPortrait) screenWidth > 600 else screenWidth > 840 val isCardSelected = classroomSummaryViewModel.classroomSummary.classroomId == selectedClassroomId + val transitionState = remember { MutableTransitionState(isSticky) } + val transition = updateTransition(transitionState, label = "transition") + val cardHeight by transition.animateDp( + { tween(durationMillis = 300) }, + label = "cardHeightTransition" + ) { isSticky -> + if (isSticky) + dimensionResource(id = R.dimen.classrooms_card_collapsed_height) + else + dimensionResource(id = R.dimen.classrooms_card_height) + } Card( modifier = Modifier - .height(dimensionResource(id = R.dimen.classrooms_card_height)) + .height(cardHeight) .width(dimensionResource(id = R.dimen.classrooms_card_width)) .padding( start = dimensionResource(R.dimen.promoted_story_card_layout_margin_start), @@ -116,7 +130,7 @@ fun ClassroomCard( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, ) { - if (isPortrait || isTablet) { // Hides the classroom icon for landscape phone layouts. + if (!isSticky) { Image( painter = painterResource( id = classroomSummaryViewModel diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml index 49afd330bdf..0fce9e8ccc0 100644 --- a/app/src/main/res/values-land/dimens.xml +++ b/app/src/main/res/values-land/dimens.xml @@ -552,6 +552,4 @@ 20dp 72dp 12dp - 150dp - 60dp diff --git a/app/src/main/res/values-sw600dp-land/dimens.xml b/app/src/main/res/values-sw600dp-land/dimens.xml index 47caee25f05..f90b9fb9cfe 100644 --- a/app/src/main/res/values-sw600dp-land/dimens.xml +++ b/app/src/main/res/values-sw600dp-land/dimens.xml @@ -517,6 +517,4 @@ 20dp 72dp 12dp - 150dp - 182dp diff --git a/app/src/main/res/values-sw600dp-port/dimens.xml b/app/src/main/res/values-sw600dp-port/dimens.xml index d2c15feccbc..3a9e6ad20dc 100644 --- a/app/src/main/res/values-sw600dp-port/dimens.xml +++ b/app/src/main/res/values-sw600dp-port/dimens.xml @@ -534,6 +534,4 @@ 20dp 60dp 12dp - 150dp - 182dp diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 0b06f5569ba..77232adb674 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -835,6 +835,7 @@ 18sp 150dp 182dp + 60dp 18sp 20dp 20dp From 1b7ed1ca448d07a684fc9285e0bf7d4d85324f3e Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Sat, 13 Jul 2024 11:55:33 +0530 Subject: [PATCH 02/21] Rename shadowed variable --- .../android/app/classroom/classroomlist/ClassroomList.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index 3c3a7ca0344..f9a057220cf 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -100,8 +100,8 @@ fun ClassroomCard( val cardHeight by transition.animateDp( { tween(durationMillis = 300) }, label = "cardHeightTransition" - ) { isSticky -> - if (isSticky) + ) { isStickyState -> + if (isStickyState) dimensionResource(id = R.dimen.classrooms_card_collapsed_height) else dimensionResource(id = R.dimen.classrooms_card_height) From 7e5b1c2bb79c598d8fb659316b4c0dd32bc0fd52 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Sat, 13 Jul 2024 14:06:34 +0530 Subject: [PATCH 03/21] Refactor card collapse logic --- .../classroom/classroomlist/ClassroomList.kt | 34 ++++++------------- app/src/main/res/values-land/dimens.xml | 2 ++ .../main/res/values-sw600dp-land/dimens.xml | 4 ++- .../main/res/values-sw600dp-port/dimens.xml | 2 ++ app/src/main/res/values/dimens.xml | 8 +++-- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index f9a057220cf..0b4c6724283 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -1,9 +1,6 @@ package org.oppia.android.app.classroom.classroomlist -import androidx.compose.animation.core.MutableTransitionState -import androidx.compose.animation.core.animateDp -import androidx.compose.animation.core.tween -import androidx.compose.animation.core.updateTransition +import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -12,7 +9,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -21,8 +17,6 @@ import androidx.compose.foundation.lazy.items import androidx.compose.material.Card import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag @@ -95,24 +89,12 @@ fun ClassroomCard( isSticky: Boolean, ) { val isCardSelected = classroomSummaryViewModel.classroomSummary.classroomId == selectedClassroomId - val transitionState = remember { MutableTransitionState(isSticky) } - val transition = updateTransition(transitionState, label = "transition") - val cardHeight by transition.animateDp( - { tween(durationMillis = 300) }, - label = "cardHeightTransition" - ) { isStickyState -> - if (isStickyState) - dimensionResource(id = R.dimen.classrooms_card_collapsed_height) - else - dimensionResource(id = R.dimen.classrooms_card_height) - } Card( modifier = Modifier - .height(cardHeight) .width(dimensionResource(id = R.dimen.classrooms_card_width)) .padding( - start = dimensionResource(R.dimen.promoted_story_card_layout_margin_start), - end = dimensionResource(R.dimen.promoted_story_card_layout_margin_end), + start = dimensionResource(R.dimen.classrooms_card_margin_start), + end = dimensionResource(R.dimen.classrooms_card_margin_end), ) .clickable { classroomSummaryViewModel.handleClassroomClick() @@ -126,11 +108,17 @@ fun ClassroomCard( elevation = dimensionResource(id = R.dimen.classrooms_card_elevation), ) { Column( - modifier = Modifier.padding(all = dimensionResource(id = R.dimen.classrooms_card_padding)), + modifier = Modifier.padding( + horizontal = dimensionResource(id = R.dimen.classrooms_card_padding_horizontal), + vertical = if (isSticky) + dimensionResource(id = R.dimen.classrooms_card_collapsed_padding_vertical) + else + dimensionResource(id = R.dimen.classrooms_card_padding_vertical), + ), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, ) { - if (!isSticky) { + AnimatedVisibility(visible = !isSticky) { Image( painter = painterResource( id = classroomSummaryViewModel diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml index 0fce9e8ccc0..103620648e6 100644 --- a/app/src/main/res/values-land/dimens.xml +++ b/app/src/main/res/values-land/dimens.xml @@ -552,4 +552,6 @@ 20dp 72dp 12dp + 8dp + 0dp diff --git a/app/src/main/res/values-sw600dp-land/dimens.xml b/app/src/main/res/values-sw600dp-land/dimens.xml index f90b9fb9cfe..ead0aff960c 100644 --- a/app/src/main/res/values-sw600dp-land/dimens.xml +++ b/app/src/main/res/values-sw600dp-land/dimens.xml @@ -351,7 +351,7 @@ 24dp 48dp - 100dp + 232dp 0dp @@ -517,4 +517,6 @@ 20dp 72dp 12dp + 0dp + 8dp diff --git a/app/src/main/res/values-sw600dp-port/dimens.xml b/app/src/main/res/values-sw600dp-port/dimens.xml index 3a9e6ad20dc..61e62a621c4 100644 --- a/app/src/main/res/values-sw600dp-port/dimens.xml +++ b/app/src/main/res/values-sw600dp-port/dimens.xml @@ -534,4 +534,6 @@ 20dp 60dp 12dp + 8dp + 0dp diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 77232adb674..426542245aa 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -837,8 +837,12 @@ 182dp 60dp 18sp - 20dp + 16dp + 28dp + 20dp 20dp - 80dp + 68dp 4dp + 8dp + 0dp From f011cc89c6509296201978dd22dd348ed08aeb01 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Sat, 13 Jul 2024 20:40:21 +0530 Subject: [PATCH 04/21] Update dark mode colors --- .../app/classroom/classroomlist/ClassroomList.kt | 12 +++++++----- .../app/classroom/promotedlist/PromotedList.kt | 2 +- app/src/main/res/values-night/color_palette.xml | 9 ++++++--- app/src/main/res/values/color_defs.xml | 7 +++++-- app/src/main/res/values/color_palette.xml | 8 +++++--- app/src/main/res/values/component_colors.xml | 2 ++ 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index 0b4c6724283..e92f9521413 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -100,9 +100,9 @@ fun ClassroomCard( classroomSummaryViewModel.handleClassroomClick() }, backgroundColor = if (isCardSelected) { - colorResource(id = R.color.component_color_classroom_card_color) + colorResource(id = R.color.component_color_classroom_card_selected_color) } else { - colorResource(id = R.color.component_color_shared_screen_primary_background_color) + colorResource(id = R.color.component_color_classroom_card_color) }, border = BorderStroke(2.dp, color = colorResource(id = R.color.color_def_oppia_green)), elevation = dimensionResource(id = R.dimen.classrooms_card_elevation), @@ -110,10 +110,12 @@ fun ClassroomCard( Column( modifier = Modifier.padding( horizontal = dimensionResource(id = R.dimen.classrooms_card_padding_horizontal), - vertical = if (isSticky) + vertical = if (isSticky) { dimensionResource(id = R.dimen.classrooms_card_collapsed_padding_vertical) - else - dimensionResource(id = R.dimen.classrooms_card_padding_vertical), + } + else { + dimensionResource(id = R.dimen.classrooms_card_padding_vertical) + }, ), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, diff --git a/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt index 3ac2bdebf1d..446cc63764c 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt @@ -127,7 +127,7 @@ fun PromotedStoryCard( ) .clickable { promotedStoryViewModel.clickOnStoryTile() }, backgroundColor = colorResource( - id = R.color.component_color_shared_screen_primary_background_color + id = R.color.component_color_classroom_promoted_list_card_background_color ), elevation = dimensionResource(id = R.dimen.promoted_story_card_elevation), ) { diff --git a/app/src/main/res/values-night/color_palette.xml b/app/src/main/res/values-night/color_palette.xml index bed7ab257be..f4cdb8dc831 100644 --- a/app/src/main/res/values-night/color_palette.xml +++ b/app/src/main/res/values-night/color_palette.xml @@ -132,7 +132,7 @@ @color/color_def_forest_green @color/color_def_oppia_dark_blue @color/color_def_oppia_turquoise - @color/color_def_persian_blue + @color/color_def_persian_blue_1 @color/color_def_bright_green @color/color_def_white @color/color_def_oppia_metallic_blue @@ -242,7 +242,10 @@ @color/color_def_oppia_reddish_brown @color/color_def_accessible_light_grey_2 - @color/color_def_greenish_black + @color/color_def_greenish_black_2 + @color/color_def_greenish_black_1 @color/color_def_white - @color/color_def_greenish_black + @color/color_def_greenish_black_3 + @color/color_def_persian_blue_2 + @color/color_def_greenish_black_2 diff --git a/app/src/main/res/values/color_defs.xml b/app/src/main/res/values/color_defs.xml index 4eb98853686..94e0fe5c8a9 100644 --- a/app/src/main/res/values/color_defs.xml +++ b/app/src/main/res/values/color_defs.xml @@ -95,7 +95,8 @@ #00FFFFFF #0e162f #081661 - #00609C + #00609C + #0097F5 #009C8A #674172 #7659B6 @@ -145,7 +146,9 @@ #E2F5F4 #25000000 #EDF6F5 - #172B28 + #325D57 + #1C3531 + #1D3532 #8EBBB6 #64817E #F8BF74 diff --git a/app/src/main/res/values/color_palette.xml b/app/src/main/res/values/color_palette.xml index cb6a86c2ff9..419de34b3bf 100644 --- a/app/src/main/res/values/color_palette.xml +++ b/app/src/main/res/values/color_palette.xml @@ -136,7 +136,7 @@ @color/color_def_oppia_brown_dark @color/color_def_oppia_dark_blue @color/color_def_oppia_brown_dark - @color/color_def_persian_blue + @color/color_def_persian_blue_1 @color/color_def_oppia_light_brown @color/color_def_black @color/color_def_teal_blue @@ -285,8 +285,10 @@ @color/color_def_accessible_light_grey_2 @color/color_def_error_text - @color/color_def_greenish_white + @color/color_def_white + @color/color_def_greenish_white @color/color_def_green @color/color_def_greenish_white - @color/color_def_persian_blue + @color/color_def_persian_blue_1 + @color/color_def_white diff --git a/app/src/main/res/values/component_colors.xml b/app/src/main/res/values/component_colors.xml index 6ed6c6a5df8..a0bab6bf31d 100644 --- a/app/src/main/res/values/component_colors.xml +++ b/app/src/main/res/values/component_colors.xml @@ -322,9 +322,11 @@ @color/color_palette_text_error_color @color/color_palette_classroom_card_color + @color/color_palette_classroom_card_selected_color @color/color_palette_classroom_shared_text_color @color/color_palette_classroom_shared_text_color @color/color_palette_classroom_shared_text_color @color/color_palette_classroom_topic_list_background_color @color/color_palette_classroom_promoted_list_classroom_label_color + @color/color_palette_classroom_promoted_list_card_background_color From 235c551056c76ff93b288fcdff99ea4f2b73e07d Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Sat, 13 Jul 2024 20:42:01 +0530 Subject: [PATCH 05/21] Fix ktlint check --- .../oppia/android/app/classroom/classroomlist/ClassroomList.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index e92f9521413..3254e6a5472 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -112,8 +112,7 @@ fun ClassroomCard( horizontal = dimensionResource(id = R.dimen.classrooms_card_padding_horizontal), vertical = if (isSticky) { dimensionResource(id = R.dimen.classrooms_card_collapsed_padding_vertical) - } - else { + } else { dimensionResource(id = R.dimen.classrooms_card_padding_vertical) }, ), From 8169c13d3c555c9b4b28ee54b9b5b690e58d40b9 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Sun, 14 Jul 2024 15:42:29 +0530 Subject: [PATCH 06/21] Separate classroom header from ClassroomList --- .../ClassroomListFragmentPresenter.kt | 9 ++++- .../app/classroom/ClassroomListViewModel.kt | 16 ++++---- .../classroomlist/AllClassroomsHeaderText.kt | 36 ++++++++++++++++++ .../classroom/classroomlist/ClassroomList.kt | 38 +++++-------------- .../classroomlist/AllClassroomsViewModel.kt | 8 ++++ .../classroom/ClassroomListFragmentTest.kt | 6 +-- 6 files changed, 73 insertions(+), 40 deletions(-) create mode 100644 app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt create mode 100644 app/src/main/java/org/oppia/android/app/home/classroomlist/AllClassroomsViewModel.kt diff --git a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt index 42e73f64fa7..d92830046e5 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.unit.dp import androidx.databinding.ObservableList import androidx.fragment.app.Fragment import org.oppia.android.R +import org.oppia.android.app.classroom.classroomlist.AllClassroomsHeaderText import org.oppia.android.app.classroom.classroomlist.ClassroomList import org.oppia.android.app.classroom.promotedlist.PromotedStoryList import org.oppia.android.app.classroom.topiclist.AllTopicsHeaderText @@ -37,6 +38,7 @@ import org.oppia.android.app.classroom.welcome.WelcomeText import org.oppia.android.app.home.HomeItemViewModel import org.oppia.android.app.home.RouteToTopicPlayStoryListener import org.oppia.android.app.home.WelcomeViewModel +import org.oppia.android.app.home.classroomlist.AllClassroomsViewModel import org.oppia.android.app.home.classroomlist.ClassroomSummaryViewModel import org.oppia.android.app.home.promotedlist.PromotedStoryListViewModel import org.oppia.android.app.home.topiclist.AllTopicsViewModel @@ -204,7 +206,12 @@ class ClassroomListFragmentPresenter @Inject constructor( ) } } - ClassroomSummaryViewModel::class -> stickyHeader(key = "classroom_carousel") { + AllClassroomsViewModel::class -> items.forEach { _ -> + item { + AllClassroomsHeaderText() + } + } + ClassroomSummaryViewModel::class -> stickyHeader() { ClassroomList( classroomSummaryList = items.map { it as ClassroomSummaryViewModel }, selectedClassroomId = classroomListViewModel.selectedClassroomId.get() ?: "", diff --git a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListViewModel.kt b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListViewModel.kt index df1b5cd8f13..8211e52529b 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListViewModel.kt @@ -10,6 +10,7 @@ import androidx.lifecycle.Transformations import org.oppia.android.R import org.oppia.android.app.home.HomeItemViewModel import org.oppia.android.app.home.WelcomeViewModel +import org.oppia.android.app.home.classroomlist.AllClassroomsViewModel import org.oppia.android.app.home.classroomlist.ClassroomSummaryClickListener import org.oppia.android.app.home.classroomlist.ClassroomSummaryViewModel import org.oppia.android.app.home.promotedlist.ComingSoonTopicListViewModel @@ -264,13 +265,14 @@ class ClassroomListViewModel( private fun computeClassroomItemViewModelList( classroomList: ClassroomList ): List { - return classroomList.classroomSummaryList.map { ephemeralClassroomSummary -> - ClassroomSummaryViewModel( - fragment as ClassroomSummaryClickListener, - ephemeralClassroomSummary, - translationController - ) - } + return listOf(AllClassroomsViewModel) + + classroomList.classroomSummaryList.map { ephemeralClassroomSummary -> + ClassroomSummaryViewModel( + fragment as ClassroomSummaryClickListener, + ephemeralClassroomSummary, + translationController + ) + } } /** diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt new file mode 100644 index 00000000000..809f1d29454 --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt @@ -0,0 +1,36 @@ +package org.oppia.android.app.classroom.classroomlist + +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp +import org.oppia.android.R + +/** Test tag for the all topics section header. */ +const val ALL_CLASSROOMS_HEADER_TEST_TAG = "TEST_TAG.all_classrooms_header" + +/** Displays the header text for the topic list section. */ +@Composable +fun AllClassroomsHeaderText() { + Text( + text = stringResource(id = R.string.classrooms_list_activity_section_header), + color = colorResource(id = R.color.component_color_shared_primary_text_color), + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Medium, + fontSize = dimensionResource(id = R.dimen.classrooms_list_header_text_size).value.sp, + modifier = Modifier + .testTag(ALL_CLASSROOMS_HEADER_TEST_TAG) + .padding( + start = dimensionResource(id = R.dimen.classrooms_text_margin_start), + top = dimensionResource(id = R.dimen.classrooms_text_margin_top), + end = dimensionResource(id = R.dimen.classrooms_text_margin_end), + ), + ) +} diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index 3254e6a5472..893dafaa032 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -32,9 +32,6 @@ import org.oppia.android.R import org.oppia.android.app.classroom.getDrawableResource import org.oppia.android.app.home.classroomlist.ClassroomSummaryViewModel -/** Test tag for the header of the classroom section. */ -const val CLASSROOM_HEADER_TEST_TAG = "TEST_TAG.classroom_header" - /** Test tag for the classroom list. */ const val CLASSROOM_LIST_TEST_TAG = "TEST_TAG.classroom_list" @@ -45,38 +42,21 @@ fun ClassroomList( selectedClassroomId: String, isSticky: Boolean, ) { - Column( + LazyRow( modifier = Modifier + .testTag(CLASSROOM_LIST_TEST_TAG) .background( color = colorResource(id = R.color.component_color_shared_screen_primary_background_color) ) .fillMaxWidth(), + contentPadding = PaddingValues( + start = dimensionResource(id = R.dimen.classrooms_text_margin_start), + top = dimensionResource(id = R.dimen.classrooms_text_margin_bottom), + end = dimensionResource(id = R.dimen.classrooms_text_margin_end), + ), ) { - Text( - text = stringResource(id = R.string.classrooms_list_activity_section_header), - color = colorResource(id = R.color.component_color_shared_primary_text_color), - fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.Medium, - fontSize = dimensionResource(id = R.dimen.classrooms_list_header_text_size).value.sp, - modifier = Modifier - .testTag(CLASSROOM_HEADER_TEST_TAG) - .padding( - start = dimensionResource(id = R.dimen.classrooms_text_margin_start), - top = dimensionResource(id = R.dimen.classrooms_text_margin_top), - end = dimensionResource(id = R.dimen.classrooms_text_margin_end), - bottom = dimensionResource(id = R.dimen.classrooms_text_margin_bottom), - ), - ) - LazyRow( - modifier = Modifier.testTag(CLASSROOM_LIST_TEST_TAG), - contentPadding = PaddingValues( - start = dimensionResource(id = R.dimen.classrooms_text_margin_start), - end = dimensionResource(id = R.dimen.classrooms_text_margin_end), - ), - ) { - items(classroomSummaryList) { - ClassroomCard(classroomSummaryViewModel = it, selectedClassroomId, isSticky) - } + items(classroomSummaryList) { + ClassroomCard(classroomSummaryViewModel = it, selectedClassroomId, isSticky) } } } diff --git a/app/src/main/java/org/oppia/android/app/home/classroomlist/AllClassroomsViewModel.kt b/app/src/main/java/org/oppia/android/app/home/classroomlist/AllClassroomsViewModel.kt new file mode 100644 index 00000000000..f3fc8d1557b --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/home/classroomlist/AllClassroomsViewModel.kt @@ -0,0 +1,8 @@ +package org.oppia.android.app.home.classroomlist + +import androidx.lifecycle.ViewModel +import org.oppia.android.app.classroom.ClassroomListFragment +import org.oppia.android.app.home.HomeItemViewModel + +/** [ViewModel] all classrooms text in [ClassroomListFragment]. */ +object AllClassroomsViewModel : HomeItemViewModel() diff --git a/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt index 87a5c58fd0a..3349268cbf4 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt @@ -42,7 +42,7 @@ import org.oppia.android.app.application.ApplicationInjectorProvider import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule -import org.oppia.android.app.classroom.classroomlist.CLASSROOM_HEADER_TEST_TAG +import org.oppia.android.app.classroom.classroomlist.ALL_CLASSROOMS_HEADER_TEST_TAG import org.oppia.android.app.classroom.classroomlist.CLASSROOM_LIST_TEST_TAG import org.oppia.android.app.classroom.promotedlist.PROMOTED_STORY_LIST_HEADER_TEST_TAG import org.oppia.android.app.classroom.promotedlist.PROMOTED_STORY_LIST_TEST_TAG @@ -196,7 +196,7 @@ class ClassroomListFragmentTest { @Test fun testFragment_allComponentsAreDisplayed() { composeRule.onNodeWithTag(WELCOME_TEST_TAG).assertIsDisplayed() - composeRule.onNodeWithTag(CLASSROOM_HEADER_TEST_TAG).assertIsDisplayed() + composeRule.onNodeWithTag(ALL_CLASSROOMS_HEADER_TEST_TAG).assertIsDisplayed() composeRule.onNodeWithTag(CLASSROOM_LIST_TEST_TAG).assertIsDisplayed() composeRule.onNodeWithTag(ALL_TOPICS_HEADER_TEST_TAG).assertIsDisplayed() } @@ -207,7 +207,7 @@ class ClassroomListFragmentTest { composeRule.onNodeWithTag(WELCOME_TEST_TAG).assertIsDisplayed() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG).assertIsDisplayed() composeRule.onNodeWithTag(PROMOTED_STORY_LIST_TEST_TAG).assertIsDisplayed() - composeRule.onNodeWithTag(CLASSROOM_HEADER_TEST_TAG).assertIsDisplayed() + composeRule.onNodeWithTag(ALL_CLASSROOMS_HEADER_TEST_TAG).assertIsDisplayed() composeRule.onNodeWithTag(CLASSROOM_LIST_TEST_TAG).assertIsDisplayed() composeRule.onNodeWithTag(CLASSROOM_LIST_SCREEN_TEST_TAG).performScrollToNode( From 72256a32ad62dc0506fdd6f456f7fb3bc4c62105 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Sun, 14 Jul 2024 15:45:41 +0530 Subject: [PATCH 07/21] Fix static checks --- .../android/app/classroom/classroomlist/ClassroomList.kt | 1 - scripts/assets/test_file_exemptions.textproto | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index 893dafaa032..d5171c595f4 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -23,7 +23,6 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp diff --git a/scripts/assets/test_file_exemptions.textproto b/scripts/assets/test_file_exemptions.textproto index d1ff255fc64..90bbe09c182 100644 --- a/scripts/assets/test_file_exemptions.textproto +++ b/scripts/assets/test_file_exemptions.textproto @@ -270,6 +270,10 @@ test_file_exemption { exempted_file_path: "app/src/main/java/org/oppia/android/app/classroom/ClassroomListViewModel.kt" test_file_not_required: true } +test_file_exemption { + exempted_file_path: "app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt" + test_file_not_required: true +} test_file_exemption { exempted_file_path: "app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt" test_file_not_required: true @@ -898,6 +902,10 @@ test_file_exemption { exempted_file_path: "app/src/main/java/org/oppia/android/app/home/classroomlist/ClassroomSummaryClickListener.kt" test_file_not_required: true } +test_file_exemption { + exempted_file_path: "app/src/main/java/org/oppia/android/app/home/classroomlist/AllClassroomsViewModel.kt" + test_file_not_required: true +} test_file_exemption { exempted_file_path: "app/src/main/java/org/oppia/android/app/home/classroomlist/ClassroomSummaryViewModel.kt" test_file_not_required: true From 871ff725ab2d794d071b4769b48aa72e508f031e Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Sun, 14 Jul 2024 16:40:14 +0530 Subject: [PATCH 08/21] Add test to verify the card collapse behavior --- .../classroom/classroomlist/ClassroomList.kt | 4 ++ .../classroom/ClassroomListFragmentTest.kt | 37 +++++++++---------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index d5171c595f4..937820edf43 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -34,6 +34,9 @@ import org.oppia.android.app.home.classroomlist.ClassroomSummaryViewModel /** Test tag for the classroom list. */ const val CLASSROOM_LIST_TEST_TAG = "TEST_TAG.classroom_list" +/** Test tag for the classroom card icon. */ +const val CLASSROOM_CARD_ICON_TEST_TAG = "TEST_TAG.classroom_card_icon" + /** Displays a list of classroom summaries with a header. */ @Composable fun ClassroomList( @@ -108,6 +111,7 @@ fun ClassroomCard( ), contentDescription = classroomSummaryViewModel.title, modifier = Modifier + .testTag("${CLASSROOM_CARD_ICON_TEST_TAG}_${classroomSummaryViewModel.title}") .padding(bottom = dimensionResource(id = R.dimen.classrooms_card_icon_padding_bottom)) .size(size = dimensionResource(id = R.dimen.classrooms_card_icon_size)), ) diff --git a/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt index 3349268cbf4..1ab63f9fe59 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/classroom/ClassroomListFragmentTest.kt @@ -2,7 +2,6 @@ package org.oppia.android.app.classroom import android.app.Application import android.content.Context -import android.content.Intent import androidx.appcompat.app.AppCompatActivity import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.assertTextContains @@ -21,11 +20,7 @@ import androidx.test.espresso.intent.Intents.intended import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.google.protobuf.MessageLite import dagger.Component -import org.hamcrest.Description -import org.hamcrest.Matcher -import org.hamcrest.TypeSafeMatcher import org.junit.After import org.junit.Before import org.junit.Ignore @@ -43,6 +38,7 @@ import org.oppia.android.app.application.ApplicationModule import org.oppia.android.app.application.ApplicationStartupListenerModule import org.oppia.android.app.application.testing.TestingBuildFlavorModule import org.oppia.android.app.classroom.classroomlist.ALL_CLASSROOMS_HEADER_TEST_TAG +import org.oppia.android.app.classroom.classroomlist.CLASSROOM_CARD_ICON_TEST_TAG import org.oppia.android.app.classroom.classroomlist.CLASSROOM_LIST_TEST_TAG import org.oppia.android.app.classroom.promotedlist.PROMOTED_STORY_LIST_HEADER_TEST_TAG import org.oppia.android.app.classroom.promotedlist.PROMOTED_STORY_LIST_TEST_TAG @@ -57,6 +53,7 @@ import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionMo import org.oppia.android.app.shim.ViewBindingShimModule import org.oppia.android.app.topic.TopicActivity import org.oppia.android.app.translation.testing.ActivityRecreatorTestModule +import org.oppia.android.app.utility.EspressoTestsMatchers.hasProtoExtra import org.oppia.android.app.utility.OrientationChangeAction.Companion.orientationLandscape import org.oppia.android.data.backends.gae.NetworkConfigProdModule import org.oppia.android.data.backends.gae.NetworkModule @@ -109,7 +106,6 @@ import org.oppia.android.testing.time.FakeOppiaClockModule import org.oppia.android.util.accessibility.AccessibilityTestModule import org.oppia.android.util.caching.AssetModule import org.oppia.android.util.caching.testing.CachingTestModule -import org.oppia.android.util.extensions.getProtoExtra import org.oppia.android.util.gcsresource.GcsResourceModule import org.oppia.android.util.locale.LocaleProdModule import org.oppia.android.util.locale.OppiaLocale @@ -664,6 +660,21 @@ class ClassroomListFragmentTest { composeRule.onNodeWithTag(CLASSROOM_LIST_TEST_TAG).assertIsDisplayed() } + @Test + fun testFragment_scrollToBottom_classroomListCollapsesAndSticks_classroomListIsVisible() { + composeRule.onNodeWithTag( + CLASSROOM_CARD_ICON_TEST_TAG + "_Science", + useUnmergedTree = true + ).assertIsDisplayed() + + composeRule.onNodeWithTag(CLASSROOM_LIST_SCREEN_TEST_TAG).performScrollToIndex(3) + + composeRule.onNodeWithTag( + CLASSROOM_CARD_ICON_TEST_TAG + "_Science", + useUnmergedTree = true + ).assertDoesNotExist() + } + @Test fun testFragment_switchClassroom_topicListUpdatesCorrectly() { // Click on Science classroom card. @@ -775,20 +786,6 @@ class ClassroomListFragmentTest { ApplicationProvider.getApplicationContext().inject(this) } - private fun hasProtoExtra(keyName: String, expectedProto: T): Matcher { - val defaultProto = expectedProto.newBuilderForType().build() - return object : TypeSafeMatcher() { - override fun describeTo(description: Description) { - description.appendText("Intent with extra: $keyName and proto value: $expectedProto") - } - - override fun matchesSafely(intent: Intent): Boolean { - return intent.hasExtra(keyName) && - intent.getProtoExtra(keyName, defaultProto) == expectedProto - } - } - } - // TODO(#59): Figure out a way to reuse modules instead of needing to re-declare them. @Singleton @Component( From df600aa384f31be5ca5341aa273b78e9defc5e6e Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Wed, 17 Jul 2024 17:59:12 +0530 Subject: [PATCH 09/21] Calculate ClassroomList index dynamically --- .../android/app/classroom/ClassroomListFragmentPresenter.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt index 0ce155bb93a..5ab630cc09f 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt @@ -199,6 +199,7 @@ class ClassroomListFragmentPresenter @Inject constructor( ?.groupBy { it::class } val topicListSpanCount = integerResource(id = R.integer.home_span_count) val listState = rememberLazyListState() + var classroomListIndex = 0 LazyColumn( modifier = Modifier.testTag(CLASSROOM_LIST_SCREEN_TEST_TAG), @@ -210,6 +211,7 @@ class ClassroomListFragmentPresenter @Inject constructor( item { WelcomeText(welcomeViewModel = item as WelcomeViewModel) } + classroomListIndex++ } PromotedStoryListViewModel::class -> items.forEach { item -> item { @@ -218,6 +220,7 @@ class ClassroomListFragmentPresenter @Inject constructor( machineLocale = machineLocale ) } + classroomListIndex++ } AllClassroomsViewModel::class -> items.forEach { _ -> item { @@ -228,7 +231,7 @@ class ClassroomListFragmentPresenter @Inject constructor( ClassroomList( classroomSummaryList = items.map { it as ClassroomSummaryViewModel }, selectedClassroomId = classroomListViewModel.selectedClassroomId.get() ?: "", - isSticky = listState.firstVisibleItemIndex >= 2 + isSticky = listState.firstVisibleItemIndex >= classroomListIndex ) } AllTopicsViewModel::class -> items.forEach { _ -> From 1ccadd3882ec34036dcd5f3c0023f6a01cc6a3de Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Sun, 21 Jul 2024 11:32:56 +0530 Subject: [PATCH 10/21] Align all topics heading vertically --- app/src/main/res/values-sw600dp-port/dimens.xml | 2 +- app/src/main/res/values/dimens.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-sw600dp-port/dimens.xml b/app/src/main/res/values-sw600dp-port/dimens.xml index 61e62a621c4..bc02e6fcdc8 100644 --- a/app/src/main/res/values-sw600dp-port/dimens.xml +++ b/app/src/main/res/values-sw600dp-port/dimens.xml @@ -282,7 +282,7 @@ 60dp - 52dp + 40dp 76dp 16dp diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 426542245aa..8aa72bdb1e9 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -452,7 +452,7 @@ 28dp - 56dp + 28dp 32dp 12dp 18dp From a168b5732dffd9e0f56c6f1b67207c836dbd3e0a Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Wed, 24 Jul 2024 20:08:13 +0530 Subject: [PATCH 11/21] Dynamically compute classroom card width --- .../classroom/classroomlist/ClassroomList.kt | 19 ++++++++++++++++++- app/src/main/res/values-land/dimens.xml | 3 +++ .../main/res/values-sw600dp-land/dimens.xml | 8 ++++++-- .../main/res/values-sw600dp-port/dimens.xml | 7 +++++-- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index 937820edf43..a6bed980585 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -19,12 +19,15 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.integerResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import org.oppia.android.R @@ -73,7 +76,7 @@ fun ClassroomCard( val isCardSelected = classroomSummaryViewModel.classroomSummary.classroomId == selectedClassroomId Card( modifier = Modifier - .width(dimensionResource(id = R.dimen.classrooms_card_width)) + .width(getClassroomCardWidth()) .padding( start = dimensionResource(R.dimen.classrooms_card_margin_start), end = dimensionResource(R.dimen.classrooms_card_margin_end), @@ -126,3 +129,17 @@ fun ClassroomCard( } } } + +@Composable +fun getClassroomCardWidth(): Dp { + val configuration = LocalConfiguration.current + val screenWidth = configuration.screenWidthDp.dp + val horizontalPadding = dimensionResource(id = R.dimen.classrooms_text_margin_start) + val topicCardHorizontalMargin = 8.dp + val topicListSpanCount = integerResource(id = R.integer.home_span_count) + + val totalTopicCardWidth = screenWidth - + (horizontalPadding.times(2) + (topicCardHorizontalMargin * (topicListSpanCount - 1) * 2)) + + return totalTopicCardWidth.div(topicListSpanCount) +} diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml index 103620648e6..3ac014dc596 100644 --- a/app/src/main/res/values-land/dimens.xml +++ b/app/src/main/res/values-land/dimens.xml @@ -552,6 +552,9 @@ 20dp 72dp 12dp + 36dp + 28dp + 80dp 8dp 0dp diff --git a/app/src/main/res/values-sw600dp-land/dimens.xml b/app/src/main/res/values-sw600dp-land/dimens.xml index ead0aff960c..60b86540e90 100644 --- a/app/src/main/res/values-sw600dp-land/dimens.xml +++ b/app/src/main/res/values-sw600dp-land/dimens.xml @@ -277,7 +277,7 @@ 72dp - 68dp + 48dp 76dp 24dp @@ -517,6 +517,10 @@ 20dp 72dp 12dp + 28dp + 52dp + 32dp + 100dp 0dp - 8dp + 16dp diff --git a/app/src/main/res/values-sw600dp-port/dimens.xml b/app/src/main/res/values-sw600dp-port/dimens.xml index bc02e6fcdc8..08eb35e162b 100644 --- a/app/src/main/res/values-sw600dp-port/dimens.xml +++ b/app/src/main/res/values-sw600dp-port/dimens.xml @@ -282,7 +282,7 @@ 60dp - 40dp + 32dp 76dp 16dp @@ -534,6 +534,9 @@ 20dp 60dp 12dp + 40dp + 28dp + 100dp 8dp - 0dp + 8dp From 083ec70d08dc5d5b45a6df3187be0efd34260dd0 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Wed, 24 Jul 2024 20:16:11 +0530 Subject: [PATCH 12/21] Fix script checks --- .../oppia/android/app/classroom/classroomlist/ClassroomList.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index a6bed980585..23554bad74d 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -131,7 +131,7 @@ fun ClassroomCard( } @Composable -fun getClassroomCardWidth(): Dp { +private fun getClassroomCardWidth(): Dp { val configuration = LocalConfiguration.current val screenWidth = configuration.screenWidthDp.dp val horizontalPadding = dimensionResource(id = R.dimen.classrooms_text_margin_start) From 33f61a492de3024ffe357e8c80eb4a2d85f4478e Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Wed, 24 Jul 2024 21:38:54 +0530 Subject: [PATCH 13/21] Update header font style --- .../app/classroom/classroomlist/AllClassroomsHeaderText.kt | 4 ++-- .../oppia/android/app/classroom/promotedlist/PromotedList.kt | 4 ++-- app/src/main/res/values-night/color_palette.xml | 1 + app/src/main/res/values/color_defs.xml | 1 + app/src/main/res/values/color_palette.xml | 1 + app/src/main/res/values/component_colors.xml | 1 + 6 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt index 809f1d29454..0fe0b840455 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt @@ -21,9 +21,9 @@ const val ALL_CLASSROOMS_HEADER_TEST_TAG = "TEST_TAG.all_classrooms_header" fun AllClassroomsHeaderText() { Text( text = stringResource(id = R.string.classrooms_list_activity_section_header), - color = colorResource(id = R.color.component_color_shared_primary_text_color), + color = colorResource(id = R.color.component_color_classroom_shared_header_text_color), fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.Medium, + fontWeight = FontWeight.Normal, fontSize = dimensionResource(id = R.dimen.classrooms_list_header_text_size).value.sp, modifier = Modifier .testTag(ALL_CLASSROOMS_HEADER_TEST_TAG) diff --git a/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt index 446cc63764c..55e59672d18 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedList.kt @@ -66,9 +66,9 @@ fun PromotedStoryList( ) { Text( text = promotedStoryListViewModel.getHeader(), - color = colorResource(id = R.color.component_color_shared_primary_text_color), + color = colorResource(id = R.color.component_color_classroom_shared_header_text_color), fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.Medium, + fontWeight = FontWeight.Normal, fontSize = dimensionResource(id = R.dimen.promoted_story_list_header_text_size).value.sp, modifier = Modifier .weight(weight = 1f, fill = false), diff --git a/app/src/main/res/values-night/color_palette.xml b/app/src/main/res/values-night/color_palette.xml index f4cdb8dc831..f5836dec321 100644 --- a/app/src/main/res/values-night/color_palette.xml +++ b/app/src/main/res/values-night/color_palette.xml @@ -242,6 +242,7 @@ @color/color_def_oppia_reddish_brown @color/color_def_accessible_light_grey_2 + @color/color_def_white_1 @color/color_def_greenish_black_2 @color/color_def_greenish_black_1 @color/color_def_white diff --git a/app/src/main/res/values/color_defs.xml b/app/src/main/res/values/color_defs.xml index 94e0fe5c8a9..f6d141cfafa 100644 --- a/app/src/main/res/values/color_defs.xml +++ b/app/src/main/res/values/color_defs.xml @@ -153,4 +153,5 @@ #64817E #F8BF74 #B3D8F1 + #B8FFFFFF diff --git a/app/src/main/res/values/color_palette.xml b/app/src/main/res/values/color_palette.xml index 419de34b3bf..159b0b36920 100644 --- a/app/src/main/res/values/color_palette.xml +++ b/app/src/main/res/values/color_palette.xml @@ -285,6 +285,7 @@ @color/color_def_accessible_light_grey_2 @color/color_def_error_text + @color/color_def_black @color/color_def_white @color/color_def_greenish_white @color/color_def_green diff --git a/app/src/main/res/values/component_colors.xml b/app/src/main/res/values/component_colors.xml index a0bab6bf31d..0bb548ae9f3 100644 --- a/app/src/main/res/values/component_colors.xml +++ b/app/src/main/res/values/component_colors.xml @@ -321,6 +321,7 @@ @color/color_palette_edittext_stroke_color @color/color_palette_text_error_color + @color/color_palette_classroom_shared_header_text_color @color/color_palette_classroom_card_color @color/color_palette_classroom_card_selected_color @color/color_palette_classroom_shared_text_color From 066dfe54d3694e24b23a0e3ba0c30e2db0c714b6 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Fri, 26 Jul 2024 07:43:32 +0530 Subject: [PATCH 14/21] Update kdoc --- .../android/app/home/classroomlist/AllClassroomsViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/oppia/android/app/home/classroomlist/AllClassroomsViewModel.kt b/app/src/main/java/org/oppia/android/app/home/classroomlist/AllClassroomsViewModel.kt index f3fc8d1557b..b0a1b366aa8 100644 --- a/app/src/main/java/org/oppia/android/app/home/classroomlist/AllClassroomsViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/home/classroomlist/AllClassroomsViewModel.kt @@ -4,5 +4,5 @@ import androidx.lifecycle.ViewModel import org.oppia.android.app.classroom.ClassroomListFragment import org.oppia.android.app.home.HomeItemViewModel -/** [ViewModel] all classrooms text in [ClassroomListFragment]. */ +/** [ViewModel] for displaying the classroom header in [ClassroomListFragment]. */ object AllClassroomsViewModel : HomeItemViewModel() From 043628ba8884d93b6ae394939f354d978f6c6d4d Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Fri, 26 Jul 2024 07:58:41 +0530 Subject: [PATCH 15/21] Update classroomListIndex for coming soon topics carousel --- .../android/app/classroom/ClassroomListFragmentPresenter.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt index d1c734e784d..c1a94848622 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt @@ -231,6 +231,7 @@ class ClassroomListFragmentPresenter @Inject constructor( machineLocale = machineLocale, ) } + classroomListIndex++ } AllClassroomsViewModel::class -> items.forEach { _ -> item { From f333672a001d24ba6f7848463098894498e1c1a9 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Wed, 31 Jul 2024 08:30:23 +0530 Subject: [PATCH 16/21] Calculate the classroomListIndex dynamically --- .../app/classroom/ClassroomListFragmentPresenter.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt index c1a94848622..19da63a9d68 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt @@ -201,7 +201,10 @@ class ClassroomListFragmentPresenter @Inject constructor( ?.groupBy { it::class } val topicListSpanCount = integerResource(id = R.integer.home_span_count) val listState = rememberLazyListState() - var classroomListIndex = 0 + val classroomListIndex = groupedItems + ?.flatMap { (type, items) -> items.map { type to it } } + ?.indexOfFirst { it.first == AllClassroomsViewModel::class } + ?: -1 LazyColumn( modifier = Modifier.testTag(CLASSROOM_LIST_SCREEN_TEST_TAG), @@ -213,7 +216,6 @@ class ClassroomListFragmentPresenter @Inject constructor( item { WelcomeText(welcomeViewModel = item as WelcomeViewModel) } - classroomListIndex++ } PromotedStoryListViewModel::class -> items.forEach { item -> item { @@ -222,7 +224,6 @@ class ClassroomListFragmentPresenter @Inject constructor( machineLocale = machineLocale ) } - classroomListIndex++ } ComingSoonTopicListViewModel::class -> items.forEach { item -> item { @@ -231,7 +232,6 @@ class ClassroomListFragmentPresenter @Inject constructor( machineLocale = machineLocale, ) } - classroomListIndex++ } AllClassroomsViewModel::class -> items.forEach { _ -> item { From f4edd4766d6cf3d8d21b99eb2e40cb8fa1472c3f Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Wed, 31 Jul 2024 08:32:45 +0530 Subject: [PATCH 17/21] Fix kdoc --- .../app/classroom/classroomlist/AllClassroomsHeaderText.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt index 0fe0b840455..2e611b069d2 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/AllClassroomsHeaderText.kt @@ -13,10 +13,10 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp import org.oppia.android.R -/** Test tag for the all topics section header. */ +/** Test tag for the all classrooms section header. */ const val ALL_CLASSROOMS_HEADER_TEST_TAG = "TEST_TAG.all_classrooms_header" -/** Displays the header text for the topic list section. */ +/** Displays the header text for the classroom list section. */ @Composable fun AllClassroomsHeaderText() { Text( From 3aaecc103bee9c678bf319a1d001ec7800be48d1 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Fri, 2 Aug 2024 17:55:55 +0530 Subject: [PATCH 18/21] Update dark mode classroom card colours --- app/src/main/res/values-night/color_palette.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-night/color_palette.xml b/app/src/main/res/values-night/color_palette.xml index f5836dec321..5bf5862b35a 100644 --- a/app/src/main/res/values-night/color_palette.xml +++ b/app/src/main/res/values-night/color_palette.xml @@ -243,8 +243,8 @@ @color/color_def_accessible_light_grey_2 @color/color_def_white_1 - @color/color_def_greenish_black_2 - @color/color_def_greenish_black_1 + @color/color_def_greenish_black_1 + @color/color_def_greenish_black_2 @color/color_def_white @color/color_def_greenish_black_3 @color/color_def_persian_blue_2 From 041b5e28bba4205b1f1f6e7cc15855b3c0b1cdc8 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Wed, 7 Aug 2024 18:26:25 +0530 Subject: [PATCH 19/21] Fix classroom list direction in RTL --- .../oppia/android/app/classroom/classroomlist/ClassroomList.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index 23554bad74d..fd0e931f703 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -52,8 +52,7 @@ fun ClassroomList( .testTag(CLASSROOM_LIST_TEST_TAG) .background( color = colorResource(id = R.color.component_color_shared_screen_primary_background_color) - ) - .fillMaxWidth(), + ), contentPadding = PaddingValues( start = dimensionResource(id = R.dimen.classrooms_text_margin_start), top = dimensionResource(id = R.dimen.classrooms_text_margin_bottom), From e6ec7650c227fca5fd34c009075625e9b5b915c2 Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Wed, 7 Aug 2024 18:27:46 +0530 Subject: [PATCH 20/21] Wrap promoted story list header with a Box This is required to ensure that the direction of the header is correct in RTL layouts --- .../promotedlist/PromotedStoryList.kt | 61 ++++++++++--------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt index 55e59672d18..b3c6b1dfbd7 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -52,40 +53,44 @@ fun PromotedStoryList( promotedStoryListViewModel: PromotedStoryListViewModel, machineLocale: OppiaLocale.MachineLocale, ) { - Row( - modifier = Modifier - .testTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG) - .fillMaxWidth() - .padding( - start = dimensionResource(id = R.dimen.promoted_story_list_layout_margin_start), - top = dimensionResource(id = R.dimen.promoted_story_list_layout_margin_top), - end = dimensionResource(id = R.dimen.promoted_story_list_layout_margin_end), - ), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, + Box( + contentAlignment = Alignment.Center, ) { - Text( - text = promotedStoryListViewModel.getHeader(), - color = colorResource(id = R.color.component_color_classroom_shared_header_text_color), - fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.Normal, - fontSize = dimensionResource(id = R.dimen.promoted_story_list_header_text_size).value.sp, + Row( modifier = Modifier - .weight(weight = 1f, fill = false), - ) - if (promotedStoryListViewModel.getViewAllButtonVisibility() == View.VISIBLE) { + .testTag(PROMOTED_STORY_LIST_HEADER_TEST_TAG) + .fillMaxWidth() + .padding( + start = dimensionResource(id = R.dimen.promoted_story_list_layout_margin_start), + top = dimensionResource(id = R.dimen.promoted_story_list_layout_margin_top), + end = dimensionResource(id = R.dimen.promoted_story_list_layout_margin_end), + ), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { Text( - text = machineLocale.run { stringResource(id = R.string.view_all).toMachineUpperCase() }, - color = colorResource(id = R.color.component_color_home_activity_view_all_text_color), + text = promotedStoryListViewModel.getHeader(), + color = colorResource(id = R.color.component_color_classroom_shared_header_text_color), fontFamily = FontFamily.SansSerif, - fontWeight = FontWeight.Medium, - fontSize = dimensionResource(id = R.dimen.promoted_story_list_view_all_text_size).value.sp, + fontWeight = FontWeight.Normal, + fontSize = dimensionResource(id = R.dimen.promoted_story_list_header_text_size).value.sp, modifier = Modifier - .padding( - start = dimensionResource(id = R.dimen.promoted_story_list_view_all_padding_start) - ) - .clickable { promotedStoryListViewModel.clickOnViewAll() }, + .weight(weight = 1f, fill = false), ) + if (promotedStoryListViewModel.getViewAllButtonVisibility() == View.VISIBLE) { + Text( + text = machineLocale.run { stringResource(id = R.string.view_all).toMachineUpperCase() }, + color = colorResource(id = R.color.component_color_home_activity_view_all_text_color), + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Medium, + fontSize = dimensionResource(id = R.dimen.promoted_story_list_view_all_text_size).value.sp, + modifier = Modifier + .padding( + start = dimensionResource(id = R.dimen.promoted_story_list_view_all_padding_start) + ) + .clickable { promotedStoryListViewModel.clickOnViewAll() }, + ) + } } } LazyRow( From 09dc4a0b6ca54ad1eca3848153100a153a4a056b Mon Sep 17 00:00:00 2001 From: Saptak Manna Date: Wed, 7 Aug 2024 18:37:06 +0530 Subject: [PATCH 21/21] Fix ktlint checks --- .../android/app/classroom/classroomlist/ClassroomList.kt | 1 - .../android/app/classroom/promotedlist/PromotedStoryList.kt | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt index fd0e931f703..5a5db784fec 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/classroomlist/ClassroomList.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width diff --git a/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt index b3c6b1dfbd7..ba9fcc32e13 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/promotedlist/PromotedStoryList.kt @@ -83,7 +83,9 @@ fun PromotedStoryList( color = colorResource(id = R.color.component_color_home_activity_view_all_text_color), fontFamily = FontFamily.SansSerif, fontWeight = FontWeight.Medium, - fontSize = dimensionResource(id = R.dimen.promoted_story_list_view_all_text_size).value.sp, + fontSize = dimensionResource( + id = R.dimen.promoted_story_list_view_all_text_size + ).value.sp, modifier = Modifier .padding( start = dimensionResource(id = R.dimen.promoted_story_list_view_all_padding_start)