diff --git a/app/src/main/java/org/openedx/app/MainFragment.kt b/app/src/main/java/org/openedx/app/MainFragment.kt index 3ab735d27..6eca5da40 100644 --- a/app/src/main/java/org/openedx/app/MainFragment.kt +++ b/app/src/main/java/org/openedx/app/MainFragment.kt @@ -50,11 +50,6 @@ class MainFragment : Fragment(R.layout.fragment_main) { binding.viewPager.setCurrentItem(0, false) } - R.id.fragmentDiscover -> { - viewModel.logDiscoveryTabClickedEvent() - binding.viewPager.setCurrentItem(1, false) - } - R.id.fragmentProfile -> { viewModel.logProfileTabClickedEvent() binding.viewPager.setCurrentItem(2, false) @@ -68,9 +63,9 @@ class MainFragment : Fragment(R.layout.fragment_main) { } viewLifecycleOwner.lifecycleScope.launch { - viewModel.navigateToDiscovery.collect { shouldNavigateToDiscovery -> - if (shouldNavigateToDiscovery) { - binding.bottomNavView.selectedItemId = R.id.fragmentDiscover + viewModel.navigateToHome.collect { shouldNavigateToHome -> + if (shouldNavigateToHome) { + binding.bottomNavView.selectedItemId = R.id.fragmentLearn } } } @@ -92,13 +87,6 @@ class MainFragment : Fragment(R.layout.fragment_main) { when (requireArguments().getString(ARG_OPEN_TAB, "")) { HomeTab.LEARN.name, - HomeTab.PROGRAMS.name -> { - binding.bottomNavView.selectedItemId = R.id.fragmentLearn - } - - HomeTab.DISCOVER.name -> { - binding.bottomNavView.selectedItemId = R.id.fragmentDiscover - } HomeTab.PROFILE.name -> { binding.bottomNavView.selectedItemId = R.id.fragmentProfile @@ -114,14 +102,9 @@ class MainFragment : Fragment(R.layout.fragment_main) { binding.viewPager.offscreenPageLimit = 4 val openTab = requireArguments().getString(ARG_OPEN_TAB, HomeTab.LEARN.name) - val learnTab = if (openTab == HomeTab.PROGRAMS.name) { - LearnTab.PROGRAMS - } else { - LearnTab.COURSES - } + val learnTab = LearnTab.COURSES adapter = NavigationFragmentAdapter(this).apply { addFragment(LearnFragment.newInstance(openTab = learnTab.name)) - addFragment(viewModel.getDiscoveryFragment) addFragment(ProfileFragment()) } binding.viewPager.adapter = adapter diff --git a/app/src/main/java/org/openedx/app/MainViewModel.kt b/app/src/main/java/org/openedx/app/MainViewModel.kt index 69c809b5c..8708b6341 100644 --- a/app/src/main/java/org/openedx/app/MainViewModel.kt +++ b/app/src/main/java/org/openedx/app/MainViewModel.kt @@ -26,9 +26,9 @@ class MainViewModel( val isBottomBarEnabled: LiveData get() = _isBottomBarEnabled - private val _navigateToDiscovery = MutableSharedFlow() - val navigateToDiscovery: SharedFlow - get() = _navigateToDiscovery.asSharedFlow() + private val _navigateToHome = MutableSharedFlow() + val navigateToHome: SharedFlow + get() = _navigateToHome.asSharedFlow() val isDiscoveryTypeWebView get() = config.getDiscoveryConfig().isViewTypeWebView() val getDiscoveryFragment get() = DiscoveryNavigator(isDiscoveryTypeWebView).getDiscoveryFragment() @@ -38,7 +38,7 @@ class MainViewModel( notifier.notifier .onEach { if (it is NavigationToDiscovery) { - _navigateToDiscovery.emit(true) + _navigateToHome.emit(true) } } .distinctUntilChanged() diff --git a/app/src/main/java/org/openedx/app/di/ScreenModule.kt b/app/src/main/java/org/openedx/app/di/ScreenModule.kt index 6b7692f99..abb238485 100644 --- a/app/src/main/java/org/openedx/app/di/ScreenModule.kt +++ b/app/src/main/java/org/openedx/app/di/ScreenModule.kt @@ -293,6 +293,7 @@ val screenModule = module { get(), get(), get(), + get(), ) } viewModel { (courseId: String, unitId: String) -> diff --git a/app/src/main/res/menu/bottom_view_menu.xml b/app/src/main/res/menu/bottom_view_menu.xml index f97e849f7..730553f88 100644 --- a/app/src/main/res/menu/bottom_view_menu.xml +++ b/app/src/main/res/menu/bottom_view_menu.xml @@ -7,12 +7,6 @@ android:icon="@drawable/app_ic_rows" android:title="@string/app_navigation_learn" /> - - Do not sell my personal information View FAQ Terms of Use + Contact Support Profile Cancel Search diff --git a/course/src/main/java/org/openedx/course/data/repository/CourseRepository.kt b/course/src/main/java/org/openedx/course/data/repository/CourseRepository.kt index d9034e4ef..0609ad583 100644 --- a/course/src/main/java/org/openedx/course/data/repository/CourseRepository.kt +++ b/course/src/main/java/org/openedx/course/data/repository/CourseRepository.kt @@ -139,4 +139,6 @@ class CourseRepository( downloadDao.removeOfflineXBlockProgress(listOf(blockId)) } } + + suspend fun getSequence(sequenceId: String) = api.getSequence(sequenceId).mapToDomain() } diff --git a/course/src/main/java/org/openedx/course/domain/interactor/CourseInteractor.kt b/course/src/main/java/org/openedx/course/domain/interactor/CourseInteractor.kt index fdbcdd204..f158079d2 100644 --- a/course/src/main/java/org/openedx/course/domain/interactor/CourseInteractor.kt +++ b/course/src/main/java/org/openedx/course/domain/interactor/CourseInteractor.kt @@ -82,6 +82,8 @@ class CourseInteractor( suspend fun removeDownloadModel(id: String) = repository.removeDownloadModel(id) + suspend fun getSubsection(subsectionId: String) = repository.getSequence(subsectionId) + fun getDownloadModels() = repository.getDownloadModels() suspend fun getAllDownloadModels() = repository.getAllDownloadModels() diff --git a/course/src/main/java/org/openedx/course/presentation/CourseAnalytics.kt b/course/src/main/java/org/openedx/course/presentation/CourseAnalytics.kt index 0dbe660e5..a5b01a097 100644 --- a/course/src/main/java/org/openedx/course/presentation/CourseAnalytics.kt +++ b/course/src/main/java/org/openedx/course/presentation/CourseAnalytics.kt @@ -78,6 +78,10 @@ enum class CourseAnalyticsEvent(val eventName: String, val biValue: String) { "Course:Unit Detail", "edx.bi.app.course.unit_detail" ), + PREREQUISITE( + "Course:Prerequisite", + "edx.bi.app.course.prerequisite" + ), VIEW_CERTIFICATE( "Course:View Certificate Clicked", "edx.bi.app.course.view_certificate.clicked" diff --git a/course/src/main/java/org/openedx/course/presentation/offline/CourseOfflineViewModel.kt b/course/src/main/java/org/openedx/course/presentation/offline/CourseOfflineViewModel.kt index 19d67f79b..5f6165566 100644 --- a/course/src/main/java/org/openedx/course/presentation/offline/CourseOfflineViewModel.kt +++ b/course/src/main/java/org/openedx/course/presentation/offline/CourseOfflineViewModel.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.launch import org.openedx.core.BlockType import org.openedx.core.data.storage.CorePreferences import org.openedx.core.domain.model.Block +import org.openedx.core.extension.safeDivBy import org.openedx.core.module.DownloadWorkerController import org.openedx.core.module.db.DownloadDao import org.openedx.core.module.db.DownloadModel @@ -187,19 +188,24 @@ class CourseOfflineViewModel( completedDownloads: List, downloadedBlocks: List ) { - val downloadedSize = getFilesSize(downloadedBlocks) + val downloadedSize = getFilesSize(downloadedBlocks).toFloat() val realDownloadedSize = completedDownloads.sumOf { it.size } val largestDownloads = completedDownloads .sortedByDescending { it.size } .take(n = 5) - + val progressBarValue = downloadedSize.safeDivBy(totalDownloadableSize.toFloat()) + val readyToDownloadSize = if (progressBarValue >= 1) { + 0 + } else { + totalDownloadableSize - realDownloadedSize + } _uiState.update { it.copy( isHaveDownloadableBlocks = true, largestDownloads = largestDownloads, - readyToDownloadSize = (totalDownloadableSize - downloadedSize).toFileSize(1, false), + readyToDownloadSize = readyToDownloadSize.toFileSize(1, false), downloadedSize = realDownloadedSize.toFileSize(1, false), - progressBarValue = downloadedSize.toFloat() / totalDownloadableSize.toFloat() + progressBarValue = progressBarValue ) } } diff --git a/course/src/main/java/org/openedx/course/presentation/section/CourseSectionFragment.kt b/course/src/main/java/org/openedx/course/presentation/section/CourseSectionFragment.kt index 75a100ab8..7b3b339ab 100644 --- a/course/src/main/java/org/openedx/course/presentation/section/CourseSectionFragment.kt +++ b/course/src/main/java/org/openedx/course/presentation/section/CourseSectionFragment.kt @@ -4,6 +4,7 @@ import android.content.res.Configuration import android.os.Bundle import android.view.LayoutInflater import android.view.ViewGroup +import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -17,6 +18,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.lazy.LazyColumn @@ -61,6 +63,7 @@ import org.openedx.core.domain.model.BlockCounts import org.openedx.core.presentation.course.CourseViewMode import org.openedx.core.ui.BackBtn import org.openedx.core.ui.HandleUIMessage +import org.openedx.core.ui.OpenEdXButton import org.openedx.core.ui.displayCutoutForLandscape import org.openedx.core.ui.statusBarsInset import org.openedx.core.ui.theme.OpenEdXTheme @@ -124,6 +127,15 @@ class CourseSectionFragment : Fragment() { ) } }, + onGoToPrerequisiteClick = { subSectionId -> + viewModel.goToPrerequisiteSectionClickedEvent(subSectionId) + router.navigateToCourseSubsections( + fm = requireActivity().supportFragmentManager, + courseId = viewModel.courseId, + subSectionId = subSectionId, + mode = CourseViewMode.FULL + ) + } ) LaunchedEffect(rememberSaveable { true }) { @@ -176,6 +188,7 @@ private fun CourseSectionScreen( uiMessage: UIMessage?, onBackClick: () -> Unit, onItemClick: (Block) -> Unit, + onGoToPrerequisiteClick: (String) -> Unit ) { val scaffoldState = rememberScaffoldState() val title = when (uiState) { @@ -256,6 +269,41 @@ private fun CourseSectionScreen( } } + is CourseSectionUIState.Gated -> { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + painter = painterResource(id = R.drawable.ic_course_gated), + contentDescription = "gated", + modifier = Modifier.size(48.dp) + ) + Spacer(modifier = Modifier.height(16.dp)) + Text( + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + text = stringResource( + id = R.string.course_gated_subsection, + uiState.prereqSubsectionName ?: "" + ), + textAlign = TextAlign.Center, + style = MaterialTheme.appTypography.titleMedium, + color = MaterialTheme.appColors.textPrimary, + ) + Spacer(modifier = Modifier.height(16.dp)) + OpenEdXButton( + text = stringResource(id = R.string.course_go_to_prerequisite_section), + onClick = { + onGoToPrerequisiteClick(uiState.prereqId ?: "") + }, + modifier = Modifier.padding(top = 16.dp) + ) + } + } + is CourseSectionUIState.Blocks -> { Column(Modifier.fillMaxSize()) { LazyColumn( @@ -361,6 +409,7 @@ private fun CourseSectionScreenPreview() { uiMessage = null, onBackClick = {}, onItemClick = {}, + onGoToPrerequisiteClick = {} ) } } @@ -385,6 +434,29 @@ private fun CourseSectionScreenTabletPreview() { uiMessage = null, onBackClick = {}, onItemClick = {}, + onGoToPrerequisiteClick = {} + ) + } +} + +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, device = Devices.NEXUS_9) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, device = Devices.NEXUS_9) +@Composable +private fun CourseSectionScreenGatedPreview() { + OpenEdXTheme { + CourseSectionScreen( + windowSize = WindowSize(WindowType.Medium, WindowType.Medium), + uiState = CourseSectionUIState.Gated( + "Gated Subsection", + "Prerequisite Subsection", + "Prerequisite Id" + ), + uiMessage = null, + onBackClick = {}, + onItemClick = {}, + onGoToPrerequisiteClick = {} ) } } diff --git a/course/src/main/java/org/openedx/course/presentation/section/CourseSectionUIState.kt b/course/src/main/java/org/openedx/course/presentation/section/CourseSectionUIState.kt index 166da30c2..484e144c9 100644 --- a/course/src/main/java/org/openedx/course/presentation/section/CourseSectionUIState.kt +++ b/course/src/main/java/org/openedx/course/presentation/section/CourseSectionUIState.kt @@ -8,5 +8,10 @@ sealed class CourseSectionUIState { val sectionName: String, val courseName: String ) : CourseSectionUIState() + data class Gated( + val gatedSubsectionName: String?, + val prereqSubsectionName: String?, + val prereqId: String?, + ) : CourseSectionUIState() data object Loading : CourseSectionUIState() } diff --git a/course/src/main/java/org/openedx/course/presentation/section/CourseSectionViewModel.kt b/course/src/main/java/org/openedx/course/presentation/section/CourseSectionViewModel.kt index 2ebe2c9b3..ebe8dc078 100644 --- a/course/src/main/java/org/openedx/course/presentation/section/CourseSectionViewModel.kt +++ b/course/src/main/java/org/openedx/course/presentation/section/CourseSectionViewModel.kt @@ -9,6 +9,7 @@ import org.openedx.core.BlockType import org.openedx.core.R import org.openedx.core.domain.model.Block import org.openedx.core.presentation.course.CourseViewMode +import org.openedx.core.system.connection.NetworkConnection import org.openedx.core.system.notifier.CourseNotifier import org.openedx.core.system.notifier.CourseSectionChanged import org.openedx.course.domain.interactor.CourseInteractor @@ -25,6 +26,7 @@ class CourseSectionViewModel( val courseId: String, private val interactor: CourseInteractor, private val resourceManager: ResourceManager, + private val networkConnection: NetworkConnection, private val notifier: CourseNotifier, private val analytics: CourseAnalytics, ) : BaseViewModel() { @@ -54,6 +56,17 @@ class CourseSectionViewModel( _uiState.value = CourseSectionUIState.Loading viewModelScope.launch { try { + if (networkConnection.isOnline()) { + val sectionData = interactor.getSubsection(blockId) + if (sectionData.gatedContent.gated) { + _uiState.value = CourseSectionUIState.Gated( + prereqId = sectionData.gatedContent.prereqId, + prereqSubsectionName = sectionData.gatedContent.prereqSubsectionName, + gatedSubsectionName = sectionData.gatedContent.gatedSubsectionName, + ) + return@launch + } + } val courseStructure = when (mode) { CourseViewMode.FULL -> interactor.getCourseStructure(courseId) CourseViewMode.VIDEOS -> interactor.getCourseStructureForVideos(courseId) @@ -118,4 +131,19 @@ class CourseSectionViewModel( ) } } + + fun goToPrerequisiteSectionClickedEvent(subSectionId: String) { + val currentState = uiState.value + if (currentState is CourseSectionUIState.Gated) { + analytics.logEvent( + event = CourseAnalyticsEvent.PREREQUISITE.eventName, + params = buildMap { + put(CourseAnalyticsKey.NAME.key, CourseAnalyticsEvent.PREREQUISITE.biValue) + put(CourseAnalyticsKey.COURSE_ID.key, courseId) + put(CourseAnalyticsKey.BLOCK_ID.key, subSectionId) + put(CourseAnalyticsKey.CATEGORY.key, CourseAnalyticsKey.NAVIGATION.key) + } + ) + } + } } diff --git a/course/src/main/java/org/openedx/course/presentation/ui/CourseUI.kt b/course/src/main/java/org/openedx/course/presentation/ui/CourseUI.kt index 2598ad8ac..f0a87d8f4 100644 --- a/course/src/main/java/org/openedx/course/presentation/ui/CourseUI.kt +++ b/course/src/main/java/org/openedx/course/presentation/ui/CourseUI.kt @@ -84,6 +84,7 @@ import org.openedx.core.domain.model.AssignmentProgress import org.openedx.core.domain.model.Block import org.openedx.core.domain.model.BlockCounts import org.openedx.core.domain.model.CourseDatesBannerInfo +import org.openedx.core.extension.safeDivBy import org.openedx.core.module.db.DownloadModel import org.openedx.core.module.db.DownloadedState import org.openedx.core.module.db.FileType @@ -260,11 +261,7 @@ fun OfflineQueueCard( maxLines = 1 ) - val progress = if (progressSize == 0L) { - 0f - } else { - progressValue.toFloat() / progressSize - } + val progress = progressValue.toFloat().safeDivBy(progressSize.toFloat()) LinearProgressIndicator( modifier = Modifier .fillMaxWidth() diff --git a/course/src/main/res/values/strings.xml b/course/src/main/res/values/strings.xml index 59c536295..5779f7eaa 100644 --- a/course/src/main/res/values/strings.xml +++ b/course/src/main/res/values/strings.xml @@ -34,6 +34,8 @@ Resume To proceed with \"%s\" press \"Next section\". Some content in this part of the course is locked for upgraded users only. + Content locked. You must complete the prerequisite: \“%s\” to access this content. + Go To Prerequisite Section You cannot change the download video quality when all videos are downloading Dates Shifted diff --git a/course/src/test/java/org/openedx/course/presentation/section/CourseSectionViewModelTest.kt b/course/src/test/java/org/openedx/course/presentation/section/CourseSectionViewModelTest.kt index 02eda9622..f8e92cd4d 100644 --- a/course/src/test/java/org/openedx/course/presentation/section/CourseSectionViewModelTest.kt +++ b/course/src/test/java/org/openedx/course/presentation/section/CourseSectionViewModelTest.kt @@ -31,6 +31,8 @@ import org.openedx.core.domain.model.Block import org.openedx.core.domain.model.BlockCounts import org.openedx.core.domain.model.CourseStructure import org.openedx.core.domain.model.CoursewareAccess +import org.openedx.core.domain.model.GatedContent +import org.openedx.core.domain.model.Subsection import org.openedx.core.module.DownloadWorkerController import org.openedx.core.module.db.DownloadDao import org.openedx.core.module.db.DownloadModel @@ -161,6 +163,36 @@ class CourseSectionViewModelTest { progress = null ) + private val subsection = Subsection( + elementId = "id", + itemId = "id", + bannerText = "bannerText", + gatedContent = GatedContent( + prereqId = null, + prereqUrl = null, + prereqSubsectionName = null, + gated = false, + gatedSubsectionName = null + ), + subsectionName = "subsectionName", + displayName = "displayName" + ) + + private val gatedSubsection = Subsection( + elementId = "id", + itemId = "id", + bannerText = "bannerText", + gatedContent = GatedContent( + prereqId = "prereqId", + prereqUrl = "prereqUrl", + prereqSubsectionName = "prereqSubsectionName", + gated = true, + gatedSubsectionName = "gatedSubsectionName" + ), + subsectionName = "subsectionName", + displayName = "displayName" + ) + private val downloadModel = DownloadModel( "id", "title", @@ -181,6 +213,8 @@ class CourseSectionViewModelTest { every { resourceManager.getString(org.openedx.course.R.string.course_can_download_only_with_wifi) } returns cantDownload + every { networkConnection.isOnline() } returns true + coEvery { interactor.getSubsection("id") } returns subsection } @After @@ -195,17 +229,20 @@ class CourseSectionViewModelTest { "", interactor, resourceManager, + networkConnection, notifier, analytics, ) + coEvery { interactor.getSubsection("") } throws UnknownHostException() coEvery { interactor.getCourseStructure(any()) } throws UnknownHostException() coEvery { interactor.getCourseStructureForVideos(any()) } throws UnknownHostException() viewModel.getBlocks("", CourseViewMode.FULL) advanceUntilIdle() - coVerify(exactly = 1) { interactor.getCourseStructure(any()) } + coVerify(exactly = 1) { interactor.getSubsection("") } + coVerify(exactly = 0) { interactor.getCourseStructure(any()) } coVerify(exactly = 0) { interactor.getCourseStructureForVideos(any()) } val message = viewModel.uiMessage.value as? UIMessage.SnackBarMessage @@ -220,17 +257,20 @@ class CourseSectionViewModelTest { "", interactor, resourceManager, + networkConnection, notifier, analytics, ) + coEvery { interactor.getSubsection("id2") } throws Exception() coEvery { interactor.getCourseStructure(any()) } throws Exception() coEvery { interactor.getCourseStructureForVideos(any()) } throws Exception() viewModel.getBlocks("id2", CourseViewMode.FULL) advanceUntilIdle() - coVerify(exactly = 1) { interactor.getCourseStructure(any()) } + coVerify(exactly = 1) { interactor.getSubsection("id2") } + coVerify(exactly = 0) { interactor.getCourseStructure(any()) } coVerify(exactly = 0) { interactor.getCourseStructureForVideos(any()) } val message = viewModel.uiMessage.value as? UIMessage.SnackBarMessage @@ -247,6 +287,7 @@ class CourseSectionViewModelTest { "", interactor, resourceManager, + networkConnection, notifier, analytics, ) @@ -276,6 +317,7 @@ class CourseSectionViewModelTest { "", interactor, resourceManager, + networkConnection, notifier, analytics, ) @@ -298,6 +340,7 @@ class CourseSectionViewModelTest { "", interactor, resourceManager, + networkConnection, notifier, analytics, ) @@ -323,6 +366,7 @@ class CourseSectionViewModelTest { "", interactor, resourceManager, + networkConnection, notifier, analytics, ) @@ -341,4 +385,26 @@ class CourseSectionViewModelTest { assert(viewModel.uiState.value is CourseSectionUIState.Blocks) } + + @Test + fun `subsection is gated`() = runTest { + coEvery { downloadDao.getAllDataFlow() } returns flow { + emit(listOf(DownloadModelEntity.createFrom(downloadModel))) + } + val viewModel = CourseSectionViewModel( + "", + interactor, + resourceManager, + networkConnection, + notifier, + analytics, + ) + + coEvery { interactor.getSubsection("id") } returns gatedSubsection + + viewModel.getBlocks("id", CourseViewMode.FULL) + advanceUntilIdle() + + assert(viewModel.uiState.value is CourseSectionUIState.Gated) + } } diff --git a/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesView.kt b/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesView.kt index 9d26e39df..2ac69f18a 100644 --- a/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesView.kt +++ b/dashboard/src/main/java/org/openedx/courses/presentation/AllEnrolledCoursesView.kt @@ -431,16 +431,11 @@ fun CourseItem( .fillMaxWidth() .height(90.dp) ) - val progress: Float = try { - course.progress.assignmentsCompleted.toFloat() / course.progress.totalAssignmentsCount.toFloat() - } catch (_: ArithmeticException) { - 0f - } LinearProgressIndicator( modifier = Modifier .fillMaxWidth() .height(8.dp), - progress = progress, + progress = course.progress.value, color = MaterialTheme.appColors.primary, backgroundColor = MaterialTheme.appColors.divider ) diff --git a/dashboard/src/main/java/org/openedx/courses/presentation/DashboardGalleryView.kt b/dashboard/src/main/java/org/openedx/courses/presentation/DashboardGalleryView.kt index 2c44c2c61..dd50d1f3b 100644 --- a/dashboard/src/main/java/org/openedx/courses/presentation/DashboardGalleryView.kt +++ b/dashboard/src/main/java/org/openedx/courses/presentation/DashboardGalleryView.kt @@ -557,17 +557,12 @@ private fun PrimaryCourseCard( .fillMaxWidth() .height(140.dp) ) - val progress: Float = try { - primaryCourse.progress.assignmentsCompleted.toFloat() / - primaryCourse.progress.totalAssignmentsCount.toFloat() - } catch (_: ArithmeticException) { - 0f - } + LinearProgressIndicator( modifier = Modifier .fillMaxWidth() .height(8.dp), - progress = progress, + progress = primaryCourse.progress.value, color = MaterialTheme.appColors.primary, backgroundColor = MaterialTheme.appColors.divider ) diff --git a/default_config/dev/config.yaml b/default_config/dev/config.yaml index 4d1d694ec..33edbd75b 100644 --- a/default_config/dev/config.yaml +++ b/default_config/dev/config.yaml @@ -11,7 +11,8 @@ AGREEMENT_URLS: PRIVACY_POLICY_URL: '' COOKIE_POLICY_URL: '' DATA_SELL_CONSENT_URL: '' - TOS_URL: '' + CONTACT_SUPPORT_URL: 'https://eshemoeasu.my.site.com/help/s/' + TOS_URL: 'https://courses.ethernet.edu.et/terms' EULA_URL: '' SUPPORTED_LANGUAGES: [ ] #en is default language diff --git a/profile/src/main/java/org/openedx/profile/presentation/profile/compose/ProfileView.kt b/profile/src/main/java/org/openedx/profile/presentation/profile/compose/ProfileView.kt index e897b37c6..331e7c3d1 100644 --- a/profile/src/main/java/org/openedx/profile/presentation/profile/compose/ProfileView.kt +++ b/profile/src/main/java/org/openedx/profile/presentation/profile/compose/ProfileView.kt @@ -38,7 +38,6 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import org.openedx.core.R import org.openedx.core.ui.HandleUIMessage -import org.openedx.core.ui.OpenEdXOutlinedButton import org.openedx.core.ui.Toolbar import org.openedx.core.ui.displayCutoutForLandscape import org.openedx.core.ui.statusBarsInset @@ -143,17 +142,6 @@ internal fun ProfileView( subtitle = "@${uiState.account.username}" ) ProfileInfoSection(uiState.account) - OpenEdXOutlinedButton( - modifier = Modifier - .fillMaxWidth(), - text = stringResource(id = org.openedx.profile.R.string.profile_edit_profile), - onClick = { - onAction(ProfileViewAction.EditAccountClick) - }, - borderColor = MaterialTheme.appColors.primaryButtonBackground, - textColor = MaterialTheme.appColors.textAccent - ) - Spacer(modifier = Modifier.height(12.dp)) } } } diff --git a/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsFragment.kt b/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsFragment.kt index 217a35258..75763bbc4 100644 --- a/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsFragment.kt +++ b/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsFragment.kt @@ -68,7 +68,9 @@ class SettingsFragment : Fragment() { SettingsScreenAction.FaqClick -> viewModel.faqClicked() SettingsScreenAction.SupportClick -> { - viewModel.emailSupportClicked(requireContext()) + viewModel.emailSupportClicked( + requireActivity().supportFragmentManager + ) } SettingsScreenAction.TermsClick -> { diff --git a/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsScreenUI.kt b/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsScreenUI.kt index 68c773745..4b50b8f5d 100644 --- a/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsScreenUI.kt +++ b/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsScreenUI.kt @@ -167,12 +167,6 @@ internal fun SettingsScreen( .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally ) { - Spacer(Modifier.height(30.dp)) - - ManageAccountSection(onManageAccountClick = { - onAction(SettingsScreenAction.ManageAccountClick) - }) - Spacer(modifier = Modifier.height(24.dp)) SettingsSection( @@ -243,24 +237,6 @@ private fun SettingsSection( } } -@Composable -private fun ManageAccountSection(onManageAccountClick: () -> Unit) { - Column { - Card( - shape = MaterialTheme.appShapes.cardShape, - elevation = 0.dp, - backgroundColor = MaterialTheme.appColors.cardViewBackground - ) { - Column(Modifier.fillMaxWidth()) { - SettingsItem( - text = stringResource(id = R.string.core_manage_account), - onClick = onManageAccountClick - ) - } - } - } -} - @Composable private fun SupportInfoSection( uiState: SettingsUIState.Data, @@ -282,7 +258,7 @@ private fun SupportInfoSection( backgroundColor = MaterialTheme.appColors.cardViewBackground ) { Column(Modifier.fillMaxWidth()) { - if (uiState.configuration.supportEmail.isNotBlank()) { + if (uiState.configuration.agreementUrls.contactSupportUrl.isNotBlank()) { SettingsItem(text = stringResource(id = profileR.string.profile_contact_support)) { onAction(SettingsScreenAction.SupportClick) } diff --git a/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsViewModel.kt b/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsViewModel.kt index 59548d1c9..37cae36ee 100644 --- a/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsViewModel.kt +++ b/profile/src/main/java/org/openedx/profile/presentation/settings/SettingsViewModel.kt @@ -23,7 +23,6 @@ import org.openedx.core.system.AppCookieManager import org.openedx.core.system.notifier.app.AppNotifier import org.openedx.core.system.notifier.app.AppUpgradeEvent import org.openedx.core.system.notifier.app.LogoutEvent -import org.openedx.core.utils.EmailUtil import org.openedx.foundation.extension.isInternetError import org.openedx.foundation.presentation.BaseViewModel import org.openedx.foundation.presentation.UIMessage @@ -182,11 +181,11 @@ class SettingsViewModel( logProfileEvent(ProfileAnalyticsEvent.TERMS_OF_USE_CLICKED) } - fun emailSupportClicked(context: Context) { - EmailUtil.showFeedbackScreen( - context = context, - feedbackEmailAddress = config.getFeedbackEmailAddress(), - appVersion = appData.versionName + fun emailSupportClicked(fragmentManager: FragmentManager) { + profileRouter.navigateToWebContent( + fm = fragmentManager, + title = resourceManager.getString(R.string.core_contact_support), + url = configuration.agreementUrls.contactSupportUrl, ) logProfileEvent(ProfileAnalyticsEvent.CONTACT_SUPPORT_CLICKED) }