Skip to content

Commit e8ee9ca

Browse files
feat: next prev buttons logic update for video view mode
1 parent 811788b commit e8ee9ca

File tree

8 files changed

+1483
-105
lines changed

8 files changed

+1483
-105
lines changed

app/schemas/org.openedx.app.room.AppDatabase/5.json

Lines changed: 1236 additions & 0 deletions
Large diffs are not rendered by default.

app/src/main/java/org/openedx/app/di/ScreenModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import org.openedx.auth.presentation.signin.SignInViewModel
1313
import org.openedx.auth.presentation.signup.SignUpViewModel
1414
import org.openedx.core.Validator
1515
import org.openedx.core.domain.interactor.CalendarInteractor
16-
import org.openedx.core.presentation.course.CourseViewMode
1716
import org.openedx.core.presentation.dialog.selectorbottomsheet.SelectDialogViewModel
1817
import org.openedx.core.presentation.settings.video.VideoQualityViewModel
1918
import org.openedx.core.repository.CalendarRepository
@@ -30,6 +29,7 @@ import org.openedx.course.presentation.outline.CourseContentAllViewModel
3029
import org.openedx.course.presentation.progress.CourseProgressViewModel
3130
import org.openedx.course.presentation.section.CourseSectionViewModel
3231
import org.openedx.course.presentation.unit.container.CourseUnitContainerViewModel
32+
import org.openedx.course.presentation.unit.container.CourseViewMode
3333
import org.openedx.course.presentation.unit.html.HtmlUnitViewModel
3434
import org.openedx.course.presentation.unit.video.BaseVideoViewModel
3535
import org.openedx.course.presentation.unit.video.EncodedVideoUnitViewModel

app/src/main/java/org/openedx/app/room/AppDatabase.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import org.openedx.discovery.data.converter.DiscoveryConverter
2323
import org.openedx.discovery.data.model.room.CourseEntity
2424
import org.openedx.discovery.data.storage.DiscoveryDao
2525

26-
const val DATABASE_VERSION = 4
26+
const val DATABASE_VERSION = 5
2727
const val DATABASE_NAME = "OpenEdX_db"
2828

2929
@Suppress("MagicNumber")
@@ -44,7 +44,8 @@ const val DATABASE_NAME = "OpenEdX_db"
4444
autoMigrations = [
4545
AutoMigration(1, 2),
4646
AutoMigration(2, 3),
47-
AutoMigration(3, DATABASE_VERSION),
47+
AutoMigration(3, 4),
48+
AutoMigration(4, DATABASE_VERSION),
4849
],
4950
version = DATABASE_VERSION
5051
)

