Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion core/src/main/java/org/openedx/core/ui/ComposeExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,24 @@

fun LazyGridState.shouldLoadMore(rememberedIndex: MutableState<Int>, threshold: Int): Boolean {
val firstVisibleIndex = this.firstVisibleItemIndex
val totalItems = layoutInfo.totalItemsCount
val visibleItems = layoutInfo.visibleItemsInfo.size

// Extra check: if all items fit on screen, trigger load more
if (totalItems in 1..visibleItems) {
return true
}

if (rememberedIndex.value != firstVisibleIndex) {
rememberedIndex.value = firstVisibleIndex
val lastVisibleIndex = layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0
return lastVisibleIndex >= layoutInfo.totalItemsCount - 1 - threshold
return lastVisibleIndex >= totalItems - 1 - threshold
}
return false
}


fun Modifier.statusBarsInset(): Modifier = composed {

Check warning

Code scanning / detekt

Reports consecutive blank lines Warning

Needless blank line(s)
val topInset = (LocalContext.current as? InsetHolder)?.topInset ?: 0
return@composed this
.padding(top = with(LocalDensity.current) { topInset.toDp() })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.fillMaxHeight
Expand Down Expand Up @@ -406,10 +407,10 @@
apiHostUrl: String,
onClick: (EnrolledCourse) -> Unit,
) {
val courseNameHeight = 60.dp
Card(
modifier = modifier
.width(170.dp)
.height(180.dp)
.clickable {
onClick(course)
},
Expand All @@ -429,7 +430,7 @@
contentScale = ContentScale.Crop,
modifier = Modifier
.fillMaxWidth()
.height(90.dp)
.aspectRatio(16f / 9f)

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.
)
val progress: Float = try {
course.progress.assignmentsCompleted.toFloat() / course.progress.totalAssignmentsCount.toFloat()
Expand Down Expand Up @@ -467,7 +468,8 @@
)
Text(
modifier = Modifier
.padding(horizontal = 8.dp, vertical = 4.dp),
.padding(horizontal = 8.dp, vertical = 2.dp)
.height(courseNameHeight),
text = course.course.name,
style = MaterialTheme.appTypography.titleSmall,
color = MaterialTheme.appColors.textDark,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class DashboardGalleryFragment : Fragment() {
}

companion object {
const val TABLET_COURSE_LIST_ITEM_COUNT = 7
const val MOBILE_COURSE_LIST_ITEM_COUNT = 7
const val TABLET_COURSE_LIST_ITEM_COUNT = 5
const val MOBILE_COURSE_LIST_ITEM_COUNT = 3
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
Expand All @@ -17,6 +18,7 @@
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
import androidx.compose.foundation.lazy.grid.items
Expand Down Expand Up @@ -46,10 +48,12 @@
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.layout.ContentScale
Expand All @@ -62,6 +66,7 @@
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
Expand Down Expand Up @@ -100,6 +105,7 @@
import org.openedx.foundation.extension.toImageLink
import org.openedx.foundation.presentation.UIMessage
import org.openedx.foundation.presentation.rememberWindowSize
import org.openedx.foundation.presentation.windowSizeValue
import java.util.Date
import org.openedx.core.R as CoreR

Expand Down Expand Up @@ -190,6 +196,17 @@
mutableStateOf(false)
}

val windowSize = rememberWindowSize()

val contentWidth by remember(key1 = windowSize) {
mutableStateOf(
windowSize.windowSizeValue(
expanded = Modifier.widthIn(Dp.Unspecified, 700.dp),
compact = Modifier.fillMaxWidth()
)
)
}

Scaffold(
scaffoldState = scaffoldState,
modifier = Modifier.fillMaxSize(),
Expand All @@ -205,11 +222,13 @@
color = MaterialTheme.appColors.background
) {
Box(
Modifier.fillMaxSize()
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Box(
Modifier
.fillMaxSize()
modifier = Modifier
.fillMaxHeight()
.then(contentWidth)
.pullRefresh(pullRefreshState)
.verticalScroll(rememberScrollState()),
) {
Expand Down Expand Up @@ -334,8 +353,8 @@
} else {
MOBILE_COURSE_LIST_ITEM_COUNT
}
val rows = if (windowSize.isTablet) 2 else 1
val height = if (windowSize.isTablet) 322.dp else 152.dp
val rows = if (windowSize.isTablet) 1 else 1
val height = if (windowSize.isTablet) 200.dp else 200.dp
val items = courses.take(itemsCount)
Column(
modifier = Modifier
Expand Down Expand Up @@ -426,8 +445,7 @@
) {
Card(
modifier = Modifier
.width(140.dp)
.height(152.dp)
.width(190.dp)
.padding(4.dp)
.clickable {
onCourseClick(course)
Expand All @@ -448,17 +466,18 @@
contentScale = ContentScale.Crop,
modifier = Modifier
.fillMaxWidth()
.height(90.dp)
.aspectRatio(16f / 9f)

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.
.clip(MaterialTheme.appShapes.courseImageShape)
)
Text(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
.padding(horizontal = 4.dp, vertical = 8.dp),
text = course.course.name,
style = MaterialTheme.appTypography.titleSmall,
color = MaterialTheme.appColors.textDark,
overflow = TextOverflow.Ellipsis,
maxLines = 2,
maxLines = 3,
minLines = 2
)
}
Expand Down Expand Up @@ -552,10 +571,9 @@
.placeholder(CoreR.drawable.core_no_image_course)
.build(),
contentDescription = null,
contentScale = ContentScale.Crop,
contentScale = ContentScale.FillWidth,
modifier = Modifier
.fillMaxWidth()
.height(140.dp)
)
val progress: Float = try {
primaryCourse.progress.assignmentsCompleted.toFloat() /
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
Expand All @@ -34,10 +34,12 @@
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
Expand All @@ -61,6 +63,7 @@
import androidx.compose.ui.zIndex
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import kotlinx.coroutines.flow.collectLatest
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.openedx.core.domain.model.Media
Expand Down Expand Up @@ -184,9 +187,9 @@
onSignInClick: () -> Unit,
) {
val scaffoldState = rememberScaffoldState()
val scrollState = rememberLazyListState()
val scrollState = rememberLazyGridState()
val firstVisibleIndex = remember {
mutableStateOf(scrollState.firstVisibleItemIndex)
mutableIntStateOf(scrollState.firstVisibleItemIndex)
}
val pullRefreshState =
rememberPullRefreshState(refreshing = refreshing, onRefresh = { onSwipeRefresh() })
Expand All @@ -207,6 +210,16 @@
focusManager.clearFocus()
}

LaunchedEffect(scrollState) {
snapshotFlow { firstVisibleIndex }.collectLatest { index ->
val totalItems = scrollState.layoutInfo.totalItemsCount
val lastVisibleItem = scrollState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0
if (lastVisibleItem >= totalItems - LOAD_MORE_THRESHOLD) {
paginationCallback()
}
}
}

Scaffold(
scaffoldState = scaffoldState,
modifier = Modifier
Expand Down Expand Up @@ -262,6 +275,12 @@
)
}

val columns = if (windowSize.width == WindowType.Compact) {
GridCells.Fixed(2) // phone

Check warning

Code scanning / detekt

Reports multiple space usages Warning

Unnecessary long whitespace
} else {
GridCells.Fixed(3) // tablet / larger

Check warning

Code scanning / detekt

Report magic numbers. Magic number is a numeric literal that is not defined as a constant and hence it's unclear what the purpose of this number is. It's better to declare such numbers as constants and give them a proper name. By default, -1, 0, 1, and 2 are not considered to be magic numbers. Warning

This expression contains a magic number. Consider defining it to a well named constant.

Check warning

Code scanning / detekt

Reports multiple space usages Warning

Unnecessary long whitespace
}

HandleUIMessage(uiMessage = uiMessage, scaffoldState = scaffoldState)

Box(
Expand Down Expand Up @@ -340,12 +359,15 @@
(state as? CourseSearchUIState.Courses)?.numCourses ?: 0
)
}
LazyColumn(
Modifier.fillMaxSize(),
contentPadding = contentPaddings,
state = scrollState
LazyVerticalGrid(
columns = columns,
modifier = Modifier.fillMaxSize(),
state = scrollState,
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalArrangement = Arrangement.spacedBy(12.dp),
contentPadding = contentPaddings
) {
item {
item(span = { GridItemSpan(maxLineSpan) }) {
Column {
Text(
modifier = Modifier.testTag("txt_search_results_title"),
Expand All @@ -366,11 +388,9 @@
}
when (state) {
is CourseSearchUIState.Loading -> {
item {
item(span = { GridItemSpan(maxLineSpan) }) {
Box(
Modifier
.fillMaxSize()
.padding(vertical = 25.dp),
Modifier.fillMaxWidth().padding(vertical = 25.dp),
contentAlignment = Alignment.Center
) {
CircularProgressIndicator(color = MaterialTheme.appColors.primary)
Expand All @@ -379,7 +399,11 @@
}

is CourseSearchUIState.Courses -> {
items(state.courses) { course ->
items(
count = state.courses.size,
key = { index -> "${state.courses[index].courseId}_$index" }
) { index ->
val course = state.courses[index]
DiscoveryCourseItem(
apiHostUrl = apiHostUrl,
course,
Expand All @@ -388,10 +412,9 @@
onItemClick(courseId)
}
)
Divider()
}
item {
if (canLoadMore) {
if (canLoadMore) {
item(span = { GridItemSpan(maxLineSpan) }) {
Box(
modifier = Modifier
.fillMaxWidth()
Expand Down
Loading
Loading