Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -93,30 +93,32 @@ data class CourseProgressResponse(
@SerializedName("assignment_colors") val assignmentColors: List<String>?
) {
// TODO Temporary solution. Backend will returns color list later
val defaultColors = listOf(
"#D24242",
"#7B9645",
"#5A5AD8",
"#B0842C",
"#2E90C2",
"#D13F88",
"#36A17D",
"#AE5AD8",
"#3BA03B"
)
companion object {
val DEFAULT_COLORS = listOf(
"#D24242",
"#7B9645",
"#5A5AD8",
"#B0842C",
"#2E90C2",
"#D13F88",
"#36A17D",
"#AE5AD8",
"#3BA03B"
)
}

fun mapToRoomEntity() = GradingPolicyDb(
assignmentPolicies = assignmentPolicies?.map { it.mapToRoomEntity() } ?: emptyList(),
gradeRange = gradeRange ?: emptyMap(),
assignmentColors = assignmentColors ?: defaultColors
assignmentColors = assignmentColors ?: DEFAULT_COLORS
)

fun mapToDomain() = CourseProgress.GradingPolicy(
assignmentPolicies = assignmentPolicies?.map { it.mapToDomain() } ?: emptyList(),
gradeRange = gradeRange ?: emptyMap(),
assignmentColors = assignmentColors?.map { colorString ->
Color(colorString.toColorInt())
} ?: defaultColors.map { Color(it.toColorInt()) }
} ?: DEFAULT_COLORS.map { Color(it.toColorInt()) }
)

