Skip to content

Commit

Permalink
fix: Update resume course navigation (openedx#151)
Browse files Browse the repository at this point in the history
* fix: Update resume course navigation

- Update navigation for resume component
- Code improvement & optimisation

fix: LEARNER-9703

* fix: handle video block for resume navigation

* fix: Address PR comment and code improvements

* fix: Address PR comments-2
  • Loading branch information
omerhabib26 authored Dec 12, 2023
1 parent 7265f38 commit cd27754
Show file tree
Hide file tree
Showing 13 changed files with 147 additions and 90 deletions.
35 changes: 27 additions & 8 deletions app/src/main/java/org/openedx/app/AppRouter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -127,37 +127,56 @@ class AppRouter : AuthRouter, DiscoveryRouter, DashboardRouter, CourseRouter, Di
override fun navigateToCourseSubsections(
fm: FragmentManager,
courseId: String,
blockId: String,
mode: CourseViewMode,
descendantId: String?
subSectionId: String,
unitId: String,
componentId: String,
mode: CourseViewMode
) {
replaceFragmentWithBackStack(
fm,
CourseSectionFragment.newInstance(courseId, blockId, mode, descendantId)
CourseSectionFragment.newInstance(
courseId = courseId,
subSectionId = subSectionId,
unitId = unitId,
componentId = componentId,
mode = mode
)
)
}

override fun navigateToCourseContainer(
fm: FragmentManager,
blockId: String,
courseId: String,
unitId: String,
componentId: String,
mode: CourseViewMode
) {
replaceFragmentWithBackStack(
fm,
CourseUnitContainerFragment.newInstance(blockId, courseId, mode)
CourseUnitContainerFragment.newInstance(
courseId = courseId,
unitId = unitId,
componentId = componentId,
mode = mode
)
)
}

override fun replaceCourseContainer(
fm: FragmentManager,
blockId: String,
courseId: String,
unitId: String,
componentId: String,
mode: CourseViewMode
) {
replaceFragment(
fm,
CourseUnitContainerFragment.newInstance(blockId, courseId, mode),
CourseUnitContainerFragment.newInstance(
courseId = courseId,
unitId = unitId,
componentId = componentId,
mode = mode
),
FragmentTransaction.TRANSIT_FRAGMENT_FADE
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.openedx.core.domain.model

import org.openedx.core.BlockType
import java.util.Date

data class CourseStructure(
Expand All @@ -18,12 +17,4 @@ data class CourseStructure(
val media: Media?,
val certificate: Certificate?,
val isSelfPaced: Boolean
) {
fun getVerticalBlocks(): List<Block> {
return blockData.filter { it.type == BlockType.VERTICAL }
}

fun getSequentialBlocks(): List<Block> {
return blockData.filter { it.type == BlockType.SEQUENTIAL }
}
}
)
11 changes: 11 additions & 0 deletions core/src/main/java/org/openedx/core/extension/ListExt.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.openedx.core.extension

import org.openedx.core.BlockType
import org.openedx.core.domain.model.Block

inline fun <T> List<T>.indexOfFirstFromIndex(startIndex: Int, predicate: (T) -> Boolean): Int {
var index = 0
for ((i, item) in this.withIndex()) {
Expand All @@ -23,3 +26,11 @@ fun <T> MutableList<T>.clearAndAddAll(collection: Collection<T>): MutableList<T>
this.addAll(collection)
return this
}

fun List<Block>.getVerticalBlocks(): List<Block> {
return this.filter { it.type == BlockType.VERTICAL }
}

fun List<Block>.getSequentialBlocks(): List<Block> {
return this.filter { it.type == BlockType.SEQUENTIAL }
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,25 @@ interface CourseRouter {
fun navigateToCourseSubsections(
fm: FragmentManager,
courseId: String,
blockId: String,
mode: CourseViewMode,
descendantId: String? = ""
subSectionId: String,
unitId: String = "",
componentId: String = "",
mode: CourseViewMode
)

fun navigateToCourseContainer(
fm: FragmentManager,
blockId: String,
courseId: String,
unitId: String,
componentId: String = "",
mode: CourseViewMode
)

fun replaceCourseContainer(
fm: FragmentManager,
blockId: String,
courseId: String,
unitId: String,
componentId: String = "",
mode: CourseViewMode
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,11 @@ class CourseDatesFragment : Fragment() {
viewModel.getSequentialBlock(verticalBlock.id)
?.let { sequentialBlock ->
router.navigateToCourseSubsections(
requireActivity().supportFragmentManager,
blockId = sequentialBlock.id,
fm = requireActivity().supportFragmentManager,
subSectionId = sequentialBlock.id,
courseId = viewModel.courseId,
mode = CourseViewMode.FULL,
descendantId = verticalBlock.id
unitId = verticalBlock.id,
mode = CourseViewMode.FULL
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import org.openedx.core.R
import org.openedx.core.SingleEventLiveData
import org.openedx.core.UIMessage
import org.openedx.core.domain.model.Block
import org.openedx.core.extension.getSequentialBlocks
import org.openedx.core.extension.getVerticalBlocks
import org.openedx.core.extension.isInternetError
import org.openedx.core.system.ResourceManager
import org.openedx.core.system.connection.NetworkConnection
Expand Down Expand Up @@ -73,7 +75,7 @@ class CourseDatesViewModel(
fun getVerticalBlock(blockId: String): Block? {
return try {
val courseStructure = interactor.getCourseStructureFromCache()
courseStructure.getVerticalBlocks().find { it.descendants.contains(blockId) }
courseStructure.blockData.getVerticalBlocks().find { it.descendants.contains(blockId) }
} catch (e: Exception) {
null
}
Expand All @@ -82,7 +84,8 @@ class CourseDatesViewModel(
fun getSequentialBlock(blockId: String): Block? {
return try {
val courseStructure = interactor.getCourseStructureFromCache()
courseStructure.getSequentialBlocks().find { it.descendants.contains(blockId) }
courseStructure.blockData.getSequentialBlocks()
.find { it.descendants.contains(blockId) }
} catch (e: Exception) {
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,25 @@ class CourseOutlineFragment : Fragment() {
onItemClick = { block ->
viewModel.sequentialClickedEvent(block.blockId, block.displayName)
router.navigateToCourseSubsections(
requireActivity().supportFragmentManager,
fm = requireActivity().supportFragmentManager,
courseId = viewModel.courseId,
blockId = block.id,
subSectionId = block.id,
mode = CourseViewMode.FULL
)
},
onResumeClick = { blockId ->
viewModel.resumeSectionBlock?.let { sequential ->
viewModel.resumeCourseTappedEvent(sequential.blockId)
router.navigateToCourseSubsections(
requireActivity().supportFragmentManager,
viewModel.courseId,
sequential.id,
CourseViewMode.FULL
)
onResumeClick = { componentId ->
viewModel.resumeSectionBlock?.let { subSection ->
viewModel.resumeCourseTappedEvent(subSection.id)
viewModel.resumeVerticalBlock?.let { unit ->
router.navigateToCourseSubsections(
requireActivity().supportFragmentManager,
courseId = viewModel.courseId,
subSectionId = subSection.id,
mode = CourseViewMode.FULL,
unitId = unit.id,
componentId = componentId
)
}
}
},
onBackClick = {
Expand Down Expand Up @@ -290,18 +294,18 @@ internal fun CourseOutlineScreen(
courseName = uiState.courseStructure.name
)
}
if (uiState.resumeBlock != null) {
if (uiState.resumeComponent != null) {
item {
Spacer(Modifier.height(28.dp))
Box(listPadding) {
if (windowSize.isTablet) {
ResumeCourseTablet(
block = uiState.resumeBlock,
block = uiState.resumeComponent,
onResumeClick = onResumeClick
)
} else {
ResumeCourse(
block = uiState.resumeBlock,
block = uiState.resumeComponent,
onResumeClick = onResumeClick
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sealed class CourseOutlineUIState {
data class CourseData(
val courseStructure: CourseStructure,
val downloadedState: Map<String, DownloadedState>,
val resumeBlock: Block?
val resumeComponent: Block?
) : CourseOutlineUIState()

object Loading : CourseOutlineUIState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import org.openedx.core.config.Config
import org.openedx.core.data.storage.CorePreferences
import org.openedx.core.domain.model.Block
import org.openedx.core.domain.model.CourseComponentStatus
import org.openedx.core.extension.getSequentialBlocks
import org.openedx.core.extension.getVerticalBlocks
import org.openedx.core.extension.isInternetError
import org.openedx.core.module.DownloadWorkerController
import org.openedx.core.module.db.DownloadDao
Expand Down Expand Up @@ -81,7 +83,7 @@ class CourseOutlineViewModel(
_uiState.value = CourseOutlineUIState.CourseData(
courseStructure = state.courseStructure,
downloadedState = it.toMap(),
resumeBlock = state.resumeBlock
resumeComponent = state.resumeComponent
)
}
}
Expand Down Expand Up @@ -137,7 +139,7 @@ class CourseOutlineViewModel(
_uiState.value = CourseOutlineUIState.CourseData(
courseStructure = courseStructure,
downloadedState = getDownloadModelsStatus(),
resumeBlock = getResumeBlock(blocks, courseStatus.lastVisitedBlockId)
resumeComponent = getResumeBlock(blocks, courseStatus.lastVisitedBlockId)
)
} catch (e: Exception) {
if (e.isInternetError()) {
Expand Down Expand Up @@ -176,13 +178,11 @@ class CourseOutlineViewModel(
continueBlockId: String
): Block? {
val resumeBlock = blocks.firstOrNull { it.id == continueBlockId }
resumeVerticalBlock = blocks.find {
it.descendants.contains(resumeBlock?.id) && it.type == BlockType.VERTICAL
}
resumeSectionBlock = blocks.find {
it.descendants.contains(resumeVerticalBlock?.id) && it.type == BlockType.SEQUENTIAL
}
return resumeVerticalBlock
resumeVerticalBlock =
blocks.getVerticalBlocks().find { it.descendants.contains(resumeBlock?.id) }
resumeSectionBlock =
blocks.getSequentialBlocks().find { it.descendants.contains(resumeVerticalBlock?.id) }
return resumeBlock
}

fun resumeCourseTappedEvent(blockId: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ class CourseSectionFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(viewModel)
val blockId = requireArguments().getString(ARG_BLOCK_ID, "")
val subSectionId = requireArguments().getString(ARG_SUBSECTION_ID, "")
viewModel.mode = requireArguments().serializable(ARG_MODE)!!
viewModel.getBlocks(blockId, viewModel.mode)
viewModel.getBlocks(subSectionId, viewModel.mode)
}

override fun onCreateView(
Expand All @@ -121,9 +121,9 @@ class CourseSectionFragment : Fragment() {
if (block.descendants.isNotEmpty()) {
viewModel.verticalClickedEvent(block.blockId, block.displayName)
router.navigateToCourseContainer(
requireActivity().supportFragmentManager,
block.id,
fm = requireActivity().supportFragmentManager,
courseId = viewModel.courseId,
unitId = block.id,
mode = viewModel.mode
)
}
Expand All @@ -146,15 +146,16 @@ class CourseSectionFragment : Fragment() {
)

LaunchedEffect(rememberSaveable { true }) {
val descendantId = requireArguments().getString(ARG_DESCENDANT_ID, "")
if (descendantId.isNotEmpty()) {
val unitId = requireArguments().getString(ARG_UNIT_ID, "")
if (unitId.isNotEmpty()) {
router.navigateToCourseContainer(
requireActivity().supportFragmentManager,
descendantId,
fm = requireActivity().supportFragmentManager,
courseId = viewModel.courseId,
unitId = unitId,
componentId = requireArguments().getString(ARG_COMPONENT_ID, ""),
mode = viewModel.mode
)
requireArguments().putString(ARG_DESCENDANT_ID, "")
requireArguments().putString(ARG_UNIT_ID, "")
}
}
}
Expand All @@ -163,20 +164,23 @@ class CourseSectionFragment : Fragment() {

companion object {
private const val ARG_COURSE_ID = "courseId"
private const val ARG_BLOCK_ID = "blockId"
private const val ARG_DESCENDANT_ID = "descendantId"
private const val ARG_SUBSECTION_ID = "subSectionId"
private const val ARG_UNIT_ID = "unitId"
private const val ARG_COMPONENT_ID = "componentId"
private const val ARG_MODE = "mode"
fun newInstance(
courseId: String,
blockId: String,
subSectionId: String,
unitId: String?,
componentId: String?,
mode: CourseViewMode,
descendantId: String?,
): CourseSectionFragment {
val fragment = CourseSectionFragment()
fragment.arguments = bundleOf(
ARG_COURSE_ID to courseId,
ARG_BLOCK_ID to blockId,
ARG_DESCENDANT_ID to descendantId,
ARG_SUBSECTION_ID to subSectionId,
ARG_UNIT_ID to unitId,
ARG_COMPONENT_ID to componentId,
ARG_MODE to mode
)
return fragment
Expand Down
Loading

0 comments on commit cd27754

Please sign in to comment.