Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into hamza/LEARNER-10192
Browse files Browse the repository at this point in the history
# Conflicts:
#	course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt
  • Loading branch information
dixidroid committed Nov 19, 2024
2 parents f2ea984 + b892560 commit 45cb062
Show file tree
Hide file tree
Showing 24 changed files with 135 additions and 163 deletions.
9 changes: 8 additions & 1 deletion app/src/main/java/org/openedx/app/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,14 @@ val appModule = module {
DownloadWorkerController(get(), get(), get())
}

single { AppData(versionName = BuildConfig.VERSION_NAME) }
single {
val resourceManager = get<ResourceManager>()
AppData(
appName = resourceManager.getString(R.string.app_name),
versionName = BuildConfig.VERSION_NAME,
applicationId = BuildConfig.APPLICATION_ID,
)
}
factory { (activity: AppCompatActivity) -> AppReviewManager(activity, get(), get()) }

single { TranscriptManager(get(), get()) }
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/org/openedx/app/di/ScreenModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ val screenModule = module {
get(),
get(),
get(),
get(),
)
}

Expand Down Expand Up @@ -229,6 +230,7 @@ val screenModule = module {
get(),
get(),
get(),
get(),
)
}
viewModel { (courseId: String) ->
Expand Down Expand Up @@ -460,7 +462,7 @@ val screenModule = module {
)
}

viewModel { ProgramViewModel(get(), get(), get(), get(), get(), get(), get()) }
viewModel { ProgramViewModel(get(), get(), get(), get(), get(), get(), get(), get()) }

