diff --git a/course/src/main/java/org/openedx/course/presentation/container/CourseContainerFragment.kt b/course/src/main/java/org/openedx/course/presentation/container/CourseContainerFragment.kt index cae577969..1abd8cbb2 100644 --- a/course/src/main/java/org/openedx/course/presentation/container/CourseContainerFragment.kt +++ b/course/src/main/java/org/openedx/course/presentation/container/CourseContainerFragment.kt @@ -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 @@ -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 { @@ -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() } } @@ -390,7 +387,7 @@ fun CourseDashboard( isInternetConnectionShown = true }, onReloadClick = { - isInternetConnectionShown = true + isInternetConnectionShown = viewModel.hasInternetConnection onRefresh(pagerState.currentPage) } ) @@ -520,7 +517,7 @@ private fun DashboardPager( @Composable private fun CourseAccessErrorView( - viewModel: CourseContainerViewModel?, + viewModel: CourseContainerViewModel, accessError: CourseAccessError?, fragmentManager: FragmentManager, ) { @@ -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() ) ) } @@ -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 ?: "" ) } @@ -595,6 +592,7 @@ private fun CourseAccessErrorView( ) } SetupCourseAccessErrorButtons( + viewModel = viewModel, accessError = accessError, fragmentManager = fragmentManager, ) @@ -604,13 +602,13 @@ 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), @@ -618,6 +616,15 @@ private fun SetupCourseAccessErrorButtons( ) } + CourseAccessError.UNKNOWN -> { + if (viewModel.hasInternetConnection) { + OpenEdXButton( + text = stringResource(R.string.course_label_back), + onClick = { fragmentManager.popBackStack() }, + ) + } + } + else -> {} } } @@ -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!! - ) - } -} diff --git a/course/src/main/java/org/openedx/course/presentation/container/CourseContainerViewModel.kt b/course/src/main/java/org/openedx/course/presentation/container/CourseContainerViewModel.kt index 91abbb575..572a3aabf 100644 --- a/course/src/main/java/org/openedx/course/presentation/container/CourseContainerViewModel.kt +++ b/course/src/main/java/org/openedx/course/presentation/container/CourseContainerViewModel.kt @@ -202,6 +202,7 @@ class CourseContainerViewModel( delay(500L) courseNotifier.send(CourseOpenBlock(resumeBlockId)) } + _dataReady.value = true } } ?: run { _courseAccessStatus.value = CourseAccessError.UNKNOWN @@ -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)) diff --git a/course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt b/course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt index 003bbb4b3..73be2ca83 100644 --- a/course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt +++ b/course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt @@ -47,7 +47,6 @@ import org.openedx.course.presentation.CourseAnalyticsEvent import org.openedx.course.presentation.CourseRouter import org.openedx.course.utils.ImageProcessor import org.openedx.foundation.system.ResourceManager -import java.net.UnknownHostException import java.util.Date @OptIn(ExperimentalCoroutinesApi::class) @@ -216,49 +215,6 @@ class CourseContainerViewModelTest { Dispatchers.resetMain() } - @Test - fun `getCourseEnrollmentDetails internet connection exception`() = runTest { - val viewModel = CourseContainerViewModel( - "", - "", - "", - config, - interactor, - resourceManager, - courseNotifier, - networkConnection, - corePreferences, - analytics, - imageProcessor, - calendarSyncScheduler, - courseRouter, - ) - every { networkConnection.isOnline() } returns true - coEvery { interactor.getCourseStructure(any(), any()) } returns courseStructure - coEvery { interactor.getEnrollmentDetails(any()) } throws UnknownHostException() - every { - analytics.logScreenEvent( - CourseAnalyticsEvent.DASHBOARD.eventName, - any() - ) - } returns Unit - viewModel.fetchCourseDetails() - advanceUntilIdle() - - coVerify(exactly = 1) { interactor.getEnrollmentDetails(any()) } - verify(exactly = 1) { - analytics.logScreenEvent( - CourseAnalyticsEvent.DASHBOARD.eventName, - any() - ) - } - - val message = viewModel.errorMessage.value - assertEquals(noInternet, message) - assert(!viewModel.refreshing.value) - assert(viewModel.courseAccessStatus.value == null) - } - @Test fun `getCourseEnrollmentDetails unknown exception`() = runTest { val viewModel = CourseContainerViewModel( @@ -380,35 +336,6 @@ class CourseContainerViewModelTest { assert(viewModel.courseAccessStatus.value != null) } - @Test - fun `updateData no internet connection exception`() = runTest { - val viewModel = CourseContainerViewModel( - "", - "", - "", - config, - interactor, - resourceManager, - courseNotifier, - networkConnection, - corePreferences, - analytics, - imageProcessor, - calendarSyncScheduler, - courseRouter - ) - coEvery { interactor.getCourseStructure(any(), true) } throws UnknownHostException() - coEvery { courseNotifier.send(CourseStructureUpdated("")) } returns Unit - viewModel.updateData() - advanceUntilIdle() - - coVerify(exactly = 1) { interactor.getCourseStructure(any(), true) } - - val message = viewModel.errorMessage.value - assertEquals(noInternet, message) - assert(!viewModel.refreshing.value) - } - @Test fun `updateData unknown exception`() = runTest { val viewModel = CourseContainerViewModel(