Skip to content

Commit

Permalink
feat: Tablet UI
Browse files Browse the repository at this point in the history
  • Loading branch information
PavloNetrebchuk committed May 2, 2024
1 parent 3b4677d commit 5fb01ff
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 210 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/org/openedx/core/data/api/CourseApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ interface CourseApi {
suspend fun getUserCourses(
@Path("username") username: String,
@Query("page") page: Int = 1,
@Query("page_size") pageSize: Int = 9,
@Query("page_size") pageSize: Int = 20,
@Query("status") status: String? = null,
@Query("requested_fields") fields: List<String> = emptyList()
): CourseEnrollments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,8 @@ import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.platform.testTag
Expand Down Expand Up @@ -202,17 +200,20 @@ private fun AllEnrolledCoursesScreen(
onAction: (AllEnrolledCoursesAction) -> Unit
) {
val windowSize = rememberWindowSize()
val layoutDirection = LocalLayoutDirection.current
val scaffoldState = rememberScaffoldState()
val scrollState = rememberLazyGridState()
val columns = if (windowSize.isTablet) 3 else 2
val pullRefreshState = rememberPullRefreshState(
refreshing = refreshing,
onRefresh = { onAction(AllEnrolledCoursesAction.SwipeRefresh) }
)
val tabPagerState = rememberPagerState(pageCount = { CourseStatusFilter.entries.size })

val tabPagerState = rememberPagerState(pageCount = {
CourseStatusFilter.entries.size
})
var isInternetConnectionShown by rememberSaveable {
mutableStateOf(false)
}
val scrollState = rememberLazyGridState()
val firstVisibleIndex = remember {
mutableIntStateOf(scrollState.firstVisibleItemIndex)
}
Expand All @@ -226,20 +227,28 @@ private fun AllEnrolledCoursesScreen(
},
backgroundColor = MaterialTheme.appColors.background
) { paddingValues ->

val layoutDirection = LocalLayoutDirection.current
val contentPaddings by remember(key1 = windowSize) {
mutableStateOf(
windowSize.windowSizeValue(
expanded = PaddingValues(
top = 32.dp,
bottom = 40.dp
top = 16.dp,
bottom = 40.dp,
),
compact = PaddingValues(horizontal = 16.dp, vertical = 16.dp)
)
)
}

val roundTapBarPaddings by remember(key1 = windowSize) {
mutableStateOf(
windowSize.windowSizeValue(
expanded = PaddingValues(vertical = 6.dp),
compact = PaddingValues(horizontal = 16.dp, vertical = 6.dp)
)
)
}


val emptyStatePaddings by remember(key1 = windowSize) {
mutableStateOf(
windowSize.windowSizeValue(
Expand All @@ -255,174 +264,167 @@ private fun AllEnrolledCoursesScreen(
val contentWidth by remember(key1 = windowSize) {
mutableStateOf(
windowSize.windowSizeValue(
expanded = Modifier.widthIn(Dp.Unspecified, 560.dp),
expanded = Modifier.widthIn(Dp.Unspecified, 650.dp),
compact = Modifier.fillMaxWidth(),
)
)
}

HandleUIMessage(uiMessage = uiMessage, scaffoldState = scaffoldState)

Column(
Box(
modifier = Modifier
.padding(paddingValues)
.statusBarsInset()
.displayCutoutForLandscape(),
horizontalAlignment = Alignment.CenterHorizontally
.fillMaxSize()
.padding(paddingValues),
contentAlignment = Alignment.TopCenter
) {
BackBtn(
modifier = Modifier.align(Alignment.Start),
tint = MaterialTheme.appColors.textDark
Column(
modifier = Modifier
.statusBarsInset()
.displayCutoutForLandscape()
.then(contentWidth),
horizontalAlignment = Alignment.CenterHorizontally
) {
onAction(AllEnrolledCoursesAction.Back)
}
BackBtn(
modifier = Modifier.align(Alignment.Start),
tint = MaterialTheme.appColors.textDark
) {
onAction(AllEnrolledCoursesAction.Back)
}

Surface(
color = MaterialTheme.appColors.background,
shape = MaterialTheme.appShapes.screenBackgroundShape
) {
Box(
modifier = Modifier
.fillMaxWidth()
.navigationBarsPadding()
.pullRefresh(pullRefreshState),
Surface(
color = MaterialTheme.appColors.background,
shape = MaterialTheme.appShapes.screenBackgroundShape
) {
Column(
Box(
modifier = Modifier
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
.fillMaxWidth()
.navigationBarsPadding()
.pullRefresh(pullRefreshState),
) {
Header(
Column(
modifier = Modifier
.padding(
start = contentPaddings.calculateStartPadding(layoutDirection),
end = contentPaddings.calculateEndPadding(layoutDirection)
),
onSearchClick = {
onAction(AllEnrolledCoursesAction.Search)
}
)
RoundTabsBar(
items = CourseStatusFilter.entries,
contentPadding = PaddingValues(
start = 16.dp,
end = 16.dp,
top = 8.dp,
bottom = 4.dp
),
rowState = rememberLazyListState(),
pagerState = tabPagerState,
onTabClicked = {
val newFilter = CourseStatusFilter.entries[it]
onAction(AllEnrolledCoursesAction.FilterChange(newFilter))
}
)
when (state) {
is AllEnrolledCoursesUIState.Loading -> {
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator(color = MaterialTheme.appColors.primary)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Header(
modifier = Modifier
.padding(
start = contentPaddings.calculateStartPadding(layoutDirection),
end = contentPaddings.calculateEndPadding(layoutDirection)
),
onSearchClick = {
onAction(AllEnrolledCoursesAction.Search)
}
}

is AllEnrolledCoursesUIState.Courses -> {
val density = LocalDensity.current
var itemHeight by rememberSaveable {
mutableStateOf(0f)
)
RoundTabsBar(
modifier = Modifier.align(Alignment.Start),
items = CourseStatusFilter.entries,
contentPadding = roundTapBarPaddings,
rowState = rememberLazyListState(),
pagerState = tabPagerState,
onTabClicked = {
val newFilter = CourseStatusFilter.entries[it]
onAction(AllEnrolledCoursesAction.FilterChange(newFilter))
}
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(
)
when (state) {
is AllEnrolledCoursesUIState.Loading -> {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(contentPaddings)
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
LazyVerticalGrid(
modifier = Modifier
.fillMaxHeight()
.then(contentWidth),
state = scrollState,
columns = GridCells.Fixed(2),
verticalArrangement = Arrangement.spacedBy(12.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp),
content = {
items(state.courses) { course ->
CourseItem(
modifier = Modifier
.onSizeChanged {
itemHeight = it.height.toFloat()
},
course = course,
apiHostUrl = apiHostUrl,
onClick = {
onAction(AllEnrolledCoursesAction.OpenCourse(it))
}
)
}
item {
if (canLoadMore) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(with(density) { itemHeight.toDp() }),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator(
color = MaterialTheme.appColors.primary
)
CircularProgressIndicator(color = MaterialTheme.appColors.primary)
}
}

is AllEnrolledCoursesUIState.Courses -> {
Box(
modifier = Modifier
.fillMaxSize()
.padding(contentPaddings),
contentAlignment = Alignment.Center
) {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
LazyVerticalGrid(
modifier = Modifier
.fillMaxHeight(),
state = scrollState,
columns = GridCells.Fixed(columns),
verticalArrangement = Arrangement.spacedBy(12.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp),
content = {
items(state.courses) { course ->
CourseItem(
course = course,
apiHostUrl = apiHostUrl,
onClick = {
onAction(AllEnrolledCoursesAction.OpenCourse(it))
}
)
}
item {
if (canLoadMore) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(180.dp),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator(
color = MaterialTheme.appColors.primary
)
}
}
}
}
}
)
}
if (scrollState.shouldLoadMore(firstVisibleIndex, 4)) {
onAction(AllEnrolledCoursesAction.EndOfPage)
)
}
if (scrollState.shouldLoadMore(firstVisibleIndex, 4)) {
onAction(AllEnrolledCoursesAction.EndOfPage)
}
}
}
}

is AllEnrolledCoursesUIState.Empty -> {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Column(
modifier = Modifier
.fillMaxHeight()
.then(contentWidth)
.then(emptyStatePaddings)
is AllEnrolledCoursesUIState.Empty -> {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
EmptyState()
Column(
modifier = Modifier
.fillMaxHeight()
.then(emptyStatePaddings)
) {
EmptyState()
}
}
}
}
}
}
PullRefreshIndicator(
refreshing,
pullRefreshState,
Modifier.align(Alignment.TopCenter)
)

if (!isInternetConnectionShown && !hasInternetConnection) {
OfflineModeDialog(
Modifier
.fillMaxWidth()
.align(Alignment.BottomCenter),
onDismissCLick = {
isInternetConnectionShown = true
},
onReloadClick = {
isInternetConnectionShown = true
onAction(AllEnrolledCoursesAction.Reload)
}
PullRefreshIndicator(
refreshing,
pullRefreshState,
Modifier.align(Alignment.TopCenter)
)

if (!isInternetConnectionShown && !hasInternetConnection) {
OfflineModeDialog(
Modifier
.fillMaxWidth()
.align(Alignment.BottomCenter),
onDismissCLick = {
isInternetConnectionShown = true
},
onReloadClick = {
isInternetConnectionShown = true
onAction(AllEnrolledCoursesAction.Reload)
}
)
}
}
}
}
Expand Down
Loading

0 comments on commit 5fb01ff

Please sign in to comment.