Skip to content

Commit 9d88a92

Browse files
fix: removed requests duplication
1 parent a0c0c92 commit 9d88a92

12 files changed

Lines changed: 485 additions & 242 deletions

File tree

core/src/main/java/org/openedx/core/data/model/CourseProgressResponse.kt

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,30 +93,32 @@ data class CourseProgressResponse(
9393
@SerializedName("assignment_colors") val assignmentColors: List<String>?
9494
) {
9595
// TODO Temporary solution. Backend will returns color list later
96-
val defaultColors = listOf(
97-
"#D24242",
98-
"#7B9645",
99-
"#5A5AD8",
100-
"#B0842C",
101-
"#2E90C2",
102-
"#D13F88",
103-
"#36A17D",
104-
"#AE5AD8",
105-
"#3BA03B"
106-
)
96+
companion object {
97+
val DEFAULT_COLORS = listOf(
98+
"#D24242",
99+
"#7B9645",
100+
"#5A5AD8",
101+
"#B0842C",
102+
"#2E90C2",
103+
"#D13F88",
104+
"#36A17D",
105+
"#AE5AD8",
106+
"#3BA03B"
107+
)
108+
}
107109

108110
fun mapToRoomEntity() = GradingPolicyDb(
109111
assignmentPolicies = assignmentPolicies?.map { it.mapToRoomEntity() } ?: emptyList(),
110112
gradeRange = gradeRange ?: emptyMap(),
111-
assignmentColors = assignmentColors ?: defaultColors
113+
assignmentColors = assignmentColors ?: DEFAULT_COLORS
112114
)
113115

114116
fun mapToDomain() = CourseProgress.GradingPolicy(
115117
assignmentPolicies = assignmentPolicies?.map { it.mapToDomain() } ?: emptyList(),
116118
gradeRange = gradeRange ?: emptyMap(),
117119
assignmentColors = assignmentColors?.map { colorString ->
118120
Color(colorString.toColorInt())
119-
} ?: defaultColors.map { Color(it.toColorInt()) }
121+
} ?: DEFAULT_COLORS.map { Color(it.toColorInt()) }
120122
)
121123

