@@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Arrangement
1313import androidx.compose.foundation.layout.Box
1414import androidx.compose.foundation.layout.Column
1515import androidx.compose.foundation.layout.PaddingValues
16+ import androidx.compose.foundation.layout.Row
1617import androidx.compose.foundation.layout.fillMaxSize
1718import androidx.compose.foundation.layout.fillMaxWidth
1819import androidx.compose.foundation.layout.navigationBarsPadding
@@ -26,6 +27,8 @@ import androidx.compose.foundation.rememberScrollState
2627import androidx.compose.foundation.verticalScroll
2728import androidx.compose.material.Divider
2829import androidx.compose.material.ExperimentalMaterialApi
30+ import androidx.compose.material.Icon
31+ import androidx.compose.material.IconButton
2932import androidx.compose.material.MaterialTheme
3033import androidx.compose.material.Scaffold
3134import androidx.compose.material.SnackbarData
@@ -34,6 +37,9 @@ import androidx.compose.material.SnackbarHost
3437import androidx.compose.material.SnackbarHostState
3538import androidx.compose.material.Text
3639import androidx.compose.material.TextButton
40+ import androidx.compose.material.icons.Icons
41+ import androidx.compose.material.icons.automirrored.filled.ArrowBackIos
42+ import androidx.compose.material.icons.automirrored.filled.ArrowForwardIos
3743import androidx.compose.material.pullrefresh.PullRefreshIndicator
3844import androidx.compose.material.pullrefresh.pullRefresh
3945import androidx.compose.material.pullrefresh.rememberPullRefreshState
@@ -77,6 +83,7 @@ import org.openedx.core.ui.HandleUIMessage
7783import org.openedx.core.ui.IconText
7884import org.openedx.core.ui.OfflineModeDialog
7985import org.openedx.core.ui.OpenEdXButton
86+ import org.openedx.core.ui.PageIndicator
8087import org.openedx.core.ui.RoundTabsBar
8188import org.openedx.core.ui.statusBarsInset
8289import org.openedx.core.ui.theme.OpenEdXTheme
@@ -90,6 +97,7 @@ import org.openedx.course.presentation.contenttab.ContentTabScreen
9097import org.openedx.course.presentation.dates.CourseDatesScreen
9198import org.openedx.course.presentation.handouts.HandoutsScreen
9299import org.openedx.course.presentation.handouts.HandoutsType
100+ import org.openedx.course.presentation.home.CourseHomePagerTab
93101import org.openedx.course.presentation.home.CourseHomeScreen
94102import org.openedx.course.presentation.offline.CourseOfflineScreen
95103import org.openedx.course.presentation.progress.CourseProgressScreen
@@ -273,6 +281,10 @@ fun CourseDashboard(
273281 initialPage = 0 ,
274282 pageCount = { CourseContentTab .entries.size }
275283 )
284+ val homePagerState = rememberPagerState(
285+ initialPage = 0 ,
286+ pageCount = { CourseHomePagerTab .entries.size }
287+ )
276288 val accessStatus = viewModel.courseAccessStatus.observeAsState()
277289 val tabState = rememberLazyListState()
278290 val snackState = remember { SnackbarHostState () }
@@ -293,28 +305,12 @@ fun CourseDashboard(
293305 scaffoldState = scaffoldState,
294306 backgroundColor = MaterialTheme .appColors.background,
295307 bottomBar = {
308+ val currentPage = CourseContainerTab .entries[pagerState.currentPage]
296309 Box {
297- if (CourseContainerTab .entries[pagerState.currentPage] == CourseContainerTab .CONTENT &&
298- selectedContentTab == CourseContentTab .ASSIGNMENTS
299- ) {
300- Column (
301- modifier = Modifier .background(MaterialTheme .appColors.background),
302- horizontalAlignment = Alignment .CenterHorizontally
303- ) {
304- Divider (modifier = Modifier .fillMaxWidth())
305- TextButton (
306- onClick = {
307- scrollToProgress(scope, pagerState)
308- }
309- ) {
310- IconText (
311- text = stringResource(R .string.course_review_grading_policy),
312- painter = painterResource(id = coreR.drawable.core_ic_mountains),
313- color = MaterialTheme .appColors.primary,
314- textStyle = MaterialTheme .appTypography.labelLarge
315- )
316- }
317- }
310+ if (currentPage == CourseContainerTab .CONTENT && selectedContentTab == CourseContentTab .ASSIGNMENTS ) {
311+ AssignmentsBottomBar (scope = scope, pagerState = pagerState)
312+ } else if (currentPage == CourseContainerTab .HOME ) {
313+ HomeNavigationRow (homePagerState = homePagerState)
318314 }
319315 var isInternetConnectionShown by rememberSaveable {
320316 mutableStateOf(false )
@@ -412,6 +408,7 @@ fun CourseDashboard(
412408 viewModel = viewModel,
413409 pagerState = pagerState,
414410 contentTabPagerState = contentTabPagerState,
411+ homePagerState = homePagerState,
415412 isResumed = isResumed,
416413 fragmentManager = fragmentManager,
417414 onContentTabSelected = { tab ->
@@ -457,6 +454,7 @@ private fun DashboardPager(
457454 viewModel : CourseContainerViewModel ,
458455 pagerState : PagerState ,
459456 contentTabPagerState : PagerState ,
457+ homePagerState : PagerState ,
460458 isResumed : Boolean ,
461459 fragmentManager : FragmentManager ,
462460 onContentTabSelected : (CourseContentTab ) -> Unit ,
@@ -476,6 +474,7 @@ private fun DashboardPager(
476474 parameters = { parametersOf(viewModel.courseId, viewModel.courseName) }
477475 ),
478476 fragmentManager = fragmentManager,
477+ homePagerState = homePagerState,
479478 onResetDatesClick = {
480479 viewModel.onRefresh(CourseContainerTab .DATES )
481480 },
@@ -713,3 +712,87 @@ private fun scrollToProgress(scope: CoroutineScope, pagerState: PagerState) {
713712 pagerState.animateScrollToPage(CourseContainerTab .entries.indexOf(CourseContainerTab .PROGRESS ))
714713 }
715714}
715+
716+ @Composable
717+ private fun HomeNavigationRow (homePagerState : PagerState ) {
718+ val homeCoroutineScope = rememberCoroutineScope()
719+ Row (
720+ modifier = Modifier .fillMaxWidth(),
721+ horizontalArrangement = Arrangement .SpaceBetween ,
722+ verticalAlignment = Alignment .CenterVertically
723+ ) {
724+ val isPreviousPageEnabled = homePagerState.currentPage > 0
725+ IconButton (
726+ enabled = homePagerState.currentPage > 0 ,
727+ onClick = {
728+ homeCoroutineScope.launch {
729+ homePagerState.animateScrollToPage(homePagerState.currentPage - 1 )
730+ }
731+ }
732+ ) {
733+ Icon (
734+ modifier = Modifier .size(12 .dp),
735+ imageVector = Icons .AutoMirrored .Filled .ArrowBackIos ,
736+ contentDescription = stringResource(coreR.string.core_previous),
737+ tint = if (isPreviousPageEnabled) {
738+ MaterialTheme .appColors.textDark
739+ } else {
740+ MaterialTheme .appColors.textFieldHint
741+ }
742+ )
743+ }
744+ PageIndicator (
745+ modifier = Modifier .padding(vertical = 16 .dp),
746+ numberOfPages = CourseHomePagerTab .entries.size,
747+ selectedPage = homePagerState.currentPage,
748+ defaultRadius = 8 .dp,
749+ space = 8 .dp,
750+ selectedLength = 24 .dp,
751+ )
752+ val isNextPageEnabled = homePagerState.currentPage < CourseHomePagerTab .entries.size - 1
753+ IconButton (
754+ enabled = isNextPageEnabled,
755+ onClick = {
756+ homeCoroutineScope.launch {
757+ homePagerState.animateScrollToPage(homePagerState.currentPage + 1 )
758+ }
759+ }
760+ ) {
761+ Icon (
762+ modifier = Modifier .size(12 .dp),
763+ imageVector = Icons .AutoMirrored .Filled .ArrowForwardIos ,
764+ contentDescription = stringResource(coreR.string.core_next),
765+ tint = if (isNextPageEnabled) {
766+ MaterialTheme .appColors.textDark
767+ } else {
768+ MaterialTheme .appColors.textFieldHint
769+ }
770+ )
771+ }
772+ }
773+ }
774+
775+ @Composable
776+ private fun AssignmentsBottomBar (
777+ scope : CoroutineScope ,
778+ pagerState : PagerState
779+ ) {
780+ Column (
781+ modifier = Modifier .background(MaterialTheme .appColors.background),
782+ horizontalAlignment = Alignment .CenterHorizontally
783+ ) {
784+ Divider (modifier = Modifier .fillMaxWidth())
785+ TextButton (
786+ onClick = {
787+ scrollToProgress(scope, pagerState)
788+ }
789+ ) {
790+ IconText (
791+ text = stringResource(R .string.course_review_grading_policy),
792+ painter = painterResource(id = coreR.drawable.core_ic_mountains),
793+ color = MaterialTheme .appColors.primary,
794+ textStyle = MaterialTheme .appTypography.labelLarge
795+ )
796+ }
797+ }
798+ }
0 commit comments