diff --git a/core/src/main/java/org/openedx/core/BlockType.kt b/core/src/main/java/org/openedx/core/BlockType.kt index b680c68e2..db4256c06 100644 --- a/core/src/main/java/org/openedx/core/BlockType.kt +++ b/core/src/main/java/org/openedx/core/BlockType.kt @@ -16,6 +16,9 @@ enum class BlockType { HTML { override fun isContainer() = false }, + LIBRARY_CONTENT { + override fun isContainer() = false + }, LTI_CONSUMER { override fun isContainer() = false }, diff --git a/core/src/main/java/org/openedx/core/domain/model/Block.kt b/core/src/main/java/org/openedx/core/domain/model/Block.kt index 64795a17c..daa9dfc07 100644 --- a/core/src/main/java/org/openedx/core/domain/model/Block.kt +++ b/core/src/main/java/org/openedx/core/domain/model/Block.kt @@ -91,6 +91,7 @@ data class Block( val isWordCloudBlock get() = type == BlockType.WORD_CLOUD val isLTIConsumerBlock get() = type == BlockType.LTI_CONSUMER val isSurveyBlock get() = type == BlockType.SURVEY + val isLibraryContentBlock get() = type == BlockType.LIBRARY_CONTENT } @Parcelize diff --git a/course/src/main/java/org/openedx/course/presentation/unit/container/CourseUnitContainerAdapter.kt b/course/src/main/java/org/openedx/course/presentation/unit/container/CourseUnitContainerAdapter.kt index 8048d468f..c05a2f232 100644 --- a/course/src/main/java/org/openedx/course/presentation/unit/container/CourseUnitContainerAdapter.kt +++ b/course/src/main/java/org/openedx/course/presentation/unit/container/CourseUnitContainerAdapter.kt @@ -107,7 +107,8 @@ class CourseUnitContainerAdapter( block.isDragAndDropBlock || block.isWordCloudBlock || block.isLTIConsumerBlock || - block.isSurveyBlock + block.isSurveyBlock || + block.isLibraryContentBlock } private fun isBlockGatedWithPrerequisite(block: Block): Boolean { diff --git a/course/src/main/java/org/openedx/course/presentation/unit/container/CourseUnitContainerViewModel.kt b/course/src/main/java/org/openedx/course/presentation/unit/container/CourseUnitContainerViewModel.kt index 72181b4fe..50fd4b4ef 100644 --- a/course/src/main/java/org/openedx/course/presentation/unit/container/CourseUnitContainerViewModel.kt +++ b/course/src/main/java/org/openedx/course/presentation/unit/container/CourseUnitContainerViewModel.kt @@ -276,10 +276,25 @@ class CourseUnitContainerViewModel( } if (block.descendants.isNotEmpty() || block.isGated()) { - _descendantsBlocks.value = - block.descendants.mapNotNull { descendant -> - blocks.firstOrNull { descendant == it.id } - } + val rawDescendants = block.descendants.mapNotNull { descendant -> + blocks.firstOrNull { descendant == it.id } + } + + // The OpenEdX API flattens library_content's children into the parent + // vertical's descendants list but returns the library_content block itself + // with an empty descendants field. Since the library_content WebView + // already renders all its problems, remove the duplicate problem pages. + val hasLibraryContent = rawDescendants.any { it.isLibraryContentBlock } + _descendantsBlocks.value = if (hasLibraryContent) { + // Show each library problem as its own page; drop the wrapper block + // whose WebView would show all questions on a single page. + rawDescendants.filter { !it.isLibraryContentBlock } + } else { + // Generic case: filter blocks that are declared children of another + // block in the same list (handles other nested xBlock containers). + val childIdsOfDescendants = rawDescendants.flatMap { it.descendants }.toSet() + rawDescendants.filter { it.id !in childIdsOfDescendants } + } _subSectionUnitBlocks.value = getSubSectionUnitBlocks(blocks, getSubSectionId(unitId)) @@ -295,7 +310,7 @@ class CourseUnitContainerViewModel( setNextVerticalIndex() } if (currentVerticalIndex != -1) { - _verticalBlockCounts.value = blocks[currentVerticalIndex].descendants.size + _verticalBlockCounts.value = _descendantsBlocks.value.size } if (componentId.isNotEmpty()) { currentIndex = _descendantsBlocks.value.indexOfFirst { it.id == componentId }