data class AssignmentPolicy(
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@ class CourseInteractor(
private val repository: CourseRepository
) : CourseInteractor {

fun startCourseSession(courseId: String) {
repository.startCourseSession(courseId)
}

suspend fun getCourseStructureFlow(
courseId: String,
forceRefresh: Boolean = true
forceRefresh: Boolean = false
): Flow<CourseStructure?> {
return repository.getCourseStructureFlow(courseId, forceRefresh)
}
Expand All @@ -31,8 +35,11 @@ class CourseInteractor(
return repository.getCourseStructureFromCache(courseId)
}

suspend fun getEnrollmentDetailsFlow(courseId: String): Flow<CourseEnrollmentDetails?> {
return repository.getEnrollmentDetailsFlow(courseId)
suspend fun getEnrollmentDetailsFlow(
courseId: String,
forceRefresh: Boolean = false
): Flow<CourseEnrollmentDetails?> {
return repository.getEnrollmentDetailsFlow(courseId, forceRefresh)
}

suspend fun getEnrollmentDetails(courseId: String): CourseEnrollmentDetails {
Expand Down Expand Up @@ -87,13 +94,22 @@ class CourseInteractor(
}
}

suspend fun getCourseStatusFlow(courseId: String) = repository.getCourseStatusFlow(courseId)
suspend fun getCourseStatusFlow(
courseId: String,
forceRefresh: Boolean = false
) = repository.getCourseStatusFlow(courseId, forceRefresh)

suspend fun getCourseStatus(courseId: String) = repository.getCourseStatus(courseId)

suspend fun getCourseDatesFlow(courseId: String) = repository.getCourseDatesFlow(courseId)
suspend fun getCourseDatesFlow(
courseId: String,
forceRefresh: Boolean = false
) = repository.getCourseDatesFlow(courseId, forceRefresh)

suspend fun getCourseDates(courseId: String) = repository.getCourseDates(courseId)
suspend fun getCourseDates(
courseId: String,
forceRefresh: Boolean = false
) = repository.getCourseDates(courseId, forceRefresh)

suspend fun resetCourseDates(courseId: String) = repository.resetCourseDates(courseId)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class CourseAssignmentViewModel(
private fun collectData() {
viewModelScope.launch {
val courseProgressFlow = interactor.getCourseProgress(courseId, false, true)
val courseStructureFlow = interactor.getCourseStructureFlow(courseId)
val courseStructureFlow = interactor.getCourseStructureFlow(courseId, false)

combine(
courseProgressFlow,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,6 @@ class CourseContainerFragment : Fragment(R.layout.fragment_course_container) {
observe()
}

override fun onResume() {
super.onResume()
if (viewModel.courseAccessStatus.value == CourseAccessError.NONE) {
viewModel.updateData()
}
}

override fun onDestroyView() {
snackBar?.dismiss()
super.onDestroyView()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,18 @@ class CourseContainerViewModel(

_showProgress.value = true

interactor.startCourseSession(courseId)

viewModelScope.launch {
val courseStructureFlow = interactor.getCourseStructureFlow(courseId)
.catch { e ->
handleFetchError(e)
emit(null)
}
val courseDetailsFlow = interactor.getEnrollmentDetailsFlow(courseId)
val courseDetailsFlow = interactor.getEnrollmentDetailsFlow(
courseId,
forceRefresh = true
)
.catch { emit(null) }
courseStructureFlow.combine(courseDetailsFlow) { courseStructure, courseEnrollmentDetails ->
courseStructure to courseEnrollmentDetails
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import org.openedx.core.domain.model.Block
import org.openedx.core.domain.model.CourseBannerType
import org.openedx.core.domain.model.CourseDateBlock
import org.openedx.core.domain.model.CourseStructure
import org.openedx.core.exception.NoCachedDataException
import org.openedx.core.extension.getSequentialBlocks
import org.openedx.core.extension.getVerticalBlocks
import org.openedx.core.presentation.settings.calendarsync.CalendarSyncDialogType
Expand Down Expand Up @@ -75,7 +76,7 @@ class CourseDatesViewModel(
courseNotifier.notifier.collect { event ->
when (event) {
is RefreshDates -> {
loadingCourseDatesInternal()
loadingCourseDatesInternal(forceRefresh = true)
}
}
}
Expand All @@ -91,15 +92,23 @@ class CourseDatesViewModel(
}
}

loadingCourseDatesInternal()
loadingCourseDatesInternal(forceRefresh = false)
}

private fun loadingCourseDatesInternal() {
private fun loadingCourseDatesInternal(forceRefresh: Boolean) {
viewModelScope.launch {
try {
courseStructure = interactor.getCourseStructure(courseId = courseId)
courseStructure = if (forceRefresh) {
interactor.getCourseStructure(courseId = courseId, isNeedRefresh = true)
} else {
interactor.getCourseStructure(courseId = courseId)
}
isSelfPaced = courseStructure?.isSelfPaced ?: false
val datesResponse = interactor.getCourseDates(courseId = courseId)
val datesResponse = if (forceRefresh) {
interactor.getCourseDates(courseId = courseId, forceRefresh = true)
} else {
interactor.getCourseDates(courseId = courseId)
}
if (datesResponse.datesSection.isEmpty()) {
_uiState.value = CourseDatesUIState.Error
} else {
Expand All @@ -111,7 +120,7 @@ class CourseDatesViewModel(
}
} catch (e: Exception) {
_uiState.value = CourseDatesUIState.Error
if (e.isInternetError()) {
if (e.isInternetError() || e is NoCachedDataException) {
_uiMessage.emit(
UIMessage.SnackBarMessage(resourceManager.getString(CoreR.string.core_error_no_connection))
)
Expand All @@ -126,7 +135,7 @@ class CourseDatesViewModel(
viewModelScope.launch {
try {
interactor.resetCourseDates(courseId = courseId)
loadingCourseDatesInternal()
loadingCourseDatesInternal(forceRefresh = true)
courseNotifier.send(CourseDatesShifted)
onResetDates(true)
} catch (e: Exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class CourseProgressViewModel(
private fun collectData(isRefresh: Boolean) {
viewModelScope.launch {
val courseProgressFlow = interactor.getCourseProgress(courseId, isRefresh, false)
val courseStructureFlow = interactor.getCourseStructureFlow(courseId)
val courseStructureFlow = interactor.getCourseStructureFlow(courseId, false)

combine(
courseProgressFlow,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.justRun
import io.mockk.mockk
import io.mockk.spyk
import io.mockk.verify
Expand Down Expand Up @@ -76,6 +77,7 @@ class CourseContainerViewModelTest {
every { corePreferences.appConfig } returns CoreMocks.mockAppConfig
every { courseNotifier.notifier } returns emptyFlow()
every { config.getApiHostURL() } returns "baseUrl"
justRun { interactor.startCourseSession(any()) }
coEvery { interactor.getEnrollmentDetails(any()) } returns CoreMocks.mockCourseEnrollmentDetails
every { imageProcessor.loadImage(any(), any(), any()) } returns Unit
every { imageProcessor.applyBlur(any(), any()) } returns mockBitmap
Expand Down Expand Up @@ -109,7 +111,7 @@ class CourseContainerViewModelTest {
interactor.getCourseStructureFlow(any(), any())
} returns flowOf(null)
coEvery {
interactor.getEnrollmentDetailsFlow(any())
interactor.getEnrollmentDetailsFlow(any(), any())
} returns flow { throw Exception() }
every {
analytics.logScreenEvent(
Expand All @@ -126,7 +128,7 @@ class CourseContainerViewModelTest {
viewModel.fetchCourseDetails()
advanceUntilIdle()

coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any()) }
coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any(), any()) }
verify(exactly = 1) {
analytics.logScreenEvent(
CourseAnalyticsEvent.DASHBOARD.eventName,
Expand Down Expand Up @@ -164,7 +166,7 @@ class CourseContainerViewModelTest {
coEvery { interactor.getCourseStructureFlow(any(), any()) } returns flowOf(
CoreMocks.mockCourseStructure
)
coEvery { interactor.getEnrollmentDetailsFlow(any()) } returns flowOf(
coEvery { interactor.getEnrollmentDetailsFlow(any(), any()) } returns flowOf(
CoreMocks.mockCourseEnrollmentDetails
)
every {
Expand All @@ -182,7 +184,7 @@ class CourseContainerViewModelTest {
viewModel.fetchCourseDetails()
advanceUntilIdle()

coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any()) }
coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any(), any()) }
verify(exactly = 1) {
analytics.logScreenEvent(
CourseAnalyticsEvent.DASHBOARD.eventName,
Expand Down Expand Up @@ -221,7 +223,7 @@ class CourseContainerViewModelTest {
coEvery { interactor.getCourseStructureFlow(any(), any()) } returns flowOf(
CoreMocks.mockCourseStructure
)
coEvery { interactor.getEnrollmentDetailsFlow(any()) } returns flowOf(
coEvery { interactor.getEnrollmentDetailsFlow(any(), any()) } returns flowOf(
CoreMocks.mockCourseEnrollmentDetails
)
every {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,15 @@ class CourseDatesViewModelTest {
courseRouter,
calendarRouter,
)
coEvery { interactor.getCourseDates(any()) } throws UnknownHostException()
coEvery { interactor.getCourseDates(any(), any()) } throws UnknownHostException()
val message = async {
withTimeoutOrNull(5000) {
viewModel.uiMessage.first() as? UIMessage.SnackBarMessage
}
}
advanceUntilIdle()

coVerify(exactly = 1) { interactor.getCourseDates(any()) }
coVerify(exactly = 1) { interactor.getCourseDates(any(), any()) }

Assert.assertEquals(noInternet, message.await()?.message)
assert(viewModel.uiState.value is CourseDatesUIState.Error)
Expand All @@ -141,15 +141,15 @@ class CourseDatesViewModelTest {
courseRouter,
calendarRouter,
)
coEvery { interactor.getCourseDates(any()) } throws Exception()
coEvery { interactor.getCourseDates(any(), any()) } throws Exception()
val message = async {
withTimeoutOrNull(5000) {
viewModel.uiMessage.first() as? UIMessage.SnackBarMessage
}
}
advanceUntilIdle()

coVerify(exactly = 1) { interactor.getCourseDates(any()) }
coVerify(exactly = 1) { interactor.getCourseDates(any(), any()) }

assert(message.await()?.message.isNullOrEmpty())
assert(viewModel.uiState.value is CourseDatesUIState.Error)
Expand All @@ -171,15 +171,20 @@ class CourseDatesViewModelTest {
courseRouter,
calendarRouter,
)
coEvery { interactor.getCourseDates(any()) } returns CourseMocks.courseDatesResultWithData
coEvery {
interactor.getCourseDates(
any(),
any()
)
} returns CourseMocks.courseDatesResultWithData
val message = async {
withTimeoutOrNull(5000) {
viewModel.uiMessage.first() as? UIMessage.SnackBarMessage
}
}
advanceUntilIdle()

coVerify(exactly = 1) { interactor.getCourseDates(any()) }
coVerify(exactly = 1) { interactor.getCourseDates(any(), any()) }

assert(message.await()?.message.isNullOrEmpty())
assert(viewModel.uiState.value is CourseDatesUIState.CourseDates)
Expand All @@ -201,7 +206,7 @@ class CourseDatesViewModelTest {
courseRouter,
calendarRouter,
)
coEvery { interactor.getCourseDates(any()) } returns CourseDatesResult(
coEvery { interactor.getCourseDates(any(), any()) } returns CourseDatesResult(
datesSection = linkedMapOf(),
courseBanner = CoreMocks.mockCourseDatesBannerInfo,
)
Expand All @@ -212,7 +217,7 @@ class CourseDatesViewModelTest {
}
advanceUntilIdle()

coVerify(exactly = 1) { interactor.getCourseDates(any()) }
coVerify(exactly = 1) { interactor.getCourseDates(any(), any()) }

assert(message.await()?.message.isNullOrEmpty())
assert(viewModel.uiState.value is CourseDatesUIState.Error)
Expand Down
Loading
Loading