122124
data class AssignmentPolicy(

course/src/main/java/org/openedx/course/data/repository/CourseRepository.kt

Lines changed: 225 additions & 69 deletions
Large diffs are not rendered by default.

course/src/main/java/org/openedx/course/domain/interactor/CourseInteractor.kt

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@ class CourseInteractor(
1313
private val repository: CourseRepository
1414
) : CourseInteractor {
1515

16+
fun startCourseSession(courseId: String) {
17+
repository.startCourseSession(courseId)
18+
}
19+
1620
suspend fun getCourseStructureFlow(
1721
courseId: String,
18-
forceRefresh: Boolean = true
22+
forceRefresh: Boolean = false
1923
): Flow<CourseStructure?> {
2024
return repository.getCourseStructureFlow(courseId, forceRefresh)
2125
}
@@ -31,8 +35,11 @@ class CourseInteractor(
3135
return repository.getCourseStructureFromCache(courseId)
3236
}
3337

34-
suspend fun getEnrollmentDetailsFlow(courseId: String): Flow<CourseEnrollmentDetails?> {
35-
return repository.getEnrollmentDetailsFlow(courseId)
38+
suspend fun getEnrollmentDetailsFlow(
39+
courseId: String,
40+
forceRefresh: Boolean = false
41+
): Flow<CourseEnrollmentDetails?> {
42+
return repository.getEnrollmentDetailsFlow(courseId, forceRefresh)
3643
}
3744

3845
suspend fun getEnrollmentDetails(courseId: String): CourseEnrollmentDetails {
@@ -87,13 +94,22 @@ class CourseInteractor(
8794
}
8895
}
8996

90-
suspend fun getCourseStatusFlow(courseId: String) = repository.getCourseStatusFlow(courseId)
97+
suspend fun getCourseStatusFlow(
98+
courseId: String,
99+
forceRefresh: Boolean = false
100+
) = repository.getCourseStatusFlow(courseId, forceRefresh)
91101

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

94-
suspend fun getCourseDatesFlow(courseId: String) = repository.getCourseDatesFlow(courseId)
104+
suspend fun getCourseDatesFlow(
105+
courseId: String,
106+
forceRefresh: Boolean = false
107+
) = repository.getCourseDatesFlow(courseId, forceRefresh)
95108

96-
suspend fun getCourseDates(courseId: String) = repository.getCourseDates(courseId)
109+
suspend fun getCourseDates(
110+
courseId: String,
111+
forceRefresh: Boolean = false
112+
) = repository.getCourseDates(courseId, forceRefresh)
97113

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

course/src/main/java/org/openedx/course/presentation/assignments/CourseAssignmentViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class CourseAssignmentViewModel(
3939
private fun collectData() {
4040
viewModelScope.launch {
4141
val courseProgressFlow = interactor.getCourseProgress(courseId, false, true)
42-
val courseStructureFlow = interactor.getCourseStructureFlow(courseId)
42+
val courseStructureFlow = interactor.getCourseStructureFlow(courseId, false)
4343

4444
combine(
4545
courseProgressFlow,

course/src/main/java/org/openedx/course/presentation/container/CourseContainerFragment.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,6 @@ class CourseContainerFragment : Fragment(R.layout.fragment_course_container) {
143143
observe()
144144
}
145145

146-
override fun onResume() {
147-
super.onResume()
148-
if (viewModel.courseAccessStatus.value == CourseAccessError.NONE) {
149-
viewModel.updateData()
150-
}
151-
}
152-
153146
override fun onDestroyView() {
154147
snackBar?.dismiss()
155148
super.onDestroyView()

course/src/main/java/org/openedx/course/presentation/container/CourseContainerViewModel.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,18 @@ class CourseContainerViewModel(
172172

173173
_showProgress.value = true
174174

175+
interactor.startCourseSession(courseId)
176+
175177
viewModelScope.launch {
176178
val courseStructureFlow = interactor.getCourseStructureFlow(courseId)
177179
.catch { e ->
178180
handleFetchError(e)
179181
emit(null)
180182
}
181-
val courseDetailsFlow = interactor.getEnrollmentDetailsFlow(courseId)
183+
val courseDetailsFlow = interactor.getEnrollmentDetailsFlow(
184+
courseId,
185+
forceRefresh = true
186+
)
182187
.catch { emit(null) }
183188
courseStructureFlow.combine(courseDetailsFlow) { courseStructure, courseEnrollmentDetails ->
184189
courseStructure to courseEnrollmentDetails

course/src/main/java/org/openedx/course/presentation/dates/CourseDatesViewModel.kt

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import org.openedx.core.domain.model.Block
1818
import org.openedx.core.domain.model.CourseBannerType
1919
import org.openedx.core.domain.model.CourseDateBlock
2020
import org.openedx.core.domain.model.CourseStructure
21+
import org.openedx.core.exception.NoCachedDataException
2122
import org.openedx.core.extension.getSequentialBlocks
2223
import org.openedx.core.extension.getVerticalBlocks
2324
import org.openedx.core.presentation.settings.calendarsync.CalendarSyncDialogType
@@ -75,7 +76,7 @@ class CourseDatesViewModel(
7576
courseNotifier.notifier.collect { event ->
7677
when (event) {
7778
is RefreshDates -> {
78-
loadingCourseDatesInternal()
79+
loadingCourseDatesInternal(forceRefresh = true)
7980
}
8081
}
8182
}
@@ -91,15 +92,23 @@ class CourseDatesViewModel(
9192
}
9293
}
9394

94-
loadingCourseDatesInternal()
95+
loadingCourseDatesInternal(forceRefresh = false)
9596
}
9697

97-
private fun loadingCourseDatesInternal() {
98+
private fun loadingCourseDatesInternal(forceRefresh: Boolean) {
9899
viewModelScope.launch {
99100
try {
100-
courseStructure = interactor.getCourseStructure(courseId = courseId)
101+
courseStructure = if (forceRefresh) {
102+
interactor.getCourseStructure(courseId = courseId, isNeedRefresh = true)
103+
} else {
104+
interactor.getCourseStructure(courseId = courseId)
105+
}
101106
isSelfPaced = courseStructure?.isSelfPaced ?: false
102-
val datesResponse = interactor.getCourseDates(courseId = courseId)
107+
val datesResponse = if (forceRefresh) {
108+
interactor.getCourseDates(courseId = courseId, forceRefresh = true)
109+
} else {
110+
interactor.getCourseDates(courseId = courseId)
111+
}
103112
if (datesResponse.datesSection.isEmpty()) {
104113
_uiState.value = CourseDatesUIState.Error
105114
} else {
@@ -111,7 +120,7 @@ class CourseDatesViewModel(
111120
}
112121
} catch (e: Exception) {
113122
_uiState.value = CourseDatesUIState.Error
114-
if (e.isInternetError()) {
123+
if (e.isInternetError() || e is NoCachedDataException) {
115124
_uiMessage.emit(
116125
UIMessage.SnackBarMessage(resourceManager.getString(CoreR.string.core_error_no_connection))
117126
)
@@ -126,7 +135,7 @@ class CourseDatesViewModel(
126135
viewModelScope.launch {
127136
try {
128137
interactor.resetCourseDates(courseId = courseId)
129-
loadingCourseDatesInternal()
138+
loadingCourseDatesInternal(forceRefresh = true)
130139
courseNotifier.send(CourseDatesShifted)
131140
onResetDates(true)
132141
} catch (e: Exception) {

course/src/main/java/org/openedx/course/presentation/progress/CourseProgressViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class CourseProgressViewModel(
4141
private fun collectData(isRefresh: Boolean) {
4242
viewModelScope.launch {
4343
val courseProgressFlow = interactor.getCourseProgress(courseId, isRefresh, false)
44-
val courseStructureFlow = interactor.getCourseStructureFlow(courseId)
44+
val courseStructureFlow = interactor.getCourseStructureFlow(courseId, false)
4545

4646
combine(
4747
courseProgressFlow,

course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.arch.core.executor.testing.InstantTaskExecutorRule
55
import io.mockk.coEvery
66
import io.mockk.coVerify
77
import io.mockk.every
8+
import io.mockk.justRun
89
import io.mockk.mockk
910
import io.mockk.spyk
1011
import io.mockk.verify
@@ -76,6 +77,7 @@ class CourseContainerViewModelTest {
7677
every { corePreferences.appConfig } returns CoreMocks.mockAppConfig
7778
every { courseNotifier.notifier } returns emptyFlow()
7879
every { config.getApiHostURL() } returns "baseUrl"
80+
justRun { interactor.startCourseSession(any()) }
7981
coEvery { interactor.getEnrollmentDetails(any()) } returns CoreMocks.mockCourseEnrollmentDetails
8082
every { imageProcessor.loadImage(any(), any(), any()) } returns Unit
8183
every { imageProcessor.applyBlur(any(), any()) } returns mockBitmap
@@ -109,7 +111,7 @@ class CourseContainerViewModelTest {
109111
interactor.getCourseStructureFlow(any(), any())
110112
} returns flowOf(null)
111113
coEvery {
112-
interactor.getEnrollmentDetailsFlow(any())
114+
interactor.getEnrollmentDetailsFlow(any(), any())
113115
} returns flow { throw Exception() }
114116
every {
115117
analytics.logScreenEvent(
@@ -126,7 +128,7 @@ class CourseContainerViewModelTest {
126128
viewModel.fetchCourseDetails()
127129
advanceUntilIdle()
128130

129-
coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any()) }
131+
coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any(), any()) }
130132
verify(exactly = 1) {
131133
analytics.logScreenEvent(
132134
CourseAnalyticsEvent.DASHBOARD.eventName,
@@ -164,7 +166,7 @@ class CourseContainerViewModelTest {
164166
coEvery { interactor.getCourseStructureFlow(any(), any()) } returns flowOf(
165167
CoreMocks.mockCourseStructure
166168
)
167-
coEvery { interactor.getEnrollmentDetailsFlow(any()) } returns flowOf(
169+
coEvery { interactor.getEnrollmentDetailsFlow(any(), any()) } returns flowOf(
168170
CoreMocks.mockCourseEnrollmentDetails
169171
)
170172
every {
@@ -182,7 +184,7 @@ class CourseContainerViewModelTest {
182184
viewModel.fetchCourseDetails()
183185
advanceUntilIdle()
184186

185-
coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any()) }
187+
coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any(), any()) }
186188
verify(exactly = 1) {
187189
analytics.logScreenEvent(
188190
CourseAnalyticsEvent.DASHBOARD.eventName,
@@ -221,7 +223,7 @@ class CourseContainerViewModelTest {
221223
coEvery { interactor.getCourseStructureFlow(any(), any()) } returns flowOf(
222224
CoreMocks.mockCourseStructure
223225
)
224-
coEvery { interactor.getEnrollmentDetailsFlow(any()) } returns flowOf(
226+
coEvery { interactor.getEnrollmentDetailsFlow(any(), any()) } returns flowOf(
225227
CoreMocks.mockCourseEnrollmentDetails
226228
)
227229
every {

course/src/test/java/org/openedx/course/presentation/dates/CourseDatesViewModelTest.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,15 @@ class CourseDatesViewModelTest {
111111
courseRouter,
112112
calendarRouter,
113113
)
114-
coEvery { interactor.getCourseDates(any()) } throws UnknownHostException()
114+
coEvery { interactor.getCourseDates(any(), any()) } throws UnknownHostException()
115115
val message = async {
116116
withTimeoutOrNull(5000) {
117117
viewModel.uiMessage.first() as? UIMessage.SnackBarMessage
118118
}
119119
}
120120
advanceUntilIdle()
121121

122-
coVerify(exactly = 1) { interactor.getCourseDates(any()) }
122+
coVerify(exactly = 1) { interactor.getCourseDates(any(), any()) }
123123

124124
Assert.assertEquals(noInternet, message.await()?.message)
125125
assert(viewModel.uiState.value is CourseDatesUIState.Error)
@@ -141,15 +141,15 @@ class CourseDatesViewModelTest {
141141
courseRouter,
142142
calendarRouter,
143143
)
144-
coEvery { interactor.getCourseDates(any()) } throws Exception()
144+
coEvery { interactor.getCourseDates(any(), any()) } throws Exception()
145145
val message = async {
146146
withTimeoutOrNull(5000) {
147147
viewModel.uiMessage.first() as? UIMessage.SnackBarMessage
148148
}
149149
}
150150
advanceUntilIdle()
151151

152-
coVerify(exactly = 1) { interactor.getCourseDates(any()) }
152+
coVerify(exactly = 1) { interactor.getCourseDates(any(), any()) }
153153

154154
assert(message.await()?.message.isNullOrEmpty())
155155
assert(viewModel.uiState.value is CourseDatesUIState.Error)
@@ -171,15 +171,20 @@ class CourseDatesViewModelTest {
171171
courseRouter,
172172
calendarRouter,
173173
)
174-
coEvery { interactor.getCourseDates(any()) } returns CourseMocks.courseDatesResultWithData
174+
coEvery {
175+
interactor.getCourseDates(
176+
any(),
177+
any()
178+
)
179+
} returns CourseMocks.courseDatesResultWithData
175180
val message = async {
176181
withTimeoutOrNull(5000) {
177182
viewModel.uiMessage.first() as? UIMessage.SnackBarMessage
178183
}
179184
}
180185
advanceUntilIdle()
181186

182-
coVerify(exactly = 1) { interactor.getCourseDates(any()) }
187+
coVerify(exactly = 1) { interactor.getCourseDates(any(), any()) }
183188

184189
assert(message.await()?.message.isNullOrEmpty())
185190
assert(viewModel.uiState.value is CourseDatesUIState.CourseDates)
@@ -201,7 +206,7 @@ class CourseDatesViewModelTest {
201206
courseRouter,
202207
calendarRouter,
203208
)
204-
coEvery { interactor.getCourseDates(any()) } returns CourseDatesResult(
209+
coEvery { interactor.getCourseDates(any(), any()) } returns CourseDatesResult(
205210
datesSection = linkedMapOf(),
206211
courseBanner = CoreMocks.mockCourseDatesBannerInfo,
207212
)
@@ -212,7 +217,7 @@ class CourseDatesViewModelTest {
212217
}
213218
advanceUntilIdle()
214219

215-
coVerify(exactly = 1) { interactor.getCourseDates(any()) }
220+
coVerify(exactly = 1) { interactor.getCourseDates(any(), any()) }
216221

217222
assert(message.await()?.message.isNullOrEmpty())
218223
assert(viewModel.uiState.value is CourseDatesUIState.Error)

0 commit comments

Comments
 (0)