viewModel { (courseId: String, courseTitle: String) ->
CourseOfflineViewModel(
Expand Down
29 changes: 17 additions & 12 deletions core/src/main/java/org/openedx/core/module/TranscriptManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import okhttp3.OkHttpClient
import org.openedx.core.module.download.AbstractDownloader
import org.openedx.core.utils.Directories
import org.openedx.core.utils.IOUtils
import org.openedx.core.utils.Logger
import org.openedx.core.utils.Sha1Util
import org.openedx.foundation.utils.FileUtil
import subtitleFile.FormatSRT
Expand All @@ -21,6 +22,8 @@ class TranscriptManager(
val fileUtil: FileUtil
) {

private val logger = Logger(TAG)

private val transcriptDownloader = object : AbstractDownloader() {
override val client: OkHttpClient
get() = OkHttpClient.Builder().build()
Expand Down Expand Up @@ -62,17 +65,18 @@ class TranscriptManager(
}

private suspend fun startTranscriptDownload(downloadLink: String) {
if (!has(downloadLink)) {
val file = File(getTranscriptDir(), Sha1Util.SHA1(downloadLink))
val result = transcriptDownloader.download(
downloadLink,
file.path
)
if (result == AbstractDownloader.DownloadResult.SUCCESS) {
getInputStream(downloadLink)?.let {
val transcriptTimedTextObject =
convertIntoTimedTextObject(it)
transcriptObject = transcriptTimedTextObject
if (has(downloadLink)) return
val file = File(getTranscriptDir(), Sha1Util.SHA1(downloadLink))
val result = transcriptDownloader.download(
downloadLink,
file.path
)
if (result == AbstractDownloader.DownloadResult.SUCCESS) {
getInputStream(downloadLink)?.let {
try {
transcriptObject = convertIntoTimedTextObject(it)
} catch (e: NullPointerException) {
logger.e(throwable = e, submitCrashReport = true)
}
}
}
Expand All @@ -86,7 +90,7 @@ class TranscriptManager(
try {
transcriptObject = convertIntoTimedTextObject(transcriptInputStream)
} catch (e: Exception) {
e.printStackTrace()
logger.e(throwable = e, submitCrashReport = true)
}
} else {
startTranscriptDownload(transcriptUrl)
Expand Down Expand Up @@ -127,6 +131,7 @@ class TranscriptManager(
}

companion object {
private const val TAG = "TranscriptManager"
private const val FILE_VALIDITY_DURATION_HOURS = 5L
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package org.openedx.core.presentation.global

data class AppData(
val appName: String,
val applicationId: String,
val versionName: String,
)
) {
val appUserAgent get() = "$appName/$applicationId/$versionName"
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/openedx/core/ui/ComposeCommon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1215,7 +1215,7 @@ fun FullScreenErrorView(
modifier = Modifier
.widthIn(Dp.Unspecified, 162.dp),
text = stringResource(id = errorType.actionResId),
textColor = MaterialTheme.appColors.primaryButtonText,
textColor = MaterialTheme.appColors.secondaryButtonText,
backgroundColor = MaterialTheme.appColors.secondaryButtonBackground,
onClick = onReloadClick,
)
Expand Down
16 changes: 15 additions & 1 deletion core/src/main/java/org/openedx/core/utils/Logger.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package org.openedx.core.utils

import android.util.Log
import com.google.firebase.crashlytics.FirebaseCrashlytics
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.openedx.core.BuildConfig
import org.openedx.core.config.Config

class Logger(private val tag: String) : KoinComponent {

private val config by inject<Config>()

class Logger(private val tag: String) {
fun d(message: () -> String) {
if (BuildConfig.DEBUG) Log.d(tag, message())
}
Expand All @@ -12,6 +19,13 @@ class Logger(private val tag: String) {
if (BuildConfig.DEBUG) Log.e(tag, message())
}

fun e(throwable: Throwable, submitCrashReport: Boolean = false) {
if (BuildConfig.DEBUG) throwable.printStackTrace()
if (submitCrashReport && config.getFirebaseConfig().enabled) {
FirebaseCrashlytics.getInstance().recordException(throwable)
}
}

fun i(message: () -> String) {
if (BuildConfig.DEBUG) Log.i(tag, message())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,10 @@ import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.lifecycleScope
import com.google.android.material.snackbar.Snackbar
Expand Down Expand Up @@ -164,10 +162,7 @@ class CourseContainerFragment : Fragment(R.layout.fragment_course_container) {
}
}
viewModel.errorMessage.observe(viewLifecycleOwner) {
snackBar = Snackbar.make(binding.root, it, Snackbar.LENGTH_INDEFINITE)
.setAction(org.openedx.core.R.string.core_error_try_again) {
viewModel.fetchCourseDetails()
}
snackBar = Snackbar.make(binding.root, it, Snackbar.LENGTH_SHORT)
snackBar?.show()
}
viewLifecycleOwner.lifecycleScope.launch {
Expand All @@ -180,6 +175,8 @@ class CourseContainerFragment : Fragment(R.layout.fragment_course_container) {
private fun onRefresh(currentPage: Int) {
if (viewModel.courseAccessStatus.value == CourseAccessError.NONE) {
viewModel.onRefresh(CourseContainerTab.entries[currentPage])
} else {
viewModel.fetchCourseDetails()
}
}

Expand Down Expand Up @@ -390,7 +387,7 @@ fun CourseDashboard(
isInternetConnectionShown = true
},
onReloadClick = {
isInternetConnectionShown = true
isInternetConnectionShown = viewModel.hasInternetConnection
onRefresh(pagerState.currentPage)
}
)
Expand Down Expand Up @@ -520,7 +517,7 @@ private fun DashboardPager(

@Composable
private fun CourseAccessErrorView(
viewModel: CourseContainerViewModel?,
viewModel: CourseContainerViewModel,
accessError: CourseAccessError?,
fragmentManager: FragmentManager,
) {
Expand All @@ -532,7 +529,7 @@ private fun CourseAccessErrorView(
R.string.course_error_expired_not_upgradeable_title,
TimeUtils.getCourseAccessFormattedDate(
LocalContext.current,
viewModel?.courseDetails?.courseAccessDetails?.auditAccessExpires ?: Date()
viewModel.courseDetails?.courseAccessDetails?.auditAccessExpires ?: Date()
)
)
}
Expand All @@ -541,7 +538,7 @@ private fun CourseAccessErrorView(
icon = painterResource(id = R.drawable.course_ic_calendar)
message = stringResource(
R.string.course_error_not_started_title,
viewModel?.courseDetails?.courseInfoOverview?.startDisplay ?: ""
viewModel.courseDetails?.courseInfoOverview?.startDisplay ?: ""
)
}

Expand Down Expand Up @@ -595,6 +592,7 @@ private fun CourseAccessErrorView(
)
}
SetupCourseAccessErrorButtons(
viewModel = viewModel,
accessError = accessError,
fragmentManager = fragmentManager,
)
Expand All @@ -604,20 +602,29 @@ private fun CourseAccessErrorView(

@Composable
private fun SetupCourseAccessErrorButtons(
viewModel: CourseContainerViewModel,
accessError: CourseAccessError?,
fragmentManager: FragmentManager,
) {
when (accessError) {
CourseAccessError.AUDIT_EXPIRED_NOT_UPGRADABLE,
CourseAccessError.NOT_YET_STARTED,
CourseAccessError.UNKNOWN,
-> {
OpenEdXButton(
text = stringResource(R.string.course_label_back),
onClick = { fragmentManager.popBackStack() },
)
}

CourseAccessError.UNKNOWN -> {
if (viewModel.hasInternetConnection) {
OpenEdXButton(
text = stringResource(R.string.course_label_back),
onClick = { fragmentManager.popBackStack() },
)
}
}

else -> {}
}
}
Expand All @@ -628,17 +635,3 @@ private fun scrollToDates(scope: CoroutineScope, pagerState: PagerState) {
pagerState.animateScrollToPage(CourseContainerTab.entries.indexOf(CourseContainerTab.DATES))
}
}

@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun CourseAccessErrorViewPreview() {
val context = LocalContext.current
OpenEdXTheme {
CourseAccessErrorView(
viewModel = null,
accessError = CourseAccessError.AUDIT_EXPIRED_NOT_UPGRADABLE,
fragmentManager = (context as? FragmentActivity)?.supportFragmentManager!!
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ class CourseContainerViewModel(
delay(500L)
courseNotifier.send(CourseOpenBlock(resumeBlockId))
}
_dataReady.value = true
}
} ?: run {
_courseAccessStatus.value = CourseAccessError.UNKNOWN
Expand Down Expand Up @@ -276,14 +277,9 @@ class CourseContainerViewModel(
viewModelScope.launch {
try {
interactor.getCourseStructure(courseId, isNeedRefresh = true)
} catch (e: Exception) {
if (e.isInternetError()) {
_errorMessage.value =
resourceManager.getString(CoreR.string.core_error_no_connection)
} else {
_errorMessage.value =
resourceManager.getString(CoreR.string.core_error_unknown_error)
}
} catch (ignore: Exception) {
_errorMessage.value =
resourceManager.getString(CoreR.string.core_error_unknown_error)
}
_refreshing.value = false
courseNotifier.send(CourseStructureUpdated(courseId))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -884,15 +884,15 @@ fun SubSectionUnitsTitle(
onUnitsClick: () -> Unit,
) {
val textStyle = MaterialTheme.appTypography.titleMedium
val hasUnits = unitsCount > 0
val hasMultipleUnits = unitsCount > 1
var rowModifier = Modifier
.fillMaxWidth()
.padding(
horizontal = 16.dp,
vertical = 8.dp
)
.displayCutoutForLandscape()
if (hasUnits) {
if (hasMultipleUnits) {
rowModifier = rowModifier.noRippleClickable { onUnitsClick() }
}

Expand All @@ -912,7 +912,7 @@ fun SubSectionUnitsTitle(
textAlign = TextAlign.Start
)

if (hasUnits) {
if (hasMultipleUnits) {
Icon(
modifier = Modifier.rotate(if (unitsListShowed) 180f else 0f),
painter = painterResource(id = R.drawable.ic_course_arrow_down),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,21 +281,24 @@ class CourseUnitContainerFragment : Fragment(R.layout.fragment_course_unit_conta

binding.subSectionUnitsList.setContent {
val unitBlocks by viewModel.subSectionUnitBlocks.collectAsState()
val selectedUnitIndex = unitBlocks.indexOfFirst { it.id == viewModel.unitId }
OpenEdXTheme {
SubSectionUnitsList(
unitBlocks = unitBlocks,
selectedUnitIndex = selectedUnitIndex
) { index, unit ->
if (index != selectedUnitIndex) {
router.navigateToCourseContainer(
fm = requireActivity().supportFragmentManager,
courseId = viewModel.courseId,
unitId = unit.id,
mode = requireArguments().serializable(ARG_MODE)!!
)
} else {
handleUnitsClick()
// If there is more than one unit in the section, show the list
if (unitBlocks.size > 1) {
val selectedUnitIndex = unitBlocks.indexOfFirst { it.id == viewModel.unitId }
OpenEdXTheme {
SubSectionUnitsList(
unitBlocks = unitBlocks,
selectedUnitIndex = selectedUnitIndex
) { index, unit ->
if (index != selectedUnitIndex) {
router.navigateToCourseContainer(
fm = requireActivity().supportFragmentManager,
courseId = viewModel.courseId,
unitId = unit.id,
mode = requireArguments().serializable(ARG_MODE)!!
)
} else {
handleUnitsClick()
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ class CourseUnitContainerViewModel(
}
_subSectionUnitBlocks.value =
getSubSectionUnitBlocks(blocks, getSubSectionId(unitId))

if (_descendantsBlocks.value.isEmpty()) {
_descendantsBlocks.value = listOf(block)
}
} else {
setNextVerticalIndex()
}
Expand Down
Loading

0 comments on commit 45cb062

Please sign in to comment.