course/src/main/java/org/openedx/course/presentation/ui/CourseUI.kt

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ fun NavigationUnitsButtons(
338338
nextButtonText: String,
339339
hasPrevBlock: Boolean,
340340
hasNextBlock: Boolean,
341+
showFinishButton: Boolean = true,
341342
isVerticalNavigation: Boolean,
342343
onPrevClick: () -> Unit,
343344
onNextClick: () -> Unit,
@@ -400,32 +401,34 @@ fun NavigationUnitsButtons(
400401
}
401402
Spacer(Modifier.width(16.dp))
402403
}
403-
Button(
404-
modifier = Modifier
405-
.height(42.dp),
406-
colors = ButtonDefaults.buttonColors(
407-
backgroundColor = MaterialTheme.appColors.primaryButtonBackground
408-
),
409-
elevation = null,
410-
shape = MaterialTheme.appShapes.navigationButtonShape,
411-
onClick = onNextClick
412-
) {
413-
Row(
414-
verticalAlignment = Alignment.CenterVertically,
415-
horizontalArrangement = Arrangement.Center
404+
if (hasNextBlock || showFinishButton) {
405+
Button(
406+
modifier = Modifier
407+
.height(42.dp),
408+
colors = ButtonDefaults.buttonColors(
409+
backgroundColor = MaterialTheme.appColors.primaryButtonBackground
410+
),
411+
elevation = null,
412+
shape = MaterialTheme.appShapes.navigationButtonShape,
413+
onClick = onNextClick
416414
) {
417-
Text(
418-
text = nextButtonText,
419-
color = MaterialTheme.appColors.primaryButtonText,
420-
style = MaterialTheme.appTypography.labelLarge
421-
)
422-
Spacer(Modifier.width(8.dp))
423-
Icon(
424-
modifier = Modifier.rotate(if (isVerticalNavigation || !hasNextBlock) 0f else -90f),
425-
painter = nextButtonIcon,
426-
contentDescription = null,
427-
tint = MaterialTheme.appColors.primaryButtonText
428-
)
415+
Row(
416+
verticalAlignment = Alignment.CenterVertically,
417+
horizontalArrangement = Arrangement.Center
418+
) {
419+
Text(
420+
text = nextButtonText,
421+
color = MaterialTheme.appColors.primaryButtonText,
422+
style = MaterialTheme.appTypography.labelLarge
423+
)
424+
Spacer(Modifier.width(8.dp))
425+
Icon(
426+
modifier = Modifier.rotate(if (isVerticalNavigation || !hasNextBlock) 0f else -90f),
427+
painter = nextButtonIcon,
428+
contentDescription = null,
429+
tint = MaterialTheme.appColors.primaryButtonText
430+
)
431+
}
429432
}
430433
}
431434
}
@@ -673,9 +676,6 @@ fun CourseVideoSection(
673676
0f
674677
}
675678
CourseVideoItem(
676-
modifier = Modifier
677-
.width(192.dp)
678-
.height(108.dp),
679679
modifier = Modifier
680680
.width(videoCardWidth)
681681
.height(108.dp)

course/src/main/java/org/openedx/course/presentation/unit/container/CourseUnitContainerFragment.kt

Lines changed: 87 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
4646
import org.koin.core.parameter.parametersOf
4747
import org.openedx.core.BlockType
4848
import org.openedx.core.domain.model.Block
49-
import org.openedx.core.presentation.course.CourseViewMode
5049
import org.openedx.core.presentation.global.InsetHolder
5150
import org.openedx.core.ui.theme.OpenEdXTheme
5251
import org.openedx.core.ui.theme.appColors
@@ -151,7 +150,7 @@ class CourseUnitContainerFragment : Fragment(R.layout.fragment_course_unit_conta
151150
super.onCreate(savedInstanceState)
152151
lifecycle.addObserver(viewModel)
153152
componentId = requireArguments().getString(ARG_COMPONENT_ID, "")
154-
viewModel.loadBlocks(viewModel.mode, componentId)
153+
viewModel.loadBlocks(componentId)
155154
viewModel.courseUnitContainerShowedEvent()
156155
}
157156

@@ -489,43 +488,95 @@ class CourseUnitContainerFragment : Fragment(R.layout.fragment_course_unit_conta
489488

490489
@Composable
491490
private fun NavigationBar() {
492-
OpenEdXTheme {
493-
var nextButtonText by rememberSaveable {
494-
mutableStateOf(viewModel.nextButtonText)
495-
}
496-
var hasNextBlock by rememberSaveable {
497-
mutableStateOf(viewModel.hasNextBlock)
498-
}
499-
var hasPrevBlock by rememberSaveable {
500-
mutableStateOf(viewModel.hasNextBlock)
491+
if (viewModel.mode == CourseViewMode.VIDEOS) {
492+
OpenEdXTheme {
493+
val videoBlocks by viewModel.videoList.collectAsState()
494+
val currentBlock by viewModel.currentBlock.collectAsState()
495+
val hasNextBlock = videoBlocks.lastOrNull()?.id != currentBlock?.id
496+
val nextButtonText = if (hasNextBlock) {
497+
getString(R.string.course_navigation_next)
498+
} else {
499+
getString(R.string.course_navigation_finish)
500+
}
501+
NavigationUnitsButtons(
502+
hasPrevBlock = videoBlocks.firstOrNull()?.id != currentBlock?.id,
503+
nextButtonText = nextButtonText,
504+
hasNextBlock = hasNextBlock,
505+
isVerticalNavigation = false,
506+
showFinishButton = false,
507+
onPrevClick = {
508+
if (!restrictDoubleClick()) {
509+
val currentIndex =
510+
videoBlocks.indexOfFirst { it.id == currentBlock?.id }
511+
if (currentIndex > 0) {
512+
val target = videoBlocks[currentIndex - 1]
513+
viewModel.setSelectedVideoBlock(target)
514+
updateViewPagerAdapter()
515+
val blockIndex =
516+
viewModel.getUnitBlocks().indexOfFirst { it.id == target.id }
517+
if (blockIndex != -1) {
518+
binding.viewPager.setCurrentItem(blockIndex, true)
519+
}
520+
}
521+
}
522+
},
523+
onNextClick = {
524+
if (!restrictDoubleClick()) {
525+
val currentIndex =
526+
videoBlocks.indexOfFirst { it.id == currentBlock?.id }
527+
if (currentIndex != -1 && currentIndex < videoBlocks.lastIndex) {
528+
val target = videoBlocks[currentIndex + 1]
529+
viewModel.setSelectedVideoBlock(target)
530+
updateViewPagerAdapter()
531+
val blockIndex =
532+
viewModel.getUnitBlocks().indexOfFirst { it.id == target.id }
533+
if (blockIndex != -1) {
534+
binding.viewPager.setCurrentItem(blockIndex, true)
535+
}
536+
}
537+
}
538+
}
539+
)
501540
}
541+
} else {
542+
OpenEdXTheme {
543+
var nextButtonText by rememberSaveable {
544+
mutableStateOf(viewModel.nextButtonText)
545+
}
546+
var hasNextBlock by rememberSaveable {
547+
mutableStateOf(viewModel.hasNextBlock)
548+
}
549+
var hasPrevBlock by rememberSaveable {
550+
mutableStateOf(viewModel.hasNextBlock)
551+
}
502552

503-
updateNavigationButtons { next, hasPrev, hasNext ->
504-
nextButtonText = next
505-
hasPrevBlock = hasPrev
506-
hasNextBlock = hasNext
507-
}
553+
updateNavigationButtons { next, hasPrev, hasNext ->
554+
nextButtonText = next
555+
hasPrevBlock = hasPrev
556+
hasNextBlock = hasNext
557+
}
508558

509-
NavigationUnitsButtons(
510-
hasPrevBlock = hasPrevBlock,
511-
nextButtonText = nextButtonText,
512-
hasNextBlock = hasNextBlock,
513-
isVerticalNavigation = !viewModel.isCourseUnitProgressEnabled || viewModel.mode != CourseViewMode.VIDEOS,
514-
onPrevClick = {
515-
handlePrevClick { next, hasPrev, hasNext ->
516-
nextButtonText = next
517-
hasPrevBlock = hasPrev
518-
hasNextBlock = hasNext
519-
}
520-
},
521-
onNextClick = {
522-
handleNextClick { next, hasPrev, hasNext ->
523-
nextButtonText = next
524-
hasPrevBlock = hasPrev
525-
hasNextBlock = hasNext
559+
NavigationUnitsButtons(
560+
hasPrevBlock = hasPrevBlock,
561+
nextButtonText = nextButtonText,
562+
hasNextBlock = hasNextBlock,
563+
isVerticalNavigation = !viewModel.isCourseUnitProgressEnabled,
564+
onPrevClick = {
565+
handlePrevClick { next, hasPrev, hasNext ->
566+
nextButtonText = next
567+
hasPrevBlock = hasPrev
568+
hasNextBlock = hasNext
569+
}
570+
},
571+
onNextClick = {
572+
handleNextClick { next, hasPrev, hasNext ->
573+
nextButtonText = next
574+
hasPrevBlock = hasPrev
575+
hasNextBlock = hasNext
576+
}
526577
}
527-
}
528-
)
578+
)
579+
}
529580
}
530581
}
531582

@@ -571,7 +622,7 @@ class CourseUnitContainerFragment : Fragment(R.layout.fragment_course_unit_conta
571622
onClick = {
572623
onVideoClick(block)
573624
},
574-
style = MaterialTheme.appTypography.labelSmall,
625+
titleStyle = MaterialTheme.appTypography.labelSmall,
575626
playButtonSize = playButtonSize,
576627
borderColor = borderColor
577628
)

course/src/main/java/org/openedx/course/presentation/unit/container/CourseUnitContainerViewModel.kt

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,6 @@ class CourseUnitContainerViewModel(
9898

9999
var nextButtonText = ""
100100
var hasNextBlock = false
101-
102-
private var currentMode: CourseViewMode? = null
103101
private var currentComponentId = ""
104102
private var courseName = ""
105103

@@ -109,8 +107,7 @@ class CourseUnitContainerViewModel(
109107
val hasNetworkConnection: Boolean
110108
get() = networkConnection.isOnline()
111109

112-
fun loadBlocks(mode: CourseViewMode, componentId: String = "") {
113-
currentMode = mode
110+
fun loadBlocks(componentId: String = "") {
114111
viewModelScope.launch {
115112
try {
116113
val courseStructure = when (mode) {
@@ -138,8 +135,7 @@ class CourseUnitContainerViewModel(
138135
notifier.notifier.collect { event ->
139136
if (event is CourseStructureUpdated) {
140137
if (event.courseId != courseId) return@collect
141-
142-
currentMode?.let { loadBlocks(it, currentComponentId) }
138+
loadBlocks(currentComponentId)
143139
val blockId = blocks[currentVerticalIndex].id
144140
_subSectionUnitBlocks.value =
145141
getSubSectionUnitBlocks(blocks, getSubSectionId(blockId))
@@ -402,8 +398,8 @@ class CourseUnitContainerViewModel(
402398
val videoBlocks = getAllVideoBlocks()
403399
val videoProgress = videoBlocks.associate { block ->
404400
val videoProgressEntity = interactor.getVideoProgress(block.id)
405-
val progress = videoProgressEntity.videoTime.toFloat()
406-
.safeDivBy(videoProgressEntity.duration.toFloat())
401+
val progress = videoProgressEntity.videoTime?.toFloat()
402+
?.safeDivBy(videoProgressEntity.duration?.toFloat() ?: 0f) ?: 0f
407403
block.id to progress
408404
}
409405
_videoProgress.value = videoProgress

0 commit comments

Comments
 (0)