mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2025-01-31 21:12:44 +01:00
Migrate presenters from rxjava to coroutines flow (#894)
This commit is contained in:
parent
b0a674b471
commit
1ac42bb56d
@ -92,6 +92,7 @@ android {
|
|||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
|
freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
|
||||||
}
|
}
|
||||||
|
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
@ -116,7 +117,7 @@ ext {
|
|||||||
room = "2.2.5"
|
room = "2.2.5"
|
||||||
dagger = "2.28.3"
|
dagger = "2.28.3"
|
||||||
chucker = "3.2.0"
|
chucker = "3.2.0"
|
||||||
mockk = "1.9.2"
|
mockk = "1.10.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations.all {
|
configurations.all {
|
||||||
@ -129,6 +130,7 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.3.7'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-rx2:1.3.7'
|
||||||
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7'
|
||||||
|
|
||||||
implementation "androidx.core:core-ktx:1.3.0"
|
implementation "androidx.core:core-ktx:1.3.0"
|
||||||
implementation "androidx.activity:activity-ktx:1.1.0"
|
implementation "androidx.activity:activity-ktx:1.1.0"
|
||||||
@ -156,7 +158,6 @@ dependencies {
|
|||||||
implementation 'com.github.PaulinaSadowska:RxWorkManagerObservers:1.0.0'
|
implementation 'com.github.PaulinaSadowska:RxWorkManagerObservers:1.0.0'
|
||||||
|
|
||||||
implementation "androidx.room:room-runtime:$room"
|
implementation "androidx.room:room-runtime:$room"
|
||||||
implementation "androidx.room:room-rxjava2:$room"
|
|
||||||
implementation "androidx.room:room-ktx:$room"
|
implementation "androidx.room:room-ktx:$room"
|
||||||
kapt "androidx.room:room-compiler:$room"
|
kapt "androidx.room:room-compiler:$room"
|
||||||
|
|
||||||
@ -199,6 +200,7 @@ dependencies {
|
|||||||
testImplementation "junit:junit:4.13"
|
testImplementation "junit:junit:4.13"
|
||||||
testImplementation "io.mockk:mockk:$mockk"
|
testImplementation "io.mockk:mockk:$mockk"
|
||||||
testImplementation "org.threeten:threetenbp:1.4.4"
|
testImplementation "org.threeten:threetenbp:1.4.4"
|
||||||
|
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.7'
|
||||||
|
|
||||||
androidTestImplementation "androidx.test:core:1.2.0"
|
androidTestImplementation "androidx.test:core:1.2.0"
|
||||||
androidTestImplementation "androidx.test:runner:1.2.0"
|
androidTestImplementation "androidx.test:runner:1.2.0"
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package io.github.wulkanowy.data
|
||||||
|
|
||||||
|
import io.github.wulkanowy.utils.DispatchersProvider
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
||||||
|
class TestDispatchersProvider : DispatchersProvider() {
|
||||||
|
|
||||||
|
override val backgroundThread: CoroutineDispatcher
|
||||||
|
get() = Dispatchers.Unconfined
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package io.github.wulkanowy.data.repositories
|
package io.github.wulkanowy.data.repositories
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import org.threeten.bp.LocalDate.now
|
||||||
import org.threeten.bp.LocalDateTime
|
import org.threeten.bp.LocalDateTime
|
||||||
|
|
||||||
fun getStudent(): Student {
|
fun getStudent(): Student {
|
||||||
@ -27,3 +29,16 @@ fun getStudent(): Student {
|
|||||||
isParent = false
|
isParent = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSemester() = Semester(
|
||||||
|
semesterId = 1,
|
||||||
|
studentId = 1,
|
||||||
|
classId = 1,
|
||||||
|
diaryId = 2,
|
||||||
|
diaryName = "",
|
||||||
|
end = now(),
|
||||||
|
schoolYear = 2019,
|
||||||
|
semesterName = 1,
|
||||||
|
start = now(),
|
||||||
|
unitId = 1
|
||||||
|
)
|
||||||
|
@ -6,6 +6,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -53,7 +54,7 @@ class AttendanceLocalTest {
|
|||||||
runBlocking { attendanceLocal.saveAttendance(list) }
|
runBlocking { attendanceLocal.saveAttendance(list) }
|
||||||
|
|
||||||
val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
|
val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
|
||||||
val attendance = runBlocking { attendanceLocal.getAttendance(semester, of(2018, 9, 10), of(2018, 9, 14)) }
|
val attendance = runBlocking { attendanceLocal.getAttendance(semester, of(2018, 9, 10), of(2018, 9, 14)).first() }
|
||||||
assertEquals(2, attendance.size)
|
assertEquals(2, attendance.size)
|
||||||
assertEquals(attendance[0].date, of(2018, 9, 10))
|
assertEquals(attendance[0].date, of(2018, 9, 10))
|
||||||
assertEquals(attendance[1].date, of(2018, 9, 14))
|
assertEquals(attendance[1].date, of(2018, 9, 14))
|
||||||
|
@ -6,6 +6,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -46,7 +47,7 @@ class CompletedLessonsLocalTest {
|
|||||||
runBlocking { completedLessonsLocal.saveCompletedLessons(list) }
|
runBlocking { completedLessonsLocal.saveCompletedLessons(list) }
|
||||||
|
|
||||||
val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
|
val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
|
||||||
val completed = runBlocking { completedLessonsLocal.getCompletedLessons(semester, of(2018, 9, 10), of(2018, 9, 14)) }
|
val completed = runBlocking { completedLessonsLocal.getCompletedLessons(semester, of(2018, 9, 10), of(2018, 9, 14)).first() }
|
||||||
assertEquals(2, completed.size)
|
assertEquals(2, completed.size)
|
||||||
assertEquals(completed[0].date, of(2018, 9, 10))
|
assertEquals(completed[0].date, of(2018, 9, 10))
|
||||||
assertEquals(completed[1].date, of(2018, 9, 14))
|
assertEquals(completed[1].date, of(2018, 9, 14))
|
||||||
|
@ -6,6 +6,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -43,7 +44,7 @@ class ExamLocalTest {
|
|||||||
runBlocking { examLocal.saveExams(list) }
|
runBlocking { examLocal.saveExams(list) }
|
||||||
|
|
||||||
val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
|
val semester = Semester(1, 2, "", 1, 3, 2019, now(), now(), 1, 1)
|
||||||
val exams = runBlocking { examLocal.getExams(semester, of(2018, 9, 10), of(2018, 9, 14)) }
|
val exams = runBlocking { examLocal.getExams(semester, of(2018, 9, 10), of(2018, 9, 14)).first() }
|
||||||
assertEquals(2, exams.size)
|
assertEquals(2, exams.size)
|
||||||
assertEquals(exams[0].date, of(2018, 9, 10))
|
assertEquals(exams[0].date, of(2018, 9, 10))
|
||||||
assertEquals(exams[1].date, of(2018, 9, 14))
|
assertEquals(exams[1].date, of(2018, 9, 14))
|
||||||
|
@ -5,6 +5,7 @@ import androidx.test.core.app.ApplicationProvider
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -45,7 +46,7 @@ class GradeLocalTest {
|
|||||||
|
|
||||||
val semester = Semester(1, 2, "", 2019, 2, 1, now(), now(), 1, 1)
|
val semester = Semester(1, 2, "", 2019, 2, 1, now(), now(), 1, 1)
|
||||||
|
|
||||||
val grades = runBlocking { gradeLocal.getGradesDetails(semester) }
|
val grades = runBlocking { gradeLocal.getGradesDetails(semester).first() }
|
||||||
|
|
||||||
assertEquals(2, grades.size)
|
assertEquals(2, grades.size)
|
||||||
assertEquals(grades[0].date, LocalDate.of(2019, 2, 27))
|
assertEquals(grades[0].date, LocalDate.of(2019, 2, 27))
|
||||||
|
@ -5,15 +5,18 @@ import androidx.room.Room
|
|||||||
import androidx.test.core.app.ApplicationProvider.getApplicationContext
|
import androidx.test.core.app.ApplicationProvider.getApplicationContext
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.SdkSuppress
|
import androidx.test.filters.SdkSuppress
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.sdk.pojo.Grade
|
|
||||||
import io.mockk.MockKAnnotations
|
import io.mockk.MockKAnnotations
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.impl.annotations.MockK
|
import io.mockk.impl.annotations.MockK
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -29,15 +32,12 @@ import kotlin.test.assertTrue
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class GradeRepositoryTest {
|
class GradeRepositoryTest {
|
||||||
|
|
||||||
@MockK
|
|
||||||
private lateinit var mockSdk: Sdk
|
|
||||||
|
|
||||||
@MockK
|
@MockK
|
||||||
private lateinit var semesterMock: Semester
|
private lateinit var semesterMock: Semester
|
||||||
|
|
||||||
@MockK
|
|
||||||
private lateinit var studentMock: Student
|
private lateinit var studentMock: Student
|
||||||
|
|
||||||
|
@MockK
|
||||||
private lateinit var gradeRemote: GradeRemote
|
private lateinit var gradeRemote: GradeRemote
|
||||||
|
|
||||||
private lateinit var gradeLocal: GradeLocal
|
private lateinit var gradeLocal: GradeLocal
|
||||||
@ -49,14 +49,12 @@ class GradeRepositoryTest {
|
|||||||
MockKAnnotations.init(this)
|
MockKAnnotations.init(this)
|
||||||
testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
|
testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
|
||||||
gradeLocal = GradeLocal(testDb.gradeDao, testDb.gradeSummaryDao)
|
gradeLocal = GradeLocal(testDb.gradeDao, testDb.gradeSummaryDao)
|
||||||
gradeRemote = GradeRemote(mockSdk)
|
studentMock = getStudentMock()
|
||||||
|
|
||||||
every { studentMock.registrationDate } returns LocalDateTime.of(2019, 2, 27, 12, 0)
|
|
||||||
every { semesterMock.studentId } returns 1
|
every { semesterMock.studentId } returns 1
|
||||||
every { semesterMock.diaryId } returns 1
|
every { semesterMock.diaryId } returns 1
|
||||||
every { semesterMock.schoolYear } returns 2019
|
every { semesterMock.schoolYear } returns 2019
|
||||||
every { semesterMock.semesterId } returns 1
|
every { semesterMock.semesterId } returns 1
|
||||||
every { mockSdk.switchDiary(any(), any()) } returns mockSdk
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -66,16 +64,17 @@ class GradeRepositoryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun markOlderThanRegisterDateAsRead() {
|
fun markOlderThanRegisterDateAsRead() {
|
||||||
coEvery { mockSdk.getGrades(1) } returns (listOf(
|
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
|
||||||
createGradeApi(5, 4.0, of(2019, 2, 25), "Ocena pojawiła się"),
|
createGradeLocal(5, 4.0, of(2019, 2, 25), "Ocena pojawiła się"),
|
||||||
createGradeApi(5, 4.0, of(2019, 2, 26), "przed zalogowanie w aplikacji"),
|
createGradeLocal(5, 4.0, of(2019, 2, 26), "przed zalogowanie w aplikacji"),
|
||||||
createGradeApi(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"),
|
createGradeLocal(5, 4.0, of(2019, 2, 27), "Ocena z dnia logowania"),
|
||||||
createGradeApi(5, 4.0, of(2019, 2, 28), "Ocena jeszcze nowsza")
|
createGradeLocal(5, 4.0, of(2019, 2, 28), "Ocena jeszcze nowsza")
|
||||||
) to emptyList())
|
) to emptyList())
|
||||||
|
|
||||||
val grades = runBlocking {
|
val grades = runBlocking {
|
||||||
GradeRepository(gradeLocal, gradeRemote).getGrades(studentMock, semesterMock, true)
|
GradeRepository(gradeLocal, gradeRemote)
|
||||||
.first.sortedByDescending { it.date }
|
.getGrades(studentMock, semesterMock, true)
|
||||||
|
.filter { it.status == Status.SUCCESS }.first().data!!.first.sortedByDescending { it.date }
|
||||||
}
|
}
|
||||||
|
|
||||||
assertFalse { grades[0].isRead }
|
assertFalse { grades[0].isRead }
|
||||||
@ -93,16 +92,17 @@ class GradeRepositoryTest {
|
|||||||
)
|
)
|
||||||
runBlocking { gradeLocal.saveGrades(list) }
|
runBlocking { gradeLocal.saveGrades(list) }
|
||||||
|
|
||||||
coEvery { mockSdk.getGrades(1) } returns (listOf(
|
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
|
||||||
createGradeApi(5, 2.0, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"),
|
createGradeLocal(5, 2.0, of(2019, 2, 25), "Ocena ma datę, jest inna, ale nie zostanie powiadomiona"),
|
||||||
createGradeApi(4, 3.0, of(2019, 2, 26), "starszą niż ostatnia lokalnie"),
|
createGradeLocal(4, 3.0, of(2019, 2, 26), "starszą niż ostatnia lokalnie"),
|
||||||
createGradeApi(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"),
|
createGradeLocal(3, 4.0, of(2019, 2, 27), "Ta jest z tego samego dnia co ostatnia lokalnie"),
|
||||||
createGradeApi(2, 5.0, of(2019, 2, 28), "Ta jest już w ogóle nowa")
|
createGradeLocal(2, 5.0, of(2019, 2, 28), "Ta jest już w ogóle nowa")
|
||||||
) to emptyList())
|
) to emptyList())
|
||||||
|
|
||||||
val grades = runBlocking {
|
val grades = runBlocking {
|
||||||
GradeRepository(gradeLocal, gradeRemote).getGrades(studentMock, semesterMock, true)
|
GradeRepository(gradeLocal, gradeRemote)
|
||||||
.first.sortedByDescending { it.date }
|
.getGrades(studentMock, semesterMock, true)
|
||||||
|
.filter { it.status == Status.SUCCESS }.first().data!!.first.sortedByDescending { it.date }
|
||||||
}
|
}
|
||||||
|
|
||||||
assertFalse { grades[0].isRead }
|
assertFalse { grades[0].isRead }
|
||||||
@ -120,13 +120,15 @@ class GradeRepositoryTest {
|
|||||||
)
|
)
|
||||||
runBlocking { gradeLocal.saveGrades(list) }
|
runBlocking { gradeLocal.saveGrades(list) }
|
||||||
|
|
||||||
coEvery { mockSdk.getGrades(1) } returns (listOf(
|
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
|
||||||
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||||
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||||
) to emptyList())
|
) to emptyList())
|
||||||
|
|
||||||
val grades = runBlocking {
|
val grades = runBlocking {
|
||||||
GradeRepository(gradeLocal, gradeRemote).getGrades(studentMock, semesterMock, true)
|
GradeRepository(gradeLocal, gradeRemote)
|
||||||
|
.getGrades(studentMock, semesterMock, true)
|
||||||
|
.filter { it.status == Status.SUCCESS }.first().data!!
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(2, grades.first.size)
|
assertEquals(2, grades.first.size)
|
||||||
@ -140,14 +142,16 @@ class GradeRepositoryTest {
|
|||||||
)
|
)
|
||||||
runBlocking { gradeLocal.saveGrades(list) }
|
runBlocking { gradeLocal.saveGrades(list) }
|
||||||
|
|
||||||
coEvery { mockSdk.getGrades(1) } returns (listOf(
|
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
|
||||||
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||||
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||||
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||||
) to emptyList())
|
) to emptyList())
|
||||||
|
|
||||||
val grades = runBlocking {
|
val grades = runBlocking {
|
||||||
GradeRepository(gradeLocal, gradeRemote).getGrades(studentMock, semesterMock, true)
|
GradeRepository(gradeLocal, gradeRemote)
|
||||||
|
.getGrades(studentMock, semesterMock, true)
|
||||||
|
.filter { it.status == Status.SUCCESS }.first().data!!
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(3, grades.first.size)
|
assertEquals(3, grades.first.size)
|
||||||
@ -157,14 +161,16 @@ class GradeRepositoryTest {
|
|||||||
fun emptyLocal() {
|
fun emptyLocal() {
|
||||||
runBlocking { gradeLocal.saveGrades(listOf()) }
|
runBlocking { gradeLocal.saveGrades(listOf()) }
|
||||||
|
|
||||||
coEvery { mockSdk.getGrades(1) } returns (listOf(
|
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (listOf(
|
||||||
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||||
createGradeApi(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
createGradeLocal(5, 3.0, of(2019, 2, 25), "Taka sama ocena"),
|
||||||
createGradeApi(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
createGradeLocal(3, 5.0, of(2019, 2, 26), "Jakaś inna ocena")
|
||||||
) to emptyList())
|
) to emptyList())
|
||||||
|
|
||||||
val grades = runBlocking {
|
val grades = runBlocking {
|
||||||
GradeRepository(gradeLocal, gradeRemote).getGrades(studentMock, semesterMock, true)
|
GradeRepository(gradeLocal, gradeRemote)
|
||||||
|
.getGrades(studentMock, semesterMock, true)
|
||||||
|
.filter { it.status == Status.SUCCESS }.first().data!!
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(3, grades.first.size)
|
assertEquals(3, grades.first.size)
|
||||||
@ -178,12 +184,37 @@ class GradeRepositoryTest {
|
|||||||
)
|
)
|
||||||
runBlocking { gradeLocal.saveGrades(list) }
|
runBlocking { gradeLocal.saveGrades(list) }
|
||||||
|
|
||||||
coEvery { mockSdk.getGrades(1) } returns (emptyList<Grade>() to emptyList())
|
coEvery { gradeRemote.getGrades(studentMock, semesterMock) } returns (emptyList<Grade>() to emptyList())
|
||||||
|
|
||||||
val grades = runBlocking {
|
val grades = runBlocking {
|
||||||
GradeRepository(gradeLocal, gradeRemote).getGrades(studentMock, semesterMock, true)
|
GradeRepository(gradeLocal, gradeRemote)
|
||||||
|
.getGrades(studentMock, semesterMock, true)
|
||||||
|
.filter { it.status == Status.SUCCESS }.first().data!!
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(0, grades.first.size)
|
assertEquals(0, grades.first.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getStudentMock() = Student(
|
||||||
|
scrapperBaseUrl = "http://fakelog.cf",
|
||||||
|
email = "jan@fakelog.cf",
|
||||||
|
certificateKey = "",
|
||||||
|
classId = 0,
|
||||||
|
className = "",
|
||||||
|
isCurrent = false,
|
||||||
|
isParent = false,
|
||||||
|
loginMode = Sdk.Mode.SCRAPPER.name,
|
||||||
|
loginType = "STANDARD",
|
||||||
|
mobileBaseUrl = "",
|
||||||
|
password = "",
|
||||||
|
privateKey = "",
|
||||||
|
registrationDate = LocalDateTime.of(2019, 2, 27, 12, 0),
|
||||||
|
schoolName = "",
|
||||||
|
schoolShortName = "test",
|
||||||
|
schoolSymbol = "",
|
||||||
|
studentId = 0,
|
||||||
|
studentName = "",
|
||||||
|
symbol = "",
|
||||||
|
userLoginId = 0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import io.github.wulkanowy.data.db.AppDatabase
|
|||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -42,7 +43,7 @@ class GradeStatisticsLocalTest {
|
|||||||
)
|
)
|
||||||
runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) }
|
runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) }
|
||||||
|
|
||||||
val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false, "Matematyka") }
|
val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false).first() }
|
||||||
assertEquals(1, stats.size)
|
assertEquals(1, stats.size)
|
||||||
assertEquals(stats[0].subject, "Matematyka")
|
assertEquals(stats[0].subject, "Matematyka")
|
||||||
}
|
}
|
||||||
@ -56,11 +57,12 @@ class GradeStatisticsLocalTest {
|
|||||||
)
|
)
|
||||||
runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) }
|
runBlocking { gradeStatisticsLocal.saveGradesStatistics(list) }
|
||||||
|
|
||||||
val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false, "Wszystkie") }
|
val stats = runBlocking { gradeStatisticsLocal.getGradesStatistics(getSemester(), false).first() }
|
||||||
assertEquals(3, stats.size)
|
assertEquals(2, stats.size)
|
||||||
assertEquals(stats[0].subject, "Wszystkie")
|
// assertEquals(3, stats.size)
|
||||||
assertEquals(stats[1].subject, "Matematyka")
|
// assertEquals(stats[0].subject, "Wszystkie") // now in main repo
|
||||||
assertEquals(stats[2].subject, "Chemia")
|
assertEquals(stats[0].subject, "Matematyka")
|
||||||
|
assertEquals(stats[1].subject, "Chemia")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -72,7 +74,7 @@ class GradeStatisticsLocalTest {
|
|||||||
)
|
)
|
||||||
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(list) }
|
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(list) }
|
||||||
|
|
||||||
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester(), "Matematyka") }
|
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() }
|
||||||
with(stats[0]) {
|
with(stats[0]) {
|
||||||
assertEquals(subject, "Matematyka")
|
assertEquals(subject, "Matematyka")
|
||||||
assertEquals(others, 5.0)
|
assertEquals(others, 5.0)
|
||||||
@ -84,7 +86,7 @@ class GradeStatisticsLocalTest {
|
|||||||
fun saveAndRead_subjectEmpty() {
|
fun saveAndRead_subjectEmpty() {
|
||||||
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) }
|
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) }
|
||||||
|
|
||||||
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester(), "Matematyka") }
|
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() }
|
||||||
assertEquals(emptyList(), stats)
|
assertEquals(emptyList(), stats)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +94,7 @@ class GradeStatisticsLocalTest {
|
|||||||
fun saveAndRead_allEmpty() {
|
fun saveAndRead_allEmpty() {
|
||||||
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) }
|
runBlocking { gradeStatisticsLocal.saveGradesPointsStatistics(listOf()) }
|
||||||
|
|
||||||
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester(), "Wszystkie") }
|
val stats = runBlocking { gradeStatisticsLocal.getGradesPointsStatistics(getSemester()).first() }
|
||||||
assertEquals(emptyList(), stats)
|
assertEquals(emptyList(), stats)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -41,7 +42,7 @@ class LuckyNumberLocalTest {
|
|||||||
runBlocking { luckyNumberLocal.saveLuckyNumber(number) }
|
runBlocking { luckyNumberLocal.saveLuckyNumber(number) }
|
||||||
|
|
||||||
val student = Student("", "", "", "", "", "", false, "", "", "", 1, 1, "", "", "", "", "", 1, false, now())
|
val student = Student("", "", "", "", "", "", false, "", "", "", 1, 1, "", "", "", "", "", 1, false, now())
|
||||||
val luckyNumber = runBlocking { luckyNumberLocal.getLuckyNumber(student, LocalDate.of(2019, 1, 20)) }
|
val luckyNumber = runBlocking { luckyNumberLocal.getLuckyNumber(student, LocalDate.of(2019, 1, 20)).first() }
|
||||||
|
|
||||||
assertEquals(1, luckyNumber?.studentId)
|
assertEquals(1, luckyNumber?.studentId)
|
||||||
assertEquals(LocalDate.of(2019, 1, 20), luckyNumber?.date)
|
assertEquals(LocalDate.of(2019, 1, 20), luckyNumber?.date)
|
||||||
|
@ -4,6 +4,7 @@ import android.content.Context
|
|||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import io.github.wulkanowy.data.TestDispatchersProvider
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.repositories.getStudent
|
import io.github.wulkanowy.data.repositories.getStudent
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
@ -27,7 +28,7 @@ class StudentLocalTest {
|
|||||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||||
testDb = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
|
testDb = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
|
||||||
.build()
|
.build()
|
||||||
studentLocal = StudentLocal(testDb.studentDao, context)
|
studentLocal = StudentLocal(testDb.studentDao, TestDispatchersProvider(), context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -5,6 +5,7 @@ import androidx.test.core.app.ApplicationProvider
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -48,7 +49,7 @@ class TimetableLocalTest {
|
|||||||
semester = semester,
|
semester = semester,
|
||||||
startDate = LocalDate.of(2018, 9, 10),
|
startDate = LocalDate.of(2018, 9, 10),
|
||||||
endDate = LocalDate.of(2018, 9, 14)
|
endDate = LocalDate.of(2018, 9, 14)
|
||||||
)
|
).first()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(2, exams.size)
|
assertEquals(2, exams.size)
|
||||||
|
@ -5,17 +5,16 @@ import androidx.room.Room
|
|||||||
import androidx.test.core.app.ApplicationProvider.getApplicationContext
|
import androidx.test.core.app.ApplicationProvider.getApplicationContext
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.SdkSuppress
|
import androidx.test.filters.SdkSuppress
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.AppDatabase
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.repositories.getSemester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
import io.github.wulkanowy.data.repositories.getStudent
|
import io.github.wulkanowy.data.repositories.getStudent
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
|
||||||
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
||||||
import io.mockk.MockKAnnotations
|
import io.mockk.MockKAnnotations
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.impl.annotations.MockK
|
import io.mockk.impl.annotations.MockK
|
||||||
import io.mockk.mockk
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -29,45 +28,25 @@ import kotlin.test.assertEquals
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class TimetableRepositoryTest {
|
class TimetableRepositoryTest {
|
||||||
|
|
||||||
@MockK
|
@MockK(relaxed = true)
|
||||||
private lateinit var mockSdk: Sdk
|
|
||||||
|
|
||||||
@MockK
|
|
||||||
private lateinit var studentMock: Student
|
|
||||||
|
|
||||||
private val student = getStudent()
|
|
||||||
|
|
||||||
@MockK
|
|
||||||
private lateinit var semesterMock: Semester
|
|
||||||
|
|
||||||
@MockK
|
|
||||||
private lateinit var timetableNotificationSchedulerHelper: TimetableNotificationSchedulerHelper
|
private lateinit var timetableNotificationSchedulerHelper: TimetableNotificationSchedulerHelper
|
||||||
|
|
||||||
|
@MockK
|
||||||
private lateinit var timetableRemote: TimetableRemote
|
private lateinit var timetableRemote: TimetableRemote
|
||||||
|
|
||||||
private lateinit var timetableLocal: TimetableLocal
|
private lateinit var timetableLocal: TimetableLocal
|
||||||
|
|
||||||
private lateinit var testDb: AppDatabase
|
private lateinit var testDb: AppDatabase
|
||||||
|
|
||||||
|
private val student = getStudent()
|
||||||
|
|
||||||
|
private val semester = getSemester()
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun initApi() {
|
fun initApi() {
|
||||||
MockKAnnotations.init(this)
|
MockKAnnotations.init(this)
|
||||||
testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
|
testDb = Room.inMemoryDatabaseBuilder(getApplicationContext(), AppDatabase::class.java).build()
|
||||||
timetableLocal = TimetableLocal(testDb.timetableDao)
|
timetableLocal = TimetableLocal(testDb.timetableDao)
|
||||||
timetableRemote = TimetableRemote(mockSdk)
|
|
||||||
|
|
||||||
every { timetableNotificationSchedulerHelper.scheduleNotifications(any(), any()) } returns mockk()
|
|
||||||
every { timetableNotificationSchedulerHelper.cancelScheduled(any(), any()) } returns mockk()
|
|
||||||
|
|
||||||
every { studentMock.studentId } returns 1
|
|
||||||
every { studentMock.studentName } returns "Jan Kowalski"
|
|
||||||
|
|
||||||
every { semesterMock.studentId } returns 1
|
|
||||||
every { semesterMock.diaryId } returns 2
|
|
||||||
every { semesterMock.schoolYear } returns 2019
|
|
||||||
every { semesterMock.semesterId } returns 1
|
|
||||||
|
|
||||||
every { mockSdk.switchDiary(any(), any()) } returns mockSdk
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@ -86,21 +65,21 @@ class TimetableRepositoryTest {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
coEvery { mockSdk.getTimetable(any(), any()) } returns listOf(
|
coEvery { timetableRemote.getTimetable(student, semester, any(), any()) } returns listOf(
|
||||||
createTimetableRemote(of(2019, 3, 5, 8, 0), 1, "", "Przyroda"),
|
createTimetableLocal(of(2019, 3, 5, 8, 0), 1, "", "Przyroda"),
|
||||||
createTimetableRemote(of(2019, 3, 5, 8, 50), 2, "", "Religia"),
|
createTimetableLocal(of(2019, 3, 5, 8, 50), 2, "", "Religia"),
|
||||||
createTimetableRemote(of(2019, 3, 5, 9, 40), 3, "", "W-F"),
|
createTimetableLocal(of(2019, 3, 5, 9, 40), 3, "", "W-F"),
|
||||||
createTimetableRemote(of(2019, 3, 5, 10, 30), 4, "", "W-F")
|
createTimetableLocal(of(2019, 3, 5, 10, 30), 4, "", "W-F")
|
||||||
)
|
)
|
||||||
|
|
||||||
val lessons = runBlocking {
|
val lessons = runBlocking {
|
||||||
TimetableRepository(timetableLocal, timetableRemote, timetableNotificationSchedulerHelper).getTimetable(
|
TimetableRepository(timetableLocal, timetableRemote, timetableNotificationSchedulerHelper).getTimetable(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semesterMock,
|
semester = semester,
|
||||||
start = LocalDate.of(2019, 3, 5),
|
start = LocalDate.of(2019, 3, 5),
|
||||||
end = LocalDate.of(2019, 3, 5),
|
end = LocalDate.of(2019, 3, 5),
|
||||||
forceRefresh = true
|
forceRefresh = true
|
||||||
)
|
).filter { it.status == Status.SUCCESS }.first().data.orEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(4, lessons.size)
|
assertEquals(4, lessons.size)
|
||||||
@ -129,31 +108,31 @@ class TimetableRepositoryTest {
|
|||||||
)
|
)
|
||||||
runBlocking { timetableLocal.saveTimetable(list) }
|
runBlocking { timetableLocal.saveTimetable(list) }
|
||||||
|
|
||||||
coEvery { mockSdk.getTimetable(any(), any()) } returns listOf(
|
coEvery { timetableRemote.getTimetable(student, semester, any(), any()) } returns listOf(
|
||||||
createTimetableRemote(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false),
|
createTimetableLocal(of(2019, 12, 23, 8, 0), 1, "123", "Matematyka", "Paweł Poniedziałkowski", false),
|
||||||
createTimetableRemote(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Jakub Wtorkowski", true),
|
createTimetableLocal(of(2019, 12, 23, 8, 50), 2, "124", "Matematyka", "Jakub Wtorkowski", true),
|
||||||
createTimetableRemote(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Poniedziałkowska", false),
|
createTimetableLocal(of(2019, 12, 23, 9, 40), 3, "125", "Język polski", "Joanna Poniedziałkowska", false),
|
||||||
createTimetableRemote(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true),
|
createTimetableLocal(of(2019, 12, 23, 10, 40), 4, "126", "Język polski", "Joanna Wtorkowska", true),
|
||||||
|
|
||||||
createTimetableRemote(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "", false),
|
createTimetableLocal(of(2019, 12, 24, 8, 0), 1, "123", "Język polski", "", false),
|
||||||
createTimetableRemote(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "", true),
|
createTimetableLocal(of(2019, 12, 24, 8, 50), 2, "124", "Język polski", "", true),
|
||||||
createTimetableRemote(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "", false),
|
createTimetableLocal(of(2019, 12, 24, 9, 40), 3, "125", "Język polski", "", false),
|
||||||
createTimetableRemote(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "", true),
|
createTimetableLocal(of(2019, 12, 24, 10, 40), 4, "126", "Język polski", "", true),
|
||||||
|
|
||||||
createTimetableRemote(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "Paweł Środowski", false),
|
createTimetableLocal(of(2019, 12, 25, 8, 0), 1, "123", "Matematyka", "Paweł Środowski", false),
|
||||||
createTimetableRemote(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "Paweł Czwartkowski", true),
|
createTimetableLocal(of(2019, 12, 25, 8, 50), 2, "124", "Matematyka", "Paweł Czwartkowski", true),
|
||||||
createTimetableRemote(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "Paweł Środowski", false),
|
createTimetableLocal(of(2019, 12, 25, 9, 40), 3, "125", "Matematyka", "Paweł Środowski", false),
|
||||||
createTimetableRemote(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "Paweł Czwartkowski", true)
|
createTimetableLocal(of(2019, 12, 25, 10, 40), 4, "126", "Matematyka", "Paweł Czwartkowski", true)
|
||||||
)
|
)
|
||||||
|
|
||||||
val lessons = runBlocking {
|
val lessons = runBlocking {
|
||||||
TimetableRepository(timetableLocal, timetableRemote, timetableNotificationSchedulerHelper).getTimetable(
|
TimetableRepository(timetableLocal, timetableRemote, timetableNotificationSchedulerHelper).getTimetable(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semesterMock,
|
semester = semester,
|
||||||
start = LocalDate.of(2019, 12, 23),
|
start = LocalDate.of(2019, 12, 23),
|
||||||
end = LocalDate.of(2019, 12, 25),
|
end = LocalDate.of(2019, 12, 25),
|
||||||
forceRefresh = true
|
forceRefresh = true
|
||||||
)
|
).filter { it.status == Status.SUCCESS }.first().data.orEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(12, lessons.size)
|
assertEquals(12, lessons.size)
|
||||||
|
@ -18,8 +18,7 @@
|
|||||||
android:supportsRtl="false"
|
android:supportsRtl="false"
|
||||||
android:theme="@style/WulkanowyTheme"
|
android:theme="@style/WulkanowyTheme"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute"
|
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||||
tools:replace="android:supportsRtl,android:allowBackup">
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.modules.splash.SplashActivity"
|
android:name=".ui.modules.splash.SplashActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
|
23
app/src/main/java/io/github/wulkanowy/data/Resource.kt
Normal file
23
app/src/main/java/io/github/wulkanowy/data/Resource.kt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package io.github.wulkanowy.data
|
||||||
|
|
||||||
|
data class Resource<out T>(val status: Status, val data: T?, val error: Throwable?) {
|
||||||
|
companion object {
|
||||||
|
fun <T> success(data: T?): Resource<T> {
|
||||||
|
return Resource(Status.SUCCESS, data, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> error(error: Throwable?, data: T? = null): Resource<T> {
|
||||||
|
return Resource(Status.ERROR, data, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> loading(data: T? = null): Resource<T> {
|
||||||
|
return Resource(Status.LOADING, data, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Status {
|
||||||
|
LOADING,
|
||||||
|
SUCCESS,
|
||||||
|
ERROR
|
||||||
|
}
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
|||||||
interface AttendanceDao : BaseDao<Attendance> {
|
interface AttendanceDao : BaseDao<Attendance> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
suspend fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): List<Attendance>
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Attendance>>
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,11 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface AttendanceSummaryDao : BaseDao<AttendanceSummary> {
|
interface AttendanceSummaryDao : BaseDao<AttendanceSummary> {
|
||||||
|
|
||||||
@Query("SELECT * FROM AttendanceSummary WHERE diary_id = :diaryId AND student_id = :studentId AND subject_id = :subjectId")
|
@Query("SELECT * FROM AttendanceSummary WHERE diary_id = :diaryId AND student_id = :studentId AND subject_id = :subjectId")
|
||||||
suspend fun loadAll(diaryId: Int, studentId: Int, subjectId: Int): List<AttendanceSummary>
|
fun loadAll(diaryId: Int, studentId: Int, subjectId: Int): Flow<List<AttendanceSummary>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
|||||||
interface CompletedLessonsDao : BaseDao<CompletedLesson> {
|
interface CompletedLessonsDao : BaseDao<CompletedLesson> {
|
||||||
|
|
||||||
@Query("SELECT * FROM CompletedLesson WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM CompletedLesson WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
suspend fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): List<CompletedLesson>
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<CompletedLesson>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
|||||||
interface ExamDao : BaseDao<Exam> {
|
interface ExamDao : BaseDao<Exam> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
suspend fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): List<Exam>
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Exam>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -10,5 +11,5 @@ import javax.inject.Singleton
|
|||||||
interface GradeDao : BaseDao<Grade> {
|
interface GradeDao : BaseDao<Grade> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId")
|
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId")
|
||||||
suspend fun loadAll(semesterId: Int, studentId: Int): List<Grade>
|
fun loadAll(semesterId: Int, studentId: Int): Flow<List<Grade>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -10,8 +11,8 @@ import javax.inject.Singleton
|
|||||||
interface GradePointsStatisticsDao : BaseDao<GradePointsStatistics> {
|
interface GradePointsStatisticsDao : BaseDao<GradePointsStatistics> {
|
||||||
|
|
||||||
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName")
|
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName")
|
||||||
suspend fun loadSubject(semesterId: Int, studentId: Int, subjectName: String): List<GradePointsStatistics>
|
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String): Flow<List<GradePointsStatistics>>
|
||||||
|
|
||||||
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
|
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
|
||||||
suspend fun loadAll(semesterId: Int, studentId: Int): List<GradePointsStatistics>
|
fun loadAll(semesterId: Int, studentId: Int): Flow<List<GradePointsStatistics>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -10,8 +11,8 @@ import javax.inject.Singleton
|
|||||||
interface GradeStatisticsDao : BaseDao<GradeStatistics> {
|
interface GradeStatisticsDao : BaseDao<GradeStatistics> {
|
||||||
|
|
||||||
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester")
|
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester")
|
||||||
suspend fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): List<GradeStatistics>
|
fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Flow<List<GradeStatistics>>
|
||||||
|
|
||||||
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND is_semester = :isSemester")
|
@Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND is_semester = :isSemester")
|
||||||
suspend fun loadAll(semesterId: Int, studentId: Int, isSemester: Boolean): List<GradeStatistics>
|
fun loadAll(semesterId: Int, studentId: Int, isSemester: Boolean): Flow<List<GradeStatistics>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -10,5 +11,5 @@ import javax.inject.Singleton
|
|||||||
interface GradeSummaryDao : BaseDao<GradeSummary> {
|
interface GradeSummaryDao : BaseDao<GradeSummary> {
|
||||||
|
|
||||||
@Query("SELECT * FROM GradesSummary WHERE student_id = :studentId AND semester_id = :semesterId")
|
@Query("SELECT * FROM GradesSummary WHERE student_id = :studentId AND semester_id = :semesterId")
|
||||||
suspend fun loadAll(semesterId: Int, studentId: Int): List<GradeSummary>
|
fun loadAll(semesterId: Int, studentId: Int): Flow<List<GradeSummary>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Homework
|
import io.github.wulkanowy.data.db.entities.Homework
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
|||||||
interface HomeworkDao : BaseDao<Homework> {
|
interface HomeworkDao : BaseDao<Homework> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Homework WHERE semester_id = :semesterId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Homework WHERE semester_id = :semesterId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
suspend fun loadAll(semesterId: Int, studentId: Int, from: LocalDate, end: LocalDate): List<Homework>
|
fun loadAll(semesterId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Homework>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
|||||||
interface LuckyNumberDao : BaseDao<LuckyNumber> {
|
interface LuckyNumberDao : BaseDao<LuckyNumber> {
|
||||||
|
|
||||||
@Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date")
|
@Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date")
|
||||||
suspend fun load(studentId: Int, date: LocalDate): LuckyNumber
|
fun load(studentId: Int, date: LocalDate): Flow<LuckyNumber>
|
||||||
}
|
}
|
||||||
|
@ -5,17 +5,18 @@ import androidx.room.Query
|
|||||||
import androidx.room.Transaction
|
import androidx.room.Transaction
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface MessagesDao : BaseDao<Message> {
|
interface MessagesDao : BaseDao<Message> {
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId")
|
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId")
|
||||||
suspend fun loadMessageWithAttachment(studentId: Int, messageId: Int): MessageWithAttachment
|
fun loadMessageWithAttachment(studentId: Int, messageId: Int): Flow<MessageWithAttachment>
|
||||||
|
|
||||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC")
|
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC")
|
||||||
suspend fun loadAll(studentId: Int, folder: Int): List<Message>
|
fun loadAll(studentId: Int, folder: Int): Flow<List<Message>>
|
||||||
|
|
||||||
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND removed = 1 ORDER BY date DESC")
|
@Query("SELECT * FROM Messages WHERE student_id = :studentId AND removed = 1 ORDER BY date DESC")
|
||||||
suspend fun loadDeleted(studentId: Int): List<Message>
|
fun loadDeleted(studentId: Int): Flow<List<Message>>
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,11 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface MobileDeviceDao : BaseDao<MobileDevice> {
|
interface MobileDeviceDao : BaseDao<MobileDevice> {
|
||||||
|
|
||||||
@Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC")
|
@Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC")
|
||||||
suspend fun loadAll(studentId: Int): List<MobileDevice>
|
fun loadAll(studentId: Int): Flow<List<MobileDevice>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Note
|
import io.github.wulkanowy.data.db.entities.Note
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -10,5 +11,5 @@ import javax.inject.Singleton
|
|||||||
interface NoteDao : BaseDao<Note> {
|
interface NoteDao : BaseDao<Note> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Notes WHERE student_id = :studentId")
|
@Query("SELECT * FROM Notes WHERE student_id = :studentId")
|
||||||
suspend fun loadAll(studentId: Int): List<Note>
|
fun loadAll(studentId: Int): Flow<List<Note>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.School
|
import io.github.wulkanowy.data.db.entities.School
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -10,5 +11,5 @@ import javax.inject.Singleton
|
|||||||
interface SchoolDao : BaseDao<School> {
|
interface SchoolDao : BaseDao<School> {
|
||||||
|
|
||||||
@Query("SELECT * FROM School WHERE student_id = :studentId AND class_id = :classId")
|
@Query("SELECT * FROM School WHERE student_id = :studentId AND class_id = :classId")
|
||||||
suspend fun load(studentId: Int, classId: Int): School?
|
fun load(studentId: Int, classId: Int): Flow<School?>
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,11 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Subject
|
import io.github.wulkanowy.data.db.entities.Subject
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface SubjectDao : BaseDao<Subject> {
|
interface SubjectDao : BaseDao<Subject> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Subjects WHERE diary_id = :diaryId AND student_id = :studentId")
|
@Query("SELECT * FROM Subjects WHERE diary_id = :diaryId AND student_id = :studentId")
|
||||||
suspend fun loadAll(diaryId: Int, studentId: Int): List<Subject>
|
fun loadAll(diaryId: Int, studentId: Int): Flow<List<Subject>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Teacher
|
import io.github.wulkanowy.data.db.entities.Teacher
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -10,5 +11,5 @@ import javax.inject.Singleton
|
|||||||
interface TeacherDao : BaseDao<Teacher> {
|
interface TeacherDao : BaseDao<Teacher> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Teachers WHERE student_id = :studentId AND class_id = :classId")
|
@Query("SELECT * FROM Teachers WHERE student_id = :studentId AND class_id = :classId")
|
||||||
suspend fun loadAll(studentId: Int, classId: Int): List<Teacher>
|
fun loadAll(studentId: Int, classId: Int): Flow<List<Teacher>>
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.dao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
|||||||
interface TimetableDao : BaseDao<Timetable> {
|
interface TimetableDao : BaseDao<Timetable> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
suspend fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): List<Timetable>
|
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<Timetable>>
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,10 @@ class AppCreatorRepository @Inject constructor(
|
|||||||
private val dispatchers: DispatchersProvider
|
private val dispatchers: DispatchersProvider
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getAppCreators(): List<Contributor> {
|
suspend fun getAppCreators() = withContext(dispatchers.backgroundThread) {
|
||||||
return withContext(dispatchers.backgroundThread) {
|
|
||||||
Gson().fromJson(
|
Gson().fromJson(
|
||||||
assets.open("contributors.json").bufferedReader().use { it.readText() },
|
assets.open("contributors.json").bufferedReader().use { it.readText() },
|
||||||
Array<Contributor>::class.java
|
Array<Contributor>::class.java
|
||||||
).toList()
|
).toList()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.attendance
|
|||||||
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -18,7 +19,7 @@ class AttendanceLocal @Inject constructor(private val attendanceDb: AttendanceDa
|
|||||||
attendanceDb.deleteAll(attendance)
|
attendanceDb.deleteAll(attendance)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): List<Attendance> {
|
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow<List<Attendance>> {
|
||||||
return attendanceDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
return attendanceDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import io.github.wulkanowy.data.db.entities.Attendance
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.sunday
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
@ -16,19 +17,18 @@ class AttendanceRepository @Inject constructor(
|
|||||||
private val remote: AttendanceRemote
|
private val remote: AttendanceRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean): List<Attendance> {
|
fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getAttendance(semester, start.monday, end.sunday).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getAttendance(student, semester, start.monday, end.sunday)
|
query = { local.getAttendance(semester, start.monday, end.sunday) },
|
||||||
val old = local.getAttendance(semester, start.monday, end.sunday)
|
fetch = { remote.getAttendance(student, semester, start.monday, end.sunday) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
|
local.deleteAttendance(old uniqueSubtract new)
|
||||||
|
local.saveAttendance(new uniqueSubtract old)
|
||||||
|
},
|
||||||
|
filterResult = { it.filter { item -> item.date in start..end } }
|
||||||
|
)
|
||||||
|
|
||||||
local.deleteAttendance(old.uniqueSubtract(new))
|
suspend fun excuseForAbsence(student: Student, semester: Semester, attendanceList: List<Attendance>, reason: String? = null) {
|
||||||
local.saveAttendance(new.uniqueSubtract(old))
|
remote.excuseAbsence(student, semester, attendanceList, reason)
|
||||||
|
|
||||||
local.getAttendance(semester, start.monday, end.sunday)
|
|
||||||
}.filter { it.date in start..end }
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun excuseForAbsence(student: Student, semester: Semester, attendanceList: List<Attendance>, reason: String? = null): Boolean {
|
|
||||||
return remote.excuseAbsence(student, semester, attendanceList, reason)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.attendancesummary
|
|||||||
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
|
||||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ class AttendanceSummaryLocal @Inject constructor(private val attendanceDb: Atten
|
|||||||
attendanceDb.deleteAll(attendance)
|
attendanceDb.deleteAll(attendance)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getAttendanceSummary(semester: Semester, subjectId: Int): List<AttendanceSummary> {
|
fun getAttendanceSummary(semester: Semester, subjectId: Int): Flow<List<AttendanceSummary>> {
|
||||||
return attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId)
|
return attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package io.github.wulkanowy.data.repositories.attendancesummary
|
package io.github.wulkanowy.data.repositories.attendancesummary
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -13,15 +13,13 @@ class AttendanceSummaryRepository @Inject constructor(
|
|||||||
private val remote: AttendanceSummaryRemote
|
private val remote: AttendanceSummaryRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean = false): List<AttendanceSummary> {
|
fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getAttendanceSummary(semester, subjectId).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getAttendanceSummary(student, semester, subjectId)
|
query = { local.getAttendanceSummary(semester, subjectId) },
|
||||||
|
fetch = { remote.getAttendanceSummary(student, semester, subjectId) },
|
||||||
val old = local.getAttendanceSummary(semester, subjectId)
|
saveFetchResult = { old, new ->
|
||||||
local.deleteAttendanceSummary(old.uniqueSubtract(new))
|
local.deleteAttendanceSummary(old uniqueSubtract new)
|
||||||
local.saveAttendanceSummary(new.uniqueSubtract(old))
|
local.saveAttendanceSummary(new uniqueSubtract old)
|
||||||
|
|
||||||
return local.getAttendanceSummary(semester, subjectId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.completedlessons
|
|||||||
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
|
||||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -18,7 +19,7 @@ class CompletedLessonsLocal @Inject constructor(private val completedLessonsDb:
|
|||||||
completedLessonsDb.deleteAll(completedLessons)
|
completedLessonsDb.deleteAll(completedLessons)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCompletedLessons(semester: Semester, start: LocalDate, end: LocalDate): List<CompletedLesson> {
|
fun getCompletedLessons(semester: Semester, start: LocalDate, end: LocalDate): Flow<List<CompletedLesson>> {
|
||||||
return completedLessonsDb.loadAll(semester.diaryId, semester.studentId, start, end)
|
return completedLessonsDb.loadAll(semester.diaryId, semester.studentId, start, end)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package io.github.wulkanowy.data.repositories.completedlessons
|
package io.github.wulkanowy.data.repositories.completedlessons
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.sunday
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
@ -16,15 +16,14 @@ class CompletedLessonsRepository @Inject constructor(
|
|||||||
private val remote: CompletedLessonsRemote
|
private val remote: CompletedLessonsRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): List<CompletedLesson> {
|
fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getCompletedLessons(semester, start.monday, end.sunday).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getCompletedLessons(student, semester, start.monday, end.sunday)
|
query = { local.getCompletedLessons(semester, start.monday, end.sunday) },
|
||||||
val old = local.getCompletedLessons(semester, start.monday, end.sunday)
|
fetch = { remote.getCompletedLessons(student, semester, start.monday, end.sunday) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
local.deleteCompleteLessons(old.uniqueSubtract(new))
|
local.deleteCompleteLessons(old uniqueSubtract new)
|
||||||
local.saveCompletedLessons(new.uniqueSubtract(old))
|
local.saveCompletedLessons(new uniqueSubtract old)
|
||||||
|
},
|
||||||
local.getCompletedLessons(semester, start.monday, end.sunday)
|
filterResult = { it.filter { item -> item.date in start..end } }
|
||||||
}.filter { it.date in start..end }
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.exam
|
|||||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
import io.github.wulkanowy.data.db.dao.ExamDao
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -10,7 +11,7 @@ import javax.inject.Singleton
|
|||||||
@Singleton
|
@Singleton
|
||||||
class ExamLocal @Inject constructor(private val examDb: ExamDao) {
|
class ExamLocal @Inject constructor(private val examDb: ExamDao) {
|
||||||
|
|
||||||
suspend fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): List<Exam> {
|
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow<List<Exam>> {
|
||||||
return examDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
return examDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package io.github.wulkanowy.data.repositories.exam
|
package io.github.wulkanowy.data.repositories.exam
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.sunday
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
@ -16,15 +16,14 @@ class ExamRepository @Inject constructor(
|
|||||||
private val remote: ExamRemote
|
private val remote: ExamRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): List<Exam> {
|
fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getExams(semester, start.monday, end.sunday).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getExams(student, semester, start.monday, end.sunday)
|
query = { local.getExams(semester, start.monday, end.sunday) },
|
||||||
val old = local.getExams(semester, start.monday, end.sunday)
|
fetch = { remote.getExams(student, semester, start.monday, end.sunday) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
local.deleteExams(old.uniqueSubtract(new))
|
local.deleteExams(old uniqueSubtract new)
|
||||||
local.saveExams(new.uniqueSubtract(old))
|
local.saveExams(new uniqueSubtract old)
|
||||||
|
},
|
||||||
local.getExams(semester, start.monday, end.sunday)
|
filterResult = { it.filter { item -> item.date in start..end } }
|
||||||
}.filter { it.date in start..end }
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import io.github.wulkanowy.data.db.dao.GradeSummaryDao
|
|||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ class GradeLocal @Inject constructor(
|
|||||||
gradeSummaryDb.updateAll(gradesSummary)
|
gradeSummaryDb.updateAll(gradesSummary)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGradesDetails(semester: Semester): List<Grade> {
|
fun getGradesDetails(semester: Semester): Flow<List<Grade>> {
|
||||||
return gradeDb.loadAll(semester.semesterId, semester.studentId)
|
return gradeDb.loadAll(semester.semesterId, semester.studentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ class GradeLocal @Inject constructor(
|
|||||||
gradeSummaryDb.deleteAll(gradesSummary)
|
gradeSummaryDb.deleteAll(gradesSummary)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGradesSummary(semester: Semester): List<GradeSummary> {
|
fun getGradesSummary(semester: Semester): Flow<List<GradeSummary>> {
|
||||||
return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)
|
return gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,11 @@ import io.github.wulkanowy.data.db.entities.Grade
|
|||||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import org.threeten.bp.LocalDateTime
|
import org.threeten.bp.LocalDateTime
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -15,30 +19,30 @@ class GradeRepository @Inject constructor(
|
|||||||
private val remote: GradeRemote
|
private val remote: GradeRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean = false, notify: Boolean = false): Pair<List<Grade>, List<GradeSummary>> {
|
fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||||
val details = local.getGradesDetails(semester)
|
shouldFetch = { (details, summaries) -> details.isEmpty() || summaries.isEmpty() || forceRefresh },
|
||||||
val summaries = local.getGradesSummary(semester)
|
query = { local.getGradesDetails(semester).combine(local.getGradesSummary(semester)) { details, summaries -> details to summaries } },
|
||||||
|
fetch = { remote.getGrades(student, semester) },
|
||||||
if ((details.isNotEmpty() || summaries.isNotEmpty()) && !forceRefresh) {
|
saveFetchResult = { old, new ->
|
||||||
return details to summaries
|
refreshGradeDetails(student, old.first, new.first, notify)
|
||||||
|
refreshGradeSummaries(old.second, new.second, notify)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
val (newDetails, newSummary) = remote.getGrades(student, semester)
|
private suspend fun refreshGradeDetails(student: Student, oldGrades: List<Grade>, newDetails: List<Grade>, notify: Boolean) {
|
||||||
val oldGrades = local.getGradesDetails(semester)
|
|
||||||
|
|
||||||
val notifyBreakDate = oldGrades.maxBy { it.date }?.date ?: student.registrationDate.toLocalDate()
|
val notifyBreakDate = oldGrades.maxBy { it.date }?.date ?: student.registrationDate.toLocalDate()
|
||||||
local.deleteGrades(oldGrades.uniqueSubtract(newDetails))
|
local.deleteGrades(oldGrades uniqueSubtract newDetails)
|
||||||
local.saveGrades(newDetails.uniqueSubtract(oldGrades).onEach {
|
local.saveGrades((newDetails uniqueSubtract oldGrades).onEach {
|
||||||
if (it.date >= notifyBreakDate) it.apply {
|
if (it.date >= notifyBreakDate) it.apply {
|
||||||
isRead = false
|
isRead = false
|
||||||
if (notify) isNotified = false
|
if (notify) isNotified = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
val oldSummaries = local.getGradesSummary(semester)
|
private suspend fun refreshGradeSummaries(oldSummaries: List<GradeSummary>, newSummary: List<GradeSummary>, notify: Boolean) {
|
||||||
|
local.deleteGradesSummary(oldSummaries uniqueSubtract newSummary)
|
||||||
local.deleteGradesSummary(oldSummaries.uniqueSubtract(newSummary))
|
local.saveGradesSummary((newSummary uniqueSubtract oldSummaries).onEach { summary ->
|
||||||
local.saveGradesSummary(newSummary.uniqueSubtract(oldSummaries).onEach { summary ->
|
|
||||||
val oldSummary = oldSummaries.find { oldSummary -> oldSummary.subject == summary.subject }
|
val oldSummary = oldSummaries.find { oldSummary -> oldSummary.subject == summary.subject }
|
||||||
summary.isPredictedGradeNotified = when {
|
summary.isPredictedGradeNotified = when {
|
||||||
summary.predictedGrade.isEmpty() -> true
|
summary.predictedGrade.isEmpty() -> true
|
||||||
@ -62,24 +66,22 @@ class GradeRepository @Inject constructor(
|
|||||||
else -> oldSummary.finalGradeLastChange
|
else -> oldSummary.finalGradeLastChange
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return local.getGradesDetails(semester) to local.getGradesSummary(semester)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getUnreadGrades(semester: Semester): List<Grade> {
|
fun getUnreadGrades(semester: Semester): Flow<List<Grade>> {
|
||||||
return local.getGradesDetails(semester).filter { grade -> !grade.isRead }
|
return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isRead } }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getNotNotifiedGrades(semester: Semester): List<Grade> {
|
fun getNotNotifiedGrades(semester: Semester): Flow<List<Grade>> {
|
||||||
return local.getGradesDetails(semester).filter { grade -> !grade.isNotified }
|
return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isNotified } }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getNotNotifiedPredictedGrades(semester: Semester): List<GradeSummary> {
|
fun getNotNotifiedPredictedGrades(semester: Semester): Flow<List<GradeSummary>> {
|
||||||
return local.getGradesSummary(semester).filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified }
|
return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getNotNotifiedFinalGrades(semester: Semester): List<GradeSummary> {
|
fun getNotNotifiedFinalGrades(semester: Semester): Flow<List<GradeSummary>> {
|
||||||
return local.getGradesSummary(semester).filter { gradeSummary -> !gradeSummary.isFinalGradeNotified }
|
return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateGrade(grade: Grade) {
|
suspend fun updateGrade(grade: Grade) {
|
||||||
|
@ -5,6 +5,7 @@ import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
|
|||||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -14,34 +15,14 @@ class GradeStatisticsLocal @Inject constructor(
|
|||||||
private val gradePointsStatisticsDb: GradePointsStatisticsDao
|
private val gradePointsStatisticsDb: GradePointsStatisticsDao
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getGradesStatistics(semester: Semester, isSemester: Boolean): List<GradeStatistics> {
|
fun getGradesStatistics(semester: Semester, isSemester: Boolean): Flow<List<GradeStatistics>> {
|
||||||
return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester)
|
return gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGradesPointsStatistics(semester: Semester): List<GradePointsStatistics> {
|
fun getGradesPointsStatistics(semester: Semester): Flow<List<GradePointsStatistics>> {
|
||||||
return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId)
|
return gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGradesStatistics(semester: Semester, isSemester: Boolean, subjectName: String): List<GradeStatistics> {
|
|
||||||
return when (subjectName) {
|
|
||||||
"Wszystkie" -> {
|
|
||||||
val statistics = gradeStatisticsDb.loadAll(semester.semesterId, semester.studentId, isSemester)
|
|
||||||
statistics.groupBy { it.grade }.map {
|
|
||||||
GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key,
|
|
||||||
it.value.fold(0) { acc, e -> acc + e.amount }, false)
|
|
||||||
} + statistics
|
|
||||||
}
|
|
||||||
else -> gradeStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName, isSemester)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getGradesPointsStatistics(semester: Semester, subjectName: String): List<GradePointsStatistics> {
|
|
||||||
return when (subjectName) {
|
|
||||||
"Wszystkie" -> gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId)
|
|
||||||
else -> gradePointsStatisticsDb.loadSubject(semester.semesterId, semester.studentId, subjectName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) {
|
suspend fun saveGradesStatistics(gradesStatistics: List<GradeStatistics>) {
|
||||||
gradeStatisticsDb.insertAll(gradesStatistics)
|
gradeStatisticsDb.insertAll(gradesStatistics)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.pojos.GradeStatisticsItem
|
import io.github.wulkanowy.data.pojos.GradeStatisticsItem
|
||||||
import io.github.wulkanowy.ui.modules.grade.statistics.ViewType
|
import io.github.wulkanowy.ui.modules.grade.statistics.ViewType
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -16,29 +17,40 @@ class GradeStatisticsRepository @Inject constructor(
|
|||||||
private val remote: GradeStatisticsRemote
|
private val remote: GradeStatisticsRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getGradesStatistics(student: Student, semester: Semester, subjectName: String, isSemester: Boolean, forceRefresh: Boolean = false): List<GradeStatisticsItem> {
|
fun getGradesStatistics(student: Student, semester: Semester, subjectName: String, isSemester: Boolean, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getGradesStatistics(semester, isSemester, subjectName).mapToStatisticItems().filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getGradeStatistics(student, semester, isSemester)
|
query = { local.getGradesStatistics(semester, isSemester) },
|
||||||
val old = local.getGradesStatistics(semester, isSemester)
|
fetch = { remote.getGradeStatistics(student, semester, isSemester) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
local.deleteGradesStatistics(old.uniqueSubtract(new))
|
local.deleteGradesStatistics(old uniqueSubtract new)
|
||||||
local.saveGradesStatistics(new.uniqueSubtract(old))
|
local.saveGradesStatistics(new uniqueSubtract old)
|
||||||
|
},
|
||||||
local.getGradesStatistics(semester, isSemester, subjectName).mapToStatisticItems()
|
mapResult = { items ->
|
||||||
}
|
when (subjectName) {
|
||||||
|
"Wszystkie" -> items.groupBy { it.grade }.map {
|
||||||
|
GradeStatistics(semester.studentId, semester.semesterId, subjectName, it.key,
|
||||||
|
it.value.fold(0) { acc, e -> acc + e.amount }, false)
|
||||||
|
} + items
|
||||||
|
else -> items.filter { it.subject == subjectName }
|
||||||
|
}.mapToStatisticItems()
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean): List<GradeStatisticsItem> {
|
fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getGradesPointsStatistics(semester, subjectName).mapToStatisticsItem().filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getGradePointsStatistics(student, semester)
|
query = { local.getGradesPointsStatistics(semester) },
|
||||||
val old = local.getGradesPointsStatistics(semester)
|
fetch = { remote.getGradePointsStatistics(student, semester) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
local.deleteGradesPointsStatistics(old.uniqueSubtract(new))
|
local.deleteGradesPointsStatistics(old uniqueSubtract new)
|
||||||
local.saveGradesPointsStatistics(new.uniqueSubtract(old))
|
local.saveGradesPointsStatistics(new uniqueSubtract old)
|
||||||
|
},
|
||||||
local.getGradesPointsStatistics(semester, subjectName).mapToStatisticsItem()
|
mapResult = { items ->
|
||||||
}
|
when (subjectName) {
|
||||||
|
"Wszystkie" -> items
|
||||||
|
else -> items.filter { it.subject == subjectName }
|
||||||
|
}.mapToStatisticsItem()
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
private fun List<GradeStatistics>.mapToStatisticItems() = groupBy { it.subject }.map {
|
private fun List<GradeStatistics>.mapToStatisticItems() = groupBy { it.subject }.map {
|
||||||
GradeStatisticsItem(
|
GradeStatisticsItem(
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.homework
|
|||||||
import io.github.wulkanowy.data.db.dao.HomeworkDao
|
import io.github.wulkanowy.data.db.dao.HomeworkDao
|
||||||
import io.github.wulkanowy.data.db.entities.Homework
|
import io.github.wulkanowy.data.db.entities.Homework
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -22,7 +23,7 @@ class HomeworkLocal @Inject constructor(private val homeworkDb: HomeworkDao) {
|
|||||||
homeworkDb.updateAll(homework)
|
homeworkDb.updateAll(homework)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getHomework(semester: Semester, startDate: LocalDate, endDate: LocalDate): List<Homework> {
|
fun getHomework(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow<List<Homework>> {
|
||||||
return homeworkDb.loadAll(semester.semesterId, semester.studentId, startDate, endDate)
|
return homeworkDb.loadAll(semester.semesterId, semester.studentId, startDate, endDate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import io.github.wulkanowy.data.db.entities.Homework
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.sunday
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
@ -16,18 +17,15 @@ class HomeworkRepository @Inject constructor(
|
|||||||
private val remote: HomeworkRemote
|
private val remote: HomeworkRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): List<Homework> {
|
fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getHomework(semester, start.monday, end.sunday).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getHomework(student, semester, start.monday, end.sunday)
|
query = { local.getHomework(semester, start.monday, end.sunday) },
|
||||||
|
fetch = { remote.getHomework(student, semester, start.monday, end.sunday) },
|
||||||
val old = local.getHomework(semester, start.monday, end.sunday)
|
saveFetchResult = { old, new ->
|
||||||
|
local.deleteHomework(old uniqueSubtract new)
|
||||||
local.deleteHomework(old.uniqueSubtract(new))
|
local.saveHomework(new uniqueSubtract old)
|
||||||
local.saveHomework(new.uniqueSubtract(old))
|
|
||||||
|
|
||||||
local.getHomework(semester, start.monday, end.sunday)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun toggleDone(homework: Homework) {
|
suspend fun toggleDone(homework: Homework) {
|
||||||
local.updateHomework(listOf(homework.apply {
|
local.updateHomework(listOf(homework.apply {
|
||||||
|
@ -12,17 +12,13 @@ class LoggerRepository @Inject constructor(
|
|||||||
private val dispatchers: DispatchersProvider
|
private val dispatchers: DispatchersProvider
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getLastLogLines(): List<String> {
|
suspend fun getLastLogLines() = getLastModified().readText().split("\n")
|
||||||
return getLastModified().readText().split("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getLogFiles(): List<File> {
|
suspend fun getLogFiles() = withContext(dispatchers.backgroundThread) {
|
||||||
return withContext(dispatchers.backgroundThread) {
|
|
||||||
File(context.filesDir.absolutePath).listFiles(File::isFile)?.filter {
|
File(context.filesDir.absolutePath).listFiles(File::isFile)?.filter {
|
||||||
it.name.endsWith(".log")
|
it.name.endsWith(".log")
|
||||||
}!!
|
}!!
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun getLastModified(): File {
|
private suspend fun getLastModified(): File {
|
||||||
return withContext(dispatchers.backgroundThread) {
|
return withContext(dispatchers.backgroundThread) {
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.luckynumber
|
|||||||
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
|
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
|
||||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -22,7 +23,7 @@ class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumbe
|
|||||||
luckyNumberDb.deleteAll(listOfNotNull(luckyNumber))
|
luckyNumberDb.deleteAll(listOfNotNull(luckyNumber))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getLuckyNumber(student: Student, date: LocalDate): LuckyNumber? {
|
fun getLuckyNumber(student: Student, date: LocalDate): Flow<LuckyNumber?> {
|
||||||
return luckyNumberDb.load(student.studentId, date)
|
return luckyNumberDb.load(student.studentId, date)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package io.github.wulkanowy.data.repositories.luckynumber
|
|||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate.now
|
import org.threeten.bp.LocalDate.now
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -12,31 +14,25 @@ class LuckyNumberRepository @Inject constructor(
|
|||||||
private val remote: LuckyNumberRemote
|
private val remote: LuckyNumberRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getLuckyNumber(student: Student, forceRefresh: Boolean = false, notify: Boolean = false): LuckyNumber? {
|
fun getLuckyNumber(student: Student, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||||
return local.getLuckyNumber(student, now())?.takeIf { !forceRefresh } ?: run {
|
shouldFetch = { it == null || forceRefresh },
|
||||||
val new = remote.getLuckyNumber(student)
|
query = { local.getLuckyNumber(student, now()) },
|
||||||
val old = local.getLuckyNumber(student, now())
|
fetch = { remote.getLuckyNumber(student) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
if (new != old) {
|
if (new != old) {
|
||||||
old?.let { local.deleteLuckyNumber(it) }
|
old?.let { local.deleteLuckyNumber(it) }
|
||||||
local.saveLuckyNumber(new?.apply {
|
local.saveLuckyNumber(new?.apply {
|
||||||
if (notify) isNotified = false
|
if (notify) isNotified = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
local.saveLuckyNumber(new?.apply {
|
|
||||||
if (notify) isNotified = false
|
|
||||||
})
|
|
||||||
|
|
||||||
local.getLuckyNumber(student, now())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun getNotNotifiedLuckyNumber(student: Student): LuckyNumber? {
|
fun getNotNotifiedLuckyNumber(student: Student): Flow<LuckyNumber?> {
|
||||||
return local.getLuckyNumber(student, now())
|
return local.getLuckyNumber(student, now())
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateLuckyNumber(luckyNumber: LuckyNumber) {
|
suspend fun updateLuckyNumber(luckyNumber: LuckyNumber?) {
|
||||||
local.updateLuckyNumber(luckyNumber)
|
local.updateLuckyNumber(luckyNumber)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import io.github.wulkanowy.data.db.entities.MessageAttachment
|
|||||||
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.message.MessageFolder.TRASHED
|
import io.github.wulkanowy.data.repositories.message.MessageFolder.TRASHED
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ class MessageLocal @Inject constructor(
|
|||||||
messagesDb.deleteAll(messages)
|
messagesDb.deleteAll(messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getMessageWithAttachment(student: Student, message: Message): MessageWithAttachment {
|
fun getMessageWithAttachment(student: Student, message: Message): Flow<MessageWithAttachment> {
|
||||||
return messagesDb.loadMessageWithAttachment(student.id.toInt(), message.messageId)
|
return messagesDb.loadMessageWithAttachment(student.id.toInt(), message.messageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ class MessageLocal @Inject constructor(
|
|||||||
messageAttachmentDao.insertAttachments(attachments)
|
messageAttachmentDao.insertAttachments(attachments)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getMessages(student: Student, folder: MessageFolder): List<Message> {
|
fun getMessages(student: Student, folder: MessageFolder): Flow<List<Message>> {
|
||||||
return when (folder) {
|
return when (folder) {
|
||||||
TRASHED -> messagesDb.loadDeleted(student.id.toInt())
|
TRASHED -> messagesDb.loadDeleted(student.id.toInt())
|
||||||
else -> messagesDb.loadAll(student.id.toInt(), folder.id)
|
else -> messagesDb.loadAll(student.id.toInt(), folder.id)
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
package io.github.wulkanowy.data.repositories.message
|
package io.github.wulkanowy.data.repositories.message
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
|
||||||
import io.github.wulkanowy.data.db.entities.Recipient
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED
|
import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED
|
||||||
import io.github.wulkanowy.sdk.pojo.SentMessage
|
import io.github.wulkanowy.sdk.pojo.SentMessage
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -18,46 +20,37 @@ class MessageRepository @Inject constructor(
|
|||||||
private val remote: MessageRemote
|
private val remote: MessageRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean = false, notify: Boolean = false): List<Message> {
|
fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||||
return local.getMessages(student, folder).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getMessages(student, semester, folder)
|
query = { local.getMessages(student, folder) },
|
||||||
val old = local.getMessages(student, folder)
|
fetch = { remote.getMessages(student, semester, folder) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
local.deleteMessages(old.uniqueSubtract(new))
|
local.deleteMessages(old uniqueSubtract new)
|
||||||
local.saveMessages(new.uniqueSubtract(old).onEach {
|
local.saveMessages((new uniqueSubtract old).onEach {
|
||||||
it.isNotified = !notify
|
it.isNotified = !notify
|
||||||
})
|
})
|
||||||
|
|
||||||
local.getMessages(student, folder)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun getMessage(student: Student, message: Message, markAsRead: Boolean = false): MessageWithAttachment {
|
fun getMessage(student: Student, message: Message, markAsRead: Boolean = false) = networkBoundResource(
|
||||||
return local.getMessageWithAttachment(student, message).let {
|
shouldFetch = {
|
||||||
if (it.message.content.isNotEmpty().also { status ->
|
Timber.d("Message content in db empty: ${it.message.content.isEmpty()}")
|
||||||
Timber.d("Message content in db empty: ${!status}")
|
it.message.unread || it.message.content.isEmpty()
|
||||||
} && !it.message.unread) {
|
},
|
||||||
return@let it
|
query = { local.getMessageWithAttachment(student, message) },
|
||||||
}
|
fetch = { remote.getMessagesContentDetails(student, it.message, markAsRead) },
|
||||||
|
saveFetchResult = { old, (downloadedMessage, attachments) ->
|
||||||
val dbMessage = local.getMessageWithAttachment(student, message)
|
local.updateMessages(listOf(old.message.copy(unread = !markAsRead).apply {
|
||||||
|
id = old.message.id
|
||||||
val (downloadedMessage, attachments) = remote.getMessagesContentDetails(student, dbMessage.message, markAsRead)
|
|
||||||
|
|
||||||
local.updateMessages(listOf(dbMessage.message.copy(unread = !markAsRead).apply {
|
|
||||||
id = dbMessage.message.id
|
|
||||||
content = content.ifBlank { downloadedMessage }
|
content = content.ifBlank { downloadedMessage }
|
||||||
}))
|
}))
|
||||||
local.saveMessageAttachments(attachments)
|
local.saveMessageAttachments(attachments)
|
||||||
Timber.d("Message ${message.messageId} with blank content: ${dbMessage.message.content.isBlank()}, marked as read")
|
Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read")
|
||||||
|
|
||||||
local.getMessageWithAttachment(student, message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun getNotNotifiedMessages(student: Student): List<Message> {
|
fun getNotNotifiedMessages(student: Student): Flow<List<Message>> {
|
||||||
return local.getMessages(student, RECEIVED)
|
return local.getMessages(student, RECEIVED).map { it.filter { message -> !message.isNotified && message.unread } }
|
||||||
.filter { message -> !message.isNotified && message.unread }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateMessages(messages: List<Message>) {
|
suspend fun updateMessages(messages: List<Message>) {
|
||||||
@ -68,15 +61,12 @@ class MessageRepository @Inject constructor(
|
|||||||
return remote.sendMessage(student, subject, content, recipients)
|
return remote.sendMessage(student, subject, content, recipients)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteMessage(student: Student, message: Message): Boolean {
|
suspend fun deleteMessage(student: Student, message: Message) {
|
||||||
val delete = remote.deleteMessage(student, message)
|
val isDeleted = remote.deleteMessage(student, message)
|
||||||
|
|
||||||
if (!message.removed) local.updateMessages(listOf(message.copy(removed = true).apply {
|
if (!message.removed) local.updateMessages(listOf(message.copy(removed = isDeleted).apply {
|
||||||
id = message.id
|
id = message.id
|
||||||
content = message.content
|
content = message.content
|
||||||
}))
|
})) else local.deleteMessages(listOf(message))
|
||||||
else local.deleteMessages(listOf(message))
|
|
||||||
|
|
||||||
return delete // TODO: wtf
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.mobiledevice
|
|||||||
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
|
||||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ class MobileDeviceLocal @Inject constructor(private val mobileDb: MobileDeviceDa
|
|||||||
mobileDb.deleteAll(devices)
|
mobileDb.deleteAll(devices)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getDevices(semester: Semester): List<MobileDevice> {
|
fun getDevices(semester: Semester): Flow<List<MobileDevice>> {
|
||||||
return mobileDb.loadAll(semester.studentId)
|
return mobileDb.loadAll(semester.studentId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import io.github.wulkanowy.data.db.entities.MobileDevice
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -14,20 +15,19 @@ class MobileDeviceRepository @Inject constructor(
|
|||||||
private val remote: MobileDeviceRemote
|
private val remote: MobileDeviceRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean = false): List<MobileDevice> {
|
fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getDevices(semester).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getDevices(student, semester)
|
query = { local.getDevices(semester) },
|
||||||
val old = local.getDevices(semester)
|
fetch = { remote.getDevices(student, semester) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
local.deleteDevices(old uniqueSubtract new)
|
local.deleteDevices(old uniqueSubtract new)
|
||||||
local.saveDevices(new uniqueSubtract old)
|
local.saveDevices(new uniqueSubtract old)
|
||||||
|
|
||||||
local.getDevices(semester)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice): Boolean {
|
suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) {
|
||||||
return remote.unregisterDevice(student, semester, device)
|
remote.unregisterDevice(student, semester, device)
|
||||||
|
local.deleteDevices(listOf(device))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken {
|
suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken {
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.note
|
|||||||
import io.github.wulkanowy.data.db.dao.NoteDao
|
import io.github.wulkanowy.data.db.dao.NoteDao
|
||||||
import io.github.wulkanowy.data.db.entities.Note
|
import io.github.wulkanowy.data.db.entities.Note
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ class NoteLocal @Inject constructor(private val noteDb: NoteDao) {
|
|||||||
noteDb.deleteAll(notes)
|
noteDb.deleteAll(notes)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getNotes(student: Student): List<Note> {
|
fun getNotes(student: Student): Flow<List<Note>> {
|
||||||
return noteDb.loadAll(student.studentId)
|
return noteDb.loadAll(student.studentId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,10 @@ package io.github.wulkanowy.data.repositories.note
|
|||||||
import io.github.wulkanowy.data.db.entities.Note
|
import io.github.wulkanowy.data.db.entities.Note
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -13,29 +16,27 @@ class NoteRepository @Inject constructor(
|
|||||||
private val remote: NoteRemote
|
private val remote: NoteRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean = false, notify: Boolean = false): List<Note> {
|
fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||||
return local.getNotes(student).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getNotes(student, semester)
|
query = { local.getNotes(student) },
|
||||||
val old = local.getNotes(student)
|
fetch = { remote.getNotes(student, semester) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
local.deleteNotes(old.uniqueSubtract(new))
|
local.deleteNotes(old uniqueSubtract new)
|
||||||
local.saveNotes(new.uniqueSubtract(old).onEach {
|
local.saveNotes((new uniqueSubtract old).onEach {
|
||||||
if (it.date >= student.registrationDate.toLocalDate()) it.apply {
|
if (it.date >= student.registrationDate.toLocalDate()) it.apply {
|
||||||
isRead = false
|
isRead = false
|
||||||
if (notify) isNotified = false
|
if (notify) isNotified = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
local.getNotes(student)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun getNotNotifiedNotes(student: Student): List<Note> {
|
fun getNotNotifiedNotes(student: Student): Flow<List<Note>> {
|
||||||
return local.getNotes(student).filter { note -> !note.isNotified }
|
return local.getNotes(student).map { it.filter { note -> !note.isNotified } }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateNote(note: Note) {
|
suspend fun updateNote(note: Note) {
|
||||||
return local.updateNotes(listOf(note))
|
local.updateNotes(listOf(note))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateNotes(notes: List<Note>) {
|
suspend fun updateNotes(notes: List<Note>) {
|
||||||
|
@ -14,13 +14,17 @@ class RecipientRepository @Inject constructor(
|
|||||||
private val remote: RecipientRemote
|
private val remote: RecipientRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getRecipients(student: Student, role: Int, unit: ReportingUnit, forceRefresh: Boolean = false): List<Recipient> {
|
suspend fun refreshRecipients(student: Student, role: Int, unit: ReportingUnit) {
|
||||||
return local.getRecipients(student, role, unit).filter { !forceRefresh }.ifEmpty {
|
|
||||||
val new = remote.getRecipients(student, role, unit)
|
val new = remote.getRecipients(student, role, unit)
|
||||||
val old = local.getRecipients(student, role, unit)
|
val old = local.getRecipients(student, role, unit)
|
||||||
|
|
||||||
local.deleteRecipients(old.uniqueSubtract(new))
|
local.deleteRecipients(old uniqueSubtract new)
|
||||||
local.saveRecipients(new.uniqueSubtract(old))
|
local.saveRecipients(new uniqueSubtract old)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getRecipients(student: Student, role: Int, unit: ReportingUnit): List<Recipient> {
|
||||||
|
return local.getRecipients(student, role, unit).ifEmpty {
|
||||||
|
refreshRecipients(student, role, unit)
|
||||||
|
|
||||||
local.getRecipients(student, role, unit)
|
local.getRecipients(student, role, unit)
|
||||||
}
|
}
|
||||||
|
@ -12,23 +12,27 @@ class ReportingUnitRepository @Inject constructor(
|
|||||||
private val remote: ReportingUnitRemote
|
private val remote: ReportingUnitRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getReportingUnits(student: Student, forceRefresh: Boolean = false): List<ReportingUnit> {
|
suspend fun refreshReportingUnits(student: Student) {
|
||||||
return local.getReportingUnits(student).filter { !forceRefresh }.ifEmpty {
|
|
||||||
val new = remote.getReportingUnits(student)
|
val new = remote.getReportingUnits(student)
|
||||||
val old = local.getReportingUnits(student)
|
val old = local.getReportingUnits(student)
|
||||||
|
|
||||||
local.deleteReportingUnits(old.uniqueSubtract(new))
|
local.deleteReportingUnits(old.uniqueSubtract(new))
|
||||||
local.saveReportingUnits(new.uniqueSubtract(old))
|
local.saveReportingUnits(new.uniqueSubtract(old))
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getReportingUnits(student: Student): List<ReportingUnit> {
|
||||||
|
return local.getReportingUnits(student).ifEmpty {
|
||||||
|
refreshReportingUnits(student)
|
||||||
|
|
||||||
local.getReportingUnits(student)
|
local.getReportingUnits(student)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit {
|
suspend fun getReportingUnit(student: Student, unitId: Int): ReportingUnit? {
|
||||||
return local.getReportingUnit(student, unitId) ?: run {
|
return local.getReportingUnit(student, unitId) ?: run {
|
||||||
getReportingUnits(student, true)
|
refreshReportingUnits(student)
|
||||||
|
|
||||||
return local.getReportingUnit(student, unitId)!!
|
return local.getReportingUnit(student, unitId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.school
|
|||||||
import io.github.wulkanowy.data.db.dao.SchoolDao
|
import io.github.wulkanowy.data.db.dao.SchoolDao
|
||||||
import io.github.wulkanowy.data.db.entities.School
|
import io.github.wulkanowy.data.db.entities.School
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) {
|
class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) {
|
||||||
@ -15,7 +16,7 @@ class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) {
|
|||||||
schoolDb.deleteAll(listOf(school))
|
schoolDb.deleteAll(listOf(school))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getSchool(semester: Semester): School? {
|
fun getSchool(semester: Semester): Flow<School?> {
|
||||||
return schoolDb.load(semester.studentId, semester.classId)
|
return schoolDb.load(semester.studentId, semester.classId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package io.github.wulkanowy.data.repositories.school
|
package io.github.wulkanowy.data.repositories.school
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.School
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -12,18 +12,16 @@ class SchoolRepository @Inject constructor(
|
|||||||
private val remote: SchoolRemote
|
private val remote: SchoolRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean = false): School {
|
fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getSchool(semester).takeIf { it != null && !forceRefresh } ?: run {
|
shouldFetch = { it == null || forceRefresh },
|
||||||
val new = remote.getSchoolInfo(student, semester)
|
query = { local.getSchool(semester) },
|
||||||
val old = local.getSchool(semester)
|
fetch = { remote.getSchoolInfo(student, semester) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
if (new != old && old != null) {
|
if (new != old && old != null) {
|
||||||
local.deleteSchool(old)
|
local.deleteSchool(old)
|
||||||
local.saveSchool(new)
|
local.saveSchool(new)
|
||||||
}
|
}
|
||||||
local.saveSchool(new)
|
local.saveSchool(new)
|
||||||
|
|
||||||
local.getSchool(semester)!!
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
package io.github.wulkanowy.data.repositories.semester
|
package io.github.wulkanowy.data.repositories.semester
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
|
import io.github.wulkanowy.utils.DispatchersProvider
|
||||||
import io.github.wulkanowy.utils.getCurrentOrLast
|
import io.github.wulkanowy.utils.getCurrentOrLast
|
||||||
import io.github.wulkanowy.utils.isCurrent
|
import io.github.wulkanowy.utils.isCurrent
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class SemesterRepository @Inject constructor(
|
class SemesterRepository @Inject constructor(
|
||||||
private val remote: SemesterRemote,
|
private val remote: SemesterRemote,
|
||||||
private val local: SemesterLocal
|
private val local: SemesterLocal,
|
||||||
|
private val dispatchers: DispatchersProvider
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getSemesters(student: Student, forceRefresh: Boolean = false, refreshOnNoCurrent: Boolean = false): List<Semester> {
|
suspend fun getSemesters(student: Student, forceRefresh: Boolean = false, refreshOnNoCurrent: Boolean = false) = withContext(dispatchers.backgroundThread) {
|
||||||
return local.getSemesters(student).let { semesters ->
|
local.getSemesters(student).let { semesters ->
|
||||||
semesters.filter {
|
semesters.filter {
|
||||||
!forceRefresh && when {
|
!forceRefresh && when {
|
||||||
Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API -> semesters.firstOrNull { it.isCurrent }?.diaryId != 0
|
Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API -> semesters.firstOrNull { it.isCurrent }?.diaryId != 0
|
||||||
@ -36,7 +38,7 @@ class SemesterRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCurrentSemester(student: Student, forceRefresh: Boolean = false): Semester {
|
suspend fun getCurrentSemester(student: Student, forceRefresh: Boolean = false) = withContext(dispatchers.backgroundThread) {
|
||||||
return getSemesters(student, forceRefresh).getCurrentOrLast()
|
getSemesters(student, forceRefresh).getCurrentOrLast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,52 +4,55 @@ import android.content.Context
|
|||||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
|
import io.github.wulkanowy.utils.DispatchersProvider
|
||||||
import io.github.wulkanowy.utils.security.decrypt
|
import io.github.wulkanowy.utils.security.decrypt
|
||||||
import io.github.wulkanowy.utils.security.encrypt
|
import io.github.wulkanowy.utils.security.encrypt
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class StudentLocal @Inject constructor(
|
class StudentLocal @Inject constructor(
|
||||||
private val studentDb: StudentDao,
|
private val studentDb: StudentDao,
|
||||||
|
private val dispatchers: DispatchersProvider,
|
||||||
private val context: Context
|
private val context: Context
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun saveStudents(students: List<Student>): List<Long> {
|
suspend fun saveStudents(students: List<Student>) = withContext(dispatchers.backgroundThread) {
|
||||||
return studentDb.insertAll(students.map {
|
studentDb.insertAll(students.map {
|
||||||
if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) it.copy(password = encrypt(it.password, context))
|
if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) it.copy(password = encrypt(it.password, context))
|
||||||
else it
|
else it
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getStudents(decryptPass: Boolean): List<Student> {
|
suspend fun getStudents(decryptPass: Boolean) = withContext(dispatchers.backgroundThread) {
|
||||||
return studentDb.loadAll().map {
|
studentDb.loadAll().map {
|
||||||
it.apply {
|
it.apply {
|
||||||
if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
|
if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getStudentById(id: Int): Student? {
|
suspend fun getStudentById(id: Int) = withContext(dispatchers.backgroundThread) {
|
||||||
return studentDb.loadById(id)?.apply {
|
studentDb.loadById(id)?.apply {
|
||||||
if (Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
|
if (Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCurrentStudent(decryptPass: Boolean): Student? {
|
suspend fun getCurrentStudent(decryptPass: Boolean) = withContext(dispatchers.backgroundThread) {
|
||||||
return studentDb.loadCurrent()?.apply {
|
studentDb.loadCurrent()?.apply {
|
||||||
if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
|
if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun setCurrentStudent(student: Student) {
|
suspend fun setCurrentStudent(student: Student) = withContext(dispatchers.backgroundThread) {
|
||||||
return studentDb.run {
|
studentDb.run {
|
||||||
resetCurrent()
|
resetCurrent()
|
||||||
updateCurrent(student.id)
|
updateCurrent(student.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun logoutStudent(student: Student) {
|
suspend fun logoutStudent(student: Student) = withContext(dispatchers.backgroundThread) {
|
||||||
return studentDb.delete(student)
|
studentDb.delete(student)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,14 @@ package io.github.wulkanowy.data.repositories.subject
|
|||||||
import io.github.wulkanowy.data.db.dao.SubjectDao
|
import io.github.wulkanowy.data.db.dao.SubjectDao
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Subject
|
import io.github.wulkanowy.data.db.entities.Subject
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class SubjectLocal @Inject constructor(private val subjectDao: SubjectDao) {
|
class SubjectLocal @Inject constructor(private val subjectDao: SubjectDao) {
|
||||||
|
|
||||||
suspend fun getSubjects(semester: Semester): List<Subject> {
|
fun getSubjects(semester: Semester): Flow<List<Subject>> {
|
||||||
return subjectDao.loadAll(semester.diaryId, semester.studentId)
|
return subjectDao.loadAll(semester.diaryId, semester.studentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package io.github.wulkanowy.data.repositories.subject
|
|||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.Subject
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -13,15 +13,13 @@ class SubjectRepository @Inject constructor(
|
|||||||
private val remote: SubjectRemote
|
private val remote: SubjectRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false): List<Subject> {
|
fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false) = networkBoundResource(
|
||||||
return local.getSubjects(semester).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getSubjects(student, semester)
|
query = { local.getSubjects(semester) },
|
||||||
val old = local.getSubjects(semester)
|
fetch = { remote.getSubjects(student, semester) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
local.deleteSubjects(old.uniqueSubtract(new))
|
local.deleteSubjects(old uniqueSubtract new)
|
||||||
local.saveSubjects(new.uniqueSubtract(old))
|
local.saveSubjects(new uniqueSubtract old)
|
||||||
|
|
||||||
local.getSubjects(semester)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.teacher
|
|||||||
import io.github.wulkanowy.data.db.dao.TeacherDao
|
import io.github.wulkanowy.data.db.dao.TeacherDao
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Teacher
|
import io.github.wulkanowy.data.db.entities.Teacher
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) {
|
class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) {
|
||||||
@ -15,7 +16,7 @@ class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) {
|
|||||||
teacherDb.deleteAll(teachers)
|
teacherDb.deleteAll(teachers)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getTeachers(semester: Semester): List<Teacher> {
|
fun getTeachers(semester: Semester): Flow<List<Teacher>> {
|
||||||
return teacherDb.loadAll(semester.studentId, semester.classId)
|
return teacherDb.loadAll(semester.studentId, semester.classId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package io.github.wulkanowy.data.repositories.teacher
|
|||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.Teacher
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -13,15 +13,13 @@ class TeacherRepository @Inject constructor(
|
|||||||
private val remote: TeacherRemote
|
private val remote: TeacherRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean = false): List<Teacher> {
|
fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getTeachers(semester).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getTeachers(student, semester)
|
query = { local.getTeachers(semester) },
|
||||||
val old = local.getTeachers(semester)
|
fetch = { remote.getTeachers(student, semester) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
local.deleteTeachers(old.uniqueSubtract(new))
|
local.deleteTeachers(old uniqueSubtract new)
|
||||||
local.saveTeachers(new.uniqueSubtract(old))
|
local.saveTeachers(new uniqueSubtract old)
|
||||||
|
|
||||||
local.getTeachers(semester)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.repositories.timetable
|
|||||||
import io.github.wulkanowy.data.db.dao.TimetableDao
|
import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -18,7 +19,7 @@ class TimetableLocal @Inject constructor(private val timetableDb: TimetableDao)
|
|||||||
timetableDb.deleteAll(timetables)
|
timetableDb.deleteAll(timetables)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getTimetable(semester: Semester, startDate: LocalDate, endDate: LocalDate): List<Timetable> {
|
fun getTimetable(semester: Semester, startDate: LocalDate, endDate: LocalDate): Flow<List<Timetable>> {
|
||||||
return timetableDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
return timetableDb.loadAll(semester.diaryId, semester.studentId, startDate, endDate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,12 @@ package io.github.wulkanowy.data.repositories.timetable
|
|||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
|
||||||
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import io.github.wulkanowy.utils.sunday
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
import io.github.wulkanowy.utils.uniqueSubtract
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -18,11 +19,11 @@ class TimetableRepository @Inject constructor(
|
|||||||
private val schedulerHelper: TimetableNotificationSchedulerHelper
|
private val schedulerHelper: TimetableNotificationSchedulerHelper
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): List<Timetable> {
|
fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||||
return local.getTimetable(semester, start.monday, start.sunday).filter { !forceRefresh }.ifEmpty {
|
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||||
val new = remote.getTimetable(student, semester, start.monday, start.sunday)
|
query = { local.getTimetable(semester, start.monday, end.sunday).map { schedulerHelper.scheduleNotifications(it, student); it } },
|
||||||
val old = local.getTimetable(semester, start.monday, start.sunday)
|
fetch = { remote.getTimetable(student, semester, start.monday, end.sunday) },
|
||||||
|
saveFetchResult = { old, new ->
|
||||||
local.deleteTimetable(old.uniqueSubtract(new).also { schedulerHelper.cancelScheduled(it) })
|
local.deleteTimetable(old.uniqueSubtract(new).also { schedulerHelper.cancelScheduled(it) })
|
||||||
local.saveTimetable(new.uniqueSubtract(old).also { schedulerHelper.scheduleNotifications(it, student) }.map { item ->
|
local.saveTimetable(new.uniqueSubtract(old).also { schedulerHelper.scheduleNotifications(it, student) }.map { item ->
|
||||||
item.also { new ->
|
item.also { new ->
|
||||||
@ -34,8 +35,7 @@ class TimetableRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
local.getTimetable(semester, start.monday, start.sunday)
|
filterResult = { it.filter { item -> item.date in start..end } }
|
||||||
}.filter { it.date in start..end }.also { schedulerHelper.scheduleNotifications(it, student) }
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ class AttendanceSummaryWork @Inject constructor(
|
|||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxCompletable { attendanceSummaryRepository.getAttendanceSummary(student, semester, -1, true) }
|
return rxCompletable { attendanceSummaryRepository.getAttendanceSummary(student, semester, -1, true).waitForResult() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
|
import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
|
||||||
import io.github.wulkanowy.utils.sunday
|
|
||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import kotlinx.coroutines.rx2.rxCompletable
|
||||||
import org.threeten.bp.LocalDate.now
|
import org.threeten.bp.LocalDate.now
|
||||||
@ -13,6 +13,6 @@ import javax.inject.Inject
|
|||||||
class AttendanceWork @Inject constructor(private val attendanceRepository: AttendanceRepository) : Work {
|
class AttendanceWork @Inject constructor(private val attendanceRepository: AttendanceRepository) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxCompletable { attendanceRepository.getAttendance(student, semester, now().monday, now().sunday, true) }
|
return rxCompletable { attendanceRepository.getAttendance(student, semester, now().monday, now().sunday, true).waitForResult() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.completedlessons.CompletedLessonsRepository
|
import io.github.wulkanowy.data.repositories.completedlessons.CompletedLessonsRepository
|
||||||
import io.github.wulkanowy.utils.sunday
|
|
||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import kotlinx.coroutines.rx2.rxCompletable
|
||||||
import org.threeten.bp.LocalDate.now
|
import org.threeten.bp.LocalDate.now
|
||||||
@ -15,7 +15,6 @@ class CompletedLessonWork @Inject constructor(
|
|||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxCompletable { completedLessonsRepository.getCompletedLessons(student, semester, now().monday, now().sunday, true) }
|
return rxCompletable { completedLessonsRepository.getCompletedLessons(student, semester, now().monday, now().sunday, true).waitForResult() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,6 @@ import javax.inject.Inject
|
|||||||
class ExamWork @Inject constructor(private val examRepository: ExamRepository) : Work {
|
class ExamWork @Inject constructor(private val examRepository: ExamRepository) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxCompletable { examRepository.getExams(student, semester, now().monday, now().sunday, true) }
|
return rxCompletable { examRepository.getExams(student, semester, now().monday, now().sunday, true).waitForResult() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,17 @@ import io.reactivex.Completable
|
|||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import kotlinx.coroutines.rx2.rxCompletable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class GradeStatisticsWork @Inject constructor(private val gradeStatisticsRepository: GradeStatisticsRepository) : Work {
|
class GradeStatisticsWork @Inject constructor(
|
||||||
|
private val gradeStatisticsRepository: GradeStatisticsRepository
|
||||||
|
) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxCompletable { gradeStatisticsRepository.getGradesStatistics(student, semester, "Wszystkie", false, forceRefresh = true) }
|
return rxCompletable {
|
||||||
|
with(gradeStatisticsRepository) {
|
||||||
|
getGradesStatistics(student, semester, "Wszystkie", isSemester = true, forceRefresh = true).waitForResult()
|
||||||
|
getGradesStatistics(student, semester, "Wszystkie", isSemester = false, forceRefresh = true).waitForResult()
|
||||||
|
getGradesPointsStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
|||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.utils.getCompatColor
|
import io.github.wulkanowy.utils.getCompatColor
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import kotlinx.coroutines.rx2.rxCompletable
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import kotlinx.coroutines.rx2.rxSingle
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -32,14 +33,14 @@ class GradeWork @Inject constructor(
|
|||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxCompletable { gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable) }
|
return rxCompletable { gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable).waitForResult() }
|
||||||
.concatWith(Completable.concatArray(rxSingle { gradeRepository.getNotNotifiedGrades(semester) }.flatMapCompletable {
|
.concatWith(Completable.concatArray(rxSingle { gradeRepository.getNotNotifiedGrades(semester).first() }.flatMapCompletable {
|
||||||
if (it.isNotEmpty()) notifyDetails(it)
|
if (it.isNotEmpty()) notifyDetails(it)
|
||||||
rxCompletable { gradeRepository.updateGrades(it.onEach { grade -> grade.isNotified = true }) }
|
rxCompletable { gradeRepository.updateGrades(it.onEach { grade -> grade.isNotified = true }) }
|
||||||
}, rxSingle { gradeRepository.getNotNotifiedPredictedGrades(semester) }.flatMapCompletable {
|
}, rxSingle { gradeRepository.getNotNotifiedPredictedGrades(semester).first() }.flatMapCompletable {
|
||||||
if (it.isNotEmpty()) notifyPredicted(it)
|
if (it.isNotEmpty()) notifyPredicted(it)
|
||||||
rxCompletable { gradeRepository.updateGradesSummary(it.onEach { grade -> grade.isPredictedGradeNotified = true }) }
|
rxCompletable { gradeRepository.updateGradesSummary(it.onEach { grade -> grade.isPredictedGradeNotified = true }) }
|
||||||
}, rxSingle { gradeRepository.getNotNotifiedFinalGrades(semester) }.flatMapCompletable {
|
}, rxSingle { gradeRepository.getNotNotifiedFinalGrades(semester).first() }.flatMapCompletable {
|
||||||
if (it.isNotEmpty()) notifyFinal(it)
|
if (it.isNotEmpty()) notifyFinal(it)
|
||||||
rxCompletable { gradeRepository.updateGradesSummary(it.onEach { grade -> grade.isFinalGradeNotified = true }) }
|
rxCompletable { gradeRepository.updateGradesSummary(it.onEach { grade -> grade.isFinalGradeNotified = true }) }
|
||||||
}))
|
}))
|
||||||
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.homework.HomeworkRepository
|
import io.github.wulkanowy.data.repositories.homework.HomeworkRepository
|
||||||
import io.github.wulkanowy.utils.sunday
|
|
||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import kotlinx.coroutines.rx2.rxCompletable
|
||||||
import org.threeten.bp.LocalDate.now
|
import org.threeten.bp.LocalDate.now
|
||||||
@ -13,6 +13,6 @@ import javax.inject.Inject
|
|||||||
class HomeworkWork @Inject constructor(private val homeworkRepository: HomeworkRepository) : Work {
|
class HomeworkWork @Inject constructor(private val homeworkRepository: HomeworkRepository) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxCompletable { homeworkRepository.getHomework(student, semester, now().monday, now().sunday, true) }
|
return rxCompletable { homeworkRepository.getHomework(student, semester, now().monday, now().sunday, true).waitForResult() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
|||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.utils.getCompatColor
|
import io.github.wulkanowy.utils.getCompatColor
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import kotlinx.coroutines.rx2.rxCompletable
|
||||||
import kotlinx.coroutines.rx2.rxMaybe
|
import kotlinx.coroutines.rx2.rxMaybe
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -31,8 +32,8 @@ class LuckyNumberWork @Inject constructor(
|
|||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxMaybe { luckyNumberRepository.getLuckyNumber(student, true, preferencesRepository.isNotificationsEnable) }
|
return rxMaybe { luckyNumberRepository.getLuckyNumber(student, true, preferencesRepository.isNotificationsEnable).waitForResult() }
|
||||||
.flatMap { rxMaybe { luckyNumberRepository.getNotNotifiedLuckyNumber(student) } }
|
.flatMap { rxMaybe { luckyNumberRepository.getNotNotifiedLuckyNumber(student).first() } }
|
||||||
.flatMapCompletable {
|
.flatMapCompletable {
|
||||||
notify(it)
|
notify(it)
|
||||||
rxCompletable { luckyNumberRepository.updateLuckyNumber(it.apply { isNotified = true }) }
|
rxCompletable { luckyNumberRepository.updateLuckyNumber(it.apply { isNotified = true }) }
|
||||||
|
@ -19,6 +19,7 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
|||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.utils.getCompatColor
|
import io.github.wulkanowy.utils.getCompatColor
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import kotlinx.coroutines.rx2.rxCompletable
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import kotlinx.coroutines.rx2.rxSingle
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -32,8 +33,8 @@ class MessageWork @Inject constructor(
|
|||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxSingle { messageRepository.getMessages(student, semester, RECEIVED, true, preferencesRepository.isNotificationsEnable) }
|
return rxSingle { messageRepository.getMessages(student, semester, RECEIVED, true, preferencesRepository.isNotificationsEnable).waitForResult() }
|
||||||
.flatMap { rxSingle { messageRepository.getNotNotifiedMessages(student) } }
|
.flatMap { rxSingle { messageRepository.getNotNotifiedMessages(student).first() } }
|
||||||
.flatMapCompletable {
|
.flatMapCompletable {
|
||||||
if (it.isNotEmpty()) notify(it)
|
if (it.isNotEmpty()) notify(it)
|
||||||
rxCompletable { messageRepository.updateMessages(it.onEach { message -> message.isNotified = true }) }
|
rxCompletable { messageRepository.updateMessages(it.onEach { message -> message.isNotified = true }) }
|
||||||
|
@ -18,6 +18,7 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
|||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.utils.getCompatColor
|
import io.github.wulkanowy.utils.getCompatColor
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import kotlinx.coroutines.rx2.rxCompletable
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import kotlinx.coroutines.rx2.rxSingle
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -31,8 +32,8 @@ class NoteWork @Inject constructor(
|
|||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxSingle { noteRepository.getNotes(student, semester, true, preferencesRepository.isNotificationsEnable) }
|
return rxSingle { noteRepository.getNotes(student, semester, true, preferencesRepository.isNotificationsEnable).waitForResult() }
|
||||||
.flatMap { rxSingle { noteRepository.getNotNotifiedNotes(student) } }
|
.flatMap { rxSingle { noteRepository.getNotNotifiedNotes(student).first() } }
|
||||||
.flatMapCompletable {
|
.flatMapCompletable {
|
||||||
if (it.isNotEmpty()) notify(it)
|
if (it.isNotEmpty()) notify(it)
|
||||||
rxCompletable { noteRepository.updateNotes(it.onEach { note -> note.isNotified = true }) }
|
rxCompletable { noteRepository.updateNotes(it.onEach { note -> note.isNotified = true }) }
|
||||||
|
@ -15,10 +15,11 @@ class RecipientWork @Inject constructor(
|
|||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxSingle { reportingUnitRepository.getReportingUnits(student, true) }
|
return rxSingle { reportingUnitRepository.refreshReportingUnits(student) }
|
||||||
|
.flatMap { rxSingle { reportingUnitRepository.getReportingUnits(student) } }
|
||||||
.flatMapCompletable { units ->
|
.flatMapCompletable { units ->
|
||||||
Completable.mergeDelayError(units.map {
|
Completable.mergeDelayError(units.map {
|
||||||
rxCompletable { recipientRepository.getRecipients(student, 2, it, true) }
|
rxCompletable { recipientRepository.refreshRecipients(student, 2, it) }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,6 @@ import javax.inject.Inject
|
|||||||
class TeacherWork @Inject constructor(private val teacherRepository: TeacherRepository) : Work {
|
class TeacherWork @Inject constructor(private val teacherRepository: TeacherRepository) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxCompletable { teacherRepository.getTeachers(student, semester, true) }
|
return rxCompletable { teacherRepository.getTeachers(student, semester, true).waitForResult() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,6 @@ import javax.inject.Inject
|
|||||||
class TimetableWork @Inject constructor(private val timetableRepository: TimetableRepository) : Work {
|
class TimetableWork @Inject constructor(private val timetableRepository: TimetableRepository) : Work {
|
||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return rxCompletable { timetableRepository.getTimetable(student, semester, now().monday, now().sunday, true) }
|
return rxCompletable { timetableRepository.getTimetable(student, semester, now().monday, now().sunday, true).waitForResult() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,19 @@
|
|||||||
package io.github.wulkanowy.services.sync.works
|
package io.github.wulkanowy.services.sync.works
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Resource
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
|
import kotlinx.coroutines.flow.takeWhile
|
||||||
|
|
||||||
interface Work {
|
interface Work {
|
||||||
|
|
||||||
fun create(student: Student, semester: Semester): Completable
|
fun create(student: Student, semester: Semester): Completable
|
||||||
}
|
|
||||||
|
|
||||||
|
suspend fun <T> Flow<Resource<T>>.waitForResult() = takeWhile {
|
||||||
|
it.status == Status.LOADING
|
||||||
|
}.collect()
|
||||||
|
}
|
||||||
|
@ -1,24 +1,39 @@
|
|||||||
package io.github.wulkanowy.ui.base
|
package io.github.wulkanowy.ui.base
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import io.reactivex.Completable
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
open class BasePresenter<T : BaseView>(
|
open class BasePresenter<T : BaseView>(
|
||||||
protected val errorHandler: ErrorHandler,
|
protected val errorHandler: ErrorHandler,
|
||||||
protected val studentRepository: StudentRepository,
|
protected val studentRepository: StudentRepository,
|
||||||
protected val schedulers: SchedulersProvider
|
protected val schedulers: SchedulersProvider
|
||||||
) {
|
) : CoroutineScope {
|
||||||
|
|
||||||
|
private var job: Job = Job()
|
||||||
|
|
||||||
|
private val jobs = mutableMapOf<String, Job>()
|
||||||
|
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = Dispatchers.Main + job
|
||||||
|
|
||||||
|
@Deprecated("Use flow instead :)")
|
||||||
val disposable = CompositeDisposable()
|
val disposable = CompositeDisposable()
|
||||||
|
|
||||||
var view: T? = null
|
var view: T? = null
|
||||||
|
|
||||||
open fun onAttachView(view: T) {
|
open fun onAttachView(view: T) {
|
||||||
|
job = Job()
|
||||||
this.view = view
|
this.view = view
|
||||||
errorHandler.apply {
|
errorHandler.apply {
|
||||||
showErrorMessage = view::showError
|
showErrorMessage = view::showError
|
||||||
@ -28,30 +43,48 @@ open class BasePresenter<T : BaseView>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onExpiredLoginSelected() {
|
fun onExpiredLoginSelected() {
|
||||||
Timber.i("Attempt to switch the student after the session expires")
|
flowWithResource {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent(false) }
|
val student = studentRepository.getCurrentStudent(false)
|
||||||
.flatMapCompletable { rxCompletable { studentRepository.logoutStudent(it) } }
|
studentRepository.logoutStudent(student)
|
||||||
.andThen(rxSingle { studentRepository.getSavedStudents(false) })
|
|
||||||
.flatMapCompletable {
|
val students = studentRepository.getSavedStudents(false)
|
||||||
if (it.isNotEmpty()) {
|
if (students.isNotEmpty()) {
|
||||||
Timber.i("Switching current student")
|
Timber.i("Switching current student")
|
||||||
rxCompletable { studentRepository.switchStudent(it[0]) }
|
studentRepository.switchStudent(students[0])
|
||||||
} else Completable.complete()
|
|
||||||
}
|
}
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
}.onEach {
|
||||||
.observeOn(schedulers.mainThread)
|
when (it.status) {
|
||||||
.subscribe({
|
Status.LOADING -> Timber.i("Attempt to switch the student after the session expires")
|
||||||
|
Status.SUCCESS -> {
|
||||||
Timber.i("Switch student result: Open login view")
|
Timber.i("Switch student result: Open login view")
|
||||||
view?.openClearLoginView()
|
view?.openClearLoginView()
|
||||||
}, {
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
Timber.i("Switch student result: An exception occurred")
|
Timber.i("Switch student result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it.error!!)
|
||||||
}))
|
}
|
||||||
|
}
|
||||||
|
}.launch("expired")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Flow<T>.launch(individualJobTag: String = "load"): Job {
|
||||||
|
jobs[individualJobTag]?.cancel()
|
||||||
|
val job = launchIn(this@BasePresenter)
|
||||||
|
jobs[individualJobTag] = job
|
||||||
|
Timber.d("Job $individualJobTag launched in ${this@BasePresenter.javaClass.simpleName}: $job")
|
||||||
|
return job
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cancelJobs(vararg names: String) {
|
||||||
|
names.forEach {
|
||||||
|
jobs[it]?.cancel()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun onDetachView() {
|
open fun onDetachView() {
|
||||||
view = null
|
view = null
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
|
job.cancel()
|
||||||
errorHandler.clear()
|
errorHandler.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,10 @@ open class ErrorHandler @Inject constructor(protected val resources: Resources,
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun proceed(error: Throwable) {
|
protected open fun proceed(error: Throwable) {
|
||||||
|
showErrorMessage(resources.getString(error), error)
|
||||||
when (error) {
|
when (error) {
|
||||||
is ScramblerException, is BadCredentialsException -> onSessionExpired()
|
is ScramblerException, is BadCredentialsException -> onSessionExpired()
|
||||||
is NoCurrentStudentException -> onNoCurrentStudent()
|
is NoCurrentStudentException -> onNoCurrentStudent()
|
||||||
else -> showErrorMessage(resources.getString(error), error)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package io.github.wulkanowy.ui.modules.about.contributor
|
package io.github.wulkanowy.ui.modules.about.contributor
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.pojos.Contributor
|
import io.github.wulkanowy.data.pojos.Contributor
|
||||||
import io.github.wulkanowy.data.repositories.appcreator.AppCreatorRepository
|
import io.github.wulkanowy.data.repositories.appcreator.AppCreatorRepository
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ContributorPresenter @Inject constructor(
|
class ContributorPresenter @Inject constructor(
|
||||||
@ -31,10 +33,15 @@ class ContributorPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadData() {
|
private fun loadData() {
|
||||||
disposable.add(rxSingle { appCreatorRepository.getAppCreators() }
|
flowWithResource { appCreatorRepository.getAppCreators() }.onEach {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
when (it.status) {
|
||||||
.observeOn(schedulers.mainThread)
|
Status.LOADING -> view?.showProgress(true)
|
||||||
.doFinally { view?.showProgress(false) }
|
Status.SUCCESS -> view?.run {
|
||||||
.subscribe({ view?.run { updateData(it) } }, { errorHandler.dispatch(it) }))
|
showProgress(false)
|
||||||
|
updateData(it.data!!)
|
||||||
|
}
|
||||||
|
Status.ERROR -> errorHandler.dispatch(it.error!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ class LicenseAdapter @Inject constructor() : RecyclerView.Adapter<LicenseAdapter
|
|||||||
|
|
||||||
with(holder.binding) {
|
with(holder.binding) {
|
||||||
licenseItemName.text = item.libraryName
|
licenseItemName.text = item.libraryName
|
||||||
licenseItemSummary.text = item.license?.licenseName?.takeIf { it.isNotBlank() } ?: item.libraryVersion
|
licenseItemSummary.text = item.licenses?.firstOrNull()?.licenseName?.takeIf { it.isNotBlank() } ?: item.libraryVersion
|
||||||
|
|
||||||
root.setOnClickListener { onClickListener(item) }
|
root.setOnClickListener { onClickListener(item) }
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,22 @@
|
|||||||
package io.github.wulkanowy.ui.modules.about.license
|
package io.github.wulkanowy.ui.modules.about.license
|
||||||
|
|
||||||
import com.mikepenz.aboutlibraries.entity.Library
|
import com.mikepenz.aboutlibraries.entity.Library
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
|
import io.github.wulkanowy.utils.DispatchersProvider
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import io.reactivex.Single
|
import io.github.wulkanowy.utils.afterLoading
|
||||||
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LicensePresenter @Inject constructor(
|
class LicensePresenter @Inject constructor(
|
||||||
schedulers: SchedulersProvider,
|
schedulers: SchedulersProvider,
|
||||||
|
private val dispatchers: DispatchersProvider,
|
||||||
errorHandler: ErrorHandler,
|
errorHandler: ErrorHandler,
|
||||||
studentRepository: StudentRepository
|
studentRepository: StudentRepository
|
||||||
) : BasePresenter<LicenseView>(errorHandler, studentRepository, schedulers) {
|
) : BasePresenter<LicenseView>(errorHandler, studentRepository, schedulers) {
|
||||||
@ -21,14 +28,22 @@ class LicensePresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onItemSelected(library: Library) {
|
fun onItemSelected(library: Library) {
|
||||||
view?.run { library.license?.licenseDescription?.let { openLicense(it) } }
|
view?.run { library.licenses?.firstOrNull()?.licenseDescription?.let { openLicense(it) } }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadData() {
|
private fun loadData() {
|
||||||
disposable.add(Single.fromCallable { view?.appLibraries.orEmpty() }
|
flowWithResource {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
withContext(dispatchers.backgroundThread) {
|
||||||
.observeOn(schedulers.mainThread)
|
view?.appLibraries.orEmpty()
|
||||||
.doOnEvent { _, _ -> view?.showProgress(false) }
|
}
|
||||||
.subscribe({ view?.run { updateData(it) } }, { errorHandler.dispatch(it) }))
|
}.onEach {
|
||||||
|
when (it.status) {
|
||||||
|
Status.LOADING -> Timber.d("License data load started")
|
||||||
|
Status.SUCCESS -> view?.updateData(it.data!!)
|
||||||
|
Status.ERROR -> errorHandler.dispatch(it.error!!)
|
||||||
|
}
|
||||||
|
}.afterLoading {
|
||||||
|
view?.showProgress(false)
|
||||||
|
}.launch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package io.github.wulkanowy.ui.modules.about.logviewer
|
package io.github.wulkanowy.ui.modules.about.logviewer
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.repositories.logger.LoggerRepository
|
import io.github.wulkanowy.data.repositories.logger.LoggerRepository
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -23,16 +25,19 @@ class LogViewerPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onShareLogsSelected(): Boolean {
|
fun onShareLogsSelected(): Boolean {
|
||||||
disposable.add(rxSingle { loggerRepository.getLogFiles() }
|
flowWithResource { loggerRepository.getLogFiles() }.onEach {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
when (it.status) {
|
||||||
.observeOn(schedulers.mainThread)
|
Status.LOADING -> Timber.d("Loading logs files started")
|
||||||
.subscribe({ files ->
|
Status.SUCCESS -> {
|
||||||
Timber.i("Loading logs files result: ${files.joinToString { it.name }}")
|
Timber.i("Loading logs files result: ${it.data!!.joinToString { file -> file.name }}")
|
||||||
view?.shareLogs(files)
|
view?.shareLogs(it.data)
|
||||||
}, {
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
Timber.i("Loading logs files result: An exception occurred")
|
Timber.i("Loading logs files result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it.error!!)
|
||||||
}))
|
}
|
||||||
|
}
|
||||||
|
}.launch("share")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,15 +46,18 @@ class LogViewerPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadLogFile() {
|
private fun loadLogFile() {
|
||||||
disposable.add(rxSingle { loggerRepository.getLastLogLines() }
|
flowWithResource { loggerRepository.getLastLogLines() }.onEach {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
when (it.status) {
|
||||||
.observeOn(schedulers.mainThread)
|
Status.LOADING -> Timber.d("Loading last log file started")
|
||||||
.subscribe({
|
Status.SUCCESS -> {
|
||||||
Timber.i("Loading last log file result: load ${it.size} lines")
|
Timber.i("Loading last log file result: load ${it.data!!.size} lines")
|
||||||
view?.setLines(it)
|
view?.setLines(it.data)
|
||||||
}, {
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
Timber.i("Loading last log file result: An exception occurred")
|
Timber.i("Loading last log file result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it.error!!)
|
||||||
}))
|
}
|
||||||
|
}
|
||||||
|
}.launch("file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
package io.github.wulkanowy.ui.modules.account
|
package io.github.wulkanowy.ui.modules.account
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.services.sync.SyncManager
|
import io.github.wulkanowy.services.sync.SyncManager
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import io.reactivex.Single
|
import io.github.wulkanowy.utils.afterLoading
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -37,20 +38,20 @@ class AccountPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onLogoutConfirm() {
|
fun onLogoutConfirm() {
|
||||||
Timber.i("Attempt to logout current user ")
|
flowWithResource {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent(false) }
|
val student = studentRepository.getCurrentStudent(false)
|
||||||
.flatMapCompletable { rxCompletable { studentRepository.logoutStudent(it) } }
|
studentRepository.logoutStudent(student)
|
||||||
.andThen(rxSingle { studentRepository.getSavedStudents(false) })
|
|
||||||
.flatMap {
|
val students = studentRepository.getSavedStudents(false)
|
||||||
if (it.isNotEmpty()) rxCompletable { studentRepository.switchStudent(it[0]) }.toSingle { it }
|
if (students.isNotEmpty()) {
|
||||||
else Single.just(it)
|
studentRepository.switchStudent(students[0])
|
||||||
}
|
}
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
students
|
||||||
.observeOn(schedulers.mainThread)
|
}.onEach {
|
||||||
.doFinally { view?.dismissView() }
|
when (it.status) {
|
||||||
.subscribe({
|
Status.LOADING -> Timber.i("Attempt to logout current user ")
|
||||||
view?.apply {
|
Status.SUCCESS -> view?.run {
|
||||||
if (it.isEmpty()) {
|
if (it.data!!.isEmpty()) {
|
||||||
Timber.i("Logout result: Open login view")
|
Timber.i("Logout result: Open login view")
|
||||||
syncManager.stopSyncWorker()
|
syncManager.stopSyncWorker()
|
||||||
openClearLoginView()
|
openClearLoginView()
|
||||||
@ -59,30 +60,35 @@ class AccountPresenter @Inject constructor(
|
|||||||
recreateMainView()
|
recreateMainView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
Status.ERROR -> {
|
||||||
Timber.i("Logout result: An exception occurred")
|
Timber.i("Logout result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it.error!!)
|
||||||
}))
|
}
|
||||||
|
}
|
||||||
|
}.afterLoading {
|
||||||
|
view?.dismissView()
|
||||||
|
}.launch("logout")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onItemSelected(student: Student) {
|
fun onItemSelected(student: Student) {
|
||||||
Timber.i("Select student item ${student.id}")
|
Timber.i("Select student item ${student.id}")
|
||||||
if (student.isCurrent) {
|
if (student.isCurrent) {
|
||||||
view?.dismissView()
|
view?.dismissView()
|
||||||
} else {
|
} else flowWithResource { studentRepository.switchStudent(student) }.onEach {
|
||||||
Timber.i("Attempt to change a student")
|
when (it.status) {
|
||||||
disposable.add(rxSingle { studentRepository.switchStudent(student) }
|
Status.LOADING -> Timber.i("Attempt to change a student")
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
Status.SUCCESS -> {
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doFinally { view?.dismissView() }
|
|
||||||
.subscribe({
|
|
||||||
Timber.i("Change a student result: Success")
|
Timber.i("Change a student result: Success")
|
||||||
view?.recreateMainView()
|
view?.recreateMainView()
|
||||||
}, {
|
|
||||||
Timber.i("Change a student result: An exception occurred")
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
|
Timber.i("Change a student result: An exception occurred")
|
||||||
|
errorHandler.dispatch(it.error!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.afterLoading {
|
||||||
|
view?.dismissView()
|
||||||
|
}.launch("switch")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createAccountItems(items: List<Student>): List<AccountItem<*>> {
|
private fun createAccountItems(items: List<Student>): List<AccountItem<*>> {
|
||||||
@ -94,17 +100,18 @@ class AccountPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadData() {
|
private fun loadData() {
|
||||||
Timber.i("Loading account data started")
|
flowWithResource { studentRepository.getSavedStudents(false) }.onEach {
|
||||||
disposable.add(rxSingle { studentRepository.getSavedStudents(false) }
|
when (it.status) {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
Status.LOADING -> Timber.i("Loading account data started")
|
||||||
.observeOn(schedulers.mainThread)
|
Status.SUCCESS -> {
|
||||||
.map { createAccountItems(it) }
|
|
||||||
.subscribe({
|
|
||||||
Timber.i("Loading account result: Success")
|
Timber.i("Loading account result: Success")
|
||||||
view?.updateData(it)
|
view?.updateData(createAccountItems(it.data!!))
|
||||||
}, {
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
Timber.i("Loading account result: An exception occurred")
|
Timber.i("Loading account result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it.error!!)
|
||||||
}))
|
}
|
||||||
|
}
|
||||||
|
}.launch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.github.wulkanowy.ui.modules.attendance
|
package io.github.wulkanowy.ui.modules.attendance
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
|
import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
|
||||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||||
@ -10,13 +11,18 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
|||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
|
import io.github.wulkanowy.utils.afterLoading
|
||||||
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
|
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||||
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
|
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
|
||||||
import io.github.wulkanowy.utils.isHolidays
|
import io.github.wulkanowy.utils.isHolidays
|
||||||
import io.github.wulkanowy.utils.nextSchoolDay
|
import io.github.wulkanowy.utils.nextSchoolDay
|
||||||
import io.github.wulkanowy.utils.previousOrSameSchoolDay
|
import io.github.wulkanowy.utils.previousOrSameSchoolDay
|
||||||
import io.github.wulkanowy.utils.previousSchoolDay
|
import io.github.wulkanowy.utils.previousSchoolDay
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import kotlinx.coroutines.flow.catch
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import org.threeten.bp.LocalDate.now
|
import org.threeten.bp.LocalDate.now
|
||||||
import org.threeten.bp.LocalDate.ofEpochDay
|
import org.threeten.bp.LocalDate.ofEpochDay
|
||||||
@ -168,101 +174,94 @@ class AttendancePresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setBaseDateOnHolidays() {
|
private fun setBaseDateOnHolidays() {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
flow {
|
||||||
.flatMap { rxSingle { semesterRepository.getCurrentSemester(it) } }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
emit(semesterRepository.getCurrentSemester(student))
|
||||||
.observeOn(schedulers.mainThread)
|
}.catch {
|
||||||
.subscribe({
|
Timber.i("Loading semester result: An exception occurred")
|
||||||
|
}.onEach {
|
||||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
||||||
currentDate = baseDate
|
currentDate = baseDate
|
||||||
reloadNavigation()
|
reloadNavigation()
|
||||||
}) {
|
}.launch("holidays")
|
||||||
Timber.i("Loading semester result: An exception occurred")
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||||
Timber.i("Loading attendance data started")
|
Timber.i("Loading attendance data started")
|
||||||
currentDate = date
|
currentDate = date
|
||||||
disposable.apply {
|
|
||||||
clear()
|
flowWithResourceIn {
|
||||||
add(rxSingle { studentRepository.getCurrentStudent() }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.flatMap { student ->
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
attendanceRepository.getAttendance(student, semester, date, date, forceRefresh)
|
||||||
rxSingle { attendanceRepository.getAttendance(student, semester, date, date, forceRefresh) }
|
}.onEach {
|
||||||
|
when (it.status) {
|
||||||
|
Status.LOADING -> view?.showExcuseButton(false)
|
||||||
|
Status.SUCCESS -> {
|
||||||
|
Timber.i("Loading attendance result: Success")
|
||||||
|
view?.apply {
|
||||||
|
updateData(it.data!!.let { items ->
|
||||||
|
if (prefRepository.isShowPresent) items
|
||||||
|
else items.filter { item -> !item.presence }
|
||||||
|
}.sortedBy { item -> item.number })
|
||||||
|
showEmpty(it.data.isEmpty())
|
||||||
|
showErrorView(false)
|
||||||
|
showContent(it.data.isNotEmpty())
|
||||||
|
showExcuseButton(it.data.any { item -> item.excusable })
|
||||||
|
}
|
||||||
|
analytics.logEvent(
|
||||||
|
"load_data",
|
||||||
|
"type" to "attendance",
|
||||||
|
"items" to it.data!!.size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
|
Timber.i("Loading attendance result: An exception occurred")
|
||||||
|
errorHandler.dispatch(it.error!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map { list ->
|
}.afterLoading {
|
||||||
if (prefRepository.isShowPresent) list
|
|
||||||
else list.filter { !it.presence }
|
|
||||||
}
|
|
||||||
.map { items -> items.sortedBy { it.number } }
|
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doFinally {
|
|
||||||
view?.run {
|
view?.run {
|
||||||
hideRefresh()
|
hideRefresh()
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
}
|
}
|
||||||
}
|
}.launch()
|
||||||
.subscribe({
|
|
||||||
Timber.i("Loading attendance result: Success")
|
|
||||||
view?.apply {
|
|
||||||
updateData(it)
|
|
||||||
showEmpty(it.isEmpty())
|
|
||||||
showErrorView(false)
|
|
||||||
showContent(it.isNotEmpty())
|
|
||||||
showExcuseButton(it.any { item -> item.excusable })
|
|
||||||
}
|
|
||||||
analytics.logEvent(
|
|
||||||
"load_data",
|
|
||||||
"type" to "attendance",
|
|
||||||
"items" to it.size,
|
|
||||||
"force_refresh" to forceRefresh
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
Timber.i("Loading attendance result: An exception occurred")
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun excuseAbsence(reason: String?, toExcuseList: List<Attendance>) {
|
private fun excuseAbsence(reason: String?, toExcuseList: List<Attendance>) {
|
||||||
|
flowWithResource {
|
||||||
|
val student = studentRepository.getCurrentStudent()
|
||||||
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
|
attendanceRepository.excuseForAbsence(student, semester, toExcuseList, reason)
|
||||||
|
}.onEach {
|
||||||
|
when (it.status) {
|
||||||
|
Status.LOADING -> view?.run {
|
||||||
Timber.i("Excusing absence started")
|
Timber.i("Excusing absence started")
|
||||||
disposable.apply {
|
|
||||||
add(rxSingle { studentRepository.getCurrentStudent() }
|
|
||||||
.flatMap { student ->
|
|
||||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
|
||||||
rxSingle { attendanceRepository.excuseForAbsence(student, semester, toExcuseList, reason) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doOnSubscribe {
|
|
||||||
view?.apply {
|
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
showContent(false)
|
showContent(false)
|
||||||
showExcuseButton(false)
|
showExcuseButton(false)
|
||||||
}
|
}
|
||||||
}
|
Status.SUCCESS -> {
|
||||||
.subscribe({
|
|
||||||
Timber.i("Excusing for absence result: Success")
|
Timber.i("Excusing for absence result: Success")
|
||||||
analytics.logEvent("excuse_absence", "items" to attendanceToExcuseList.size)
|
analytics.logEvent("excuse_absence", "items" to attendanceToExcuseList.size)
|
||||||
attendanceToExcuseList.clear()
|
attendanceToExcuseList.clear()
|
||||||
view?.apply {
|
view?.run {
|
||||||
showExcuseButton(false)
|
showExcuseButton(false)
|
||||||
showMessage(excuseSuccessString)
|
showMessage(excuseSuccessString)
|
||||||
|
showContent(true)
|
||||||
|
showProgress(false)
|
||||||
}
|
}
|
||||||
loadData(currentDate, true)
|
loadData(currentDate, forceRefresh = true)
|
||||||
}) {
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
Timber.i("Excusing for absence result: An exception occurred")
|
Timber.i("Excusing for absence result: An exception occurred")
|
||||||
view?.showProgress(false)
|
errorHandler.dispatch(it.error!!)
|
||||||
errorHandler.dispatch(it)
|
loadData(currentDate)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}.launch("excuse")
|
||||||
|
}
|
||||||
|
|
||||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
view?.run {
|
view?.run {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.wulkanowy.ui.modules.attendance.summary
|
package io.github.wulkanowy.ui.modules.attendance.summary
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.Subject
|
import io.github.wulkanowy.data.db.entities.Subject
|
||||||
import io.github.wulkanowy.data.repositories.attendancesummary.AttendanceSummaryRepository
|
import io.github.wulkanowy.data.repositories.attendancesummary.AttendanceSummaryRepository
|
||||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||||
@ -9,7 +10,9 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
|||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import io.github.wulkanowy.utils.afterLoading
|
||||||
|
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.threeten.bp.Month
|
import org.threeten.bp.Month
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -73,46 +76,43 @@ class AttendanceSummaryPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadData(subjectId: Int, forceRefresh: Boolean = false) {
|
private fun loadData(subjectId: Int, forceRefresh: Boolean = false) {
|
||||||
Timber.i("Loading attendance summary data started")
|
|
||||||
currentSubjectId = subjectId
|
currentSubjectId = subjectId
|
||||||
disposable.apply {
|
|
||||||
clear()
|
flowWithResourceIn {
|
||||||
add(rxSingle { studentRepository.getCurrentStudent() }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.flatMap { student ->
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap {
|
attendanceSummaryRepository.getAttendanceSummary(student, semester, subjectId, forceRefresh)
|
||||||
rxSingle { attendanceSummaryRepository.getAttendanceSummary(student, it, subjectId, forceRefresh) }
|
}.onEach {
|
||||||
|
when (it.status) {
|
||||||
|
Status.LOADING -> Timber.i("Loading attendance summary data started")
|
||||||
|
Status.SUCCESS -> {
|
||||||
|
Timber.i("Loading attendance summary result: Success")
|
||||||
|
view?.apply {
|
||||||
|
showEmpty(it.data!!.isEmpty())
|
||||||
|
showContent(it.data.isNotEmpty())
|
||||||
|
updateDataSet(it.data.sortedByDescending { item ->
|
||||||
|
if (item.month.value <= Month.JUNE.value) item.month.value + 12 else item.month.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
analytics.logEvent(
|
||||||
|
"load_data",
|
||||||
|
"type" to "attendance_summary",
|
||||||
|
"items" to it.data!!.size,
|
||||||
|
"item_id" to subjectId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
|
Timber.i("Loading attendance summary result: An exception occurred")
|
||||||
|
errorHandler.dispatch(it.error!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map { items -> items.sortedByDescending { if (it.month.value <= Month.JUNE.value) it.month.value + 12 else it.month.value } }
|
}.afterLoading {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doFinally {
|
|
||||||
view?.run {
|
view?.run {
|
||||||
hideRefresh()
|
hideRefresh()
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
}
|
}
|
||||||
}
|
}.launch()
|
||||||
.subscribe({
|
|
||||||
Timber.i("Loading attendance summary result: Success")
|
|
||||||
view?.apply {
|
|
||||||
showEmpty(it.isEmpty())
|
|
||||||
showContent(it.isNotEmpty())
|
|
||||||
updateDataSet(it)
|
|
||||||
}
|
|
||||||
analytics.logEvent(
|
|
||||||
"load_data",
|
|
||||||
"type" to "attendance_summary",
|
|
||||||
"items" to it.size,
|
|
||||||
"force_refresh" to forceRefresh,
|
|
||||||
"item_id" to subjectId
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
Timber.i("Loading attendance summary result: An exception occurred")
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
@ -127,27 +127,27 @@ class AttendanceSummaryPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadSubjects() {
|
private fun loadSubjects() {
|
||||||
Timber.i("Loading attendance summary subjects started")
|
flowWithResourceIn {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.flatMap { student ->
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
subjectRepository.getSubjects(student, semester)
|
||||||
rxSingle { subjectRepository.getSubjects(student, semester) }
|
}.onEach {
|
||||||
}
|
when (it.status) {
|
||||||
}
|
Status.LOADING -> Timber.i("Loading attendance summary subjects started")
|
||||||
.doOnSuccess { subjects = it }
|
Status.SUCCESS -> {
|
||||||
.map { ArrayList(it.map { subject -> subject.name }) }
|
subjects = it.data!!
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.subscribe({
|
|
||||||
Timber.i("Loading attendance summary subjects result: Success")
|
Timber.i("Loading attendance summary subjects result: Success")
|
||||||
view?.run {
|
view?.run {
|
||||||
view?.updateSubjects(it)
|
view?.updateSubjects(ArrayList(it.data.map { subject -> subject.name }))
|
||||||
showSubjects(true)
|
showSubjects(true)
|
||||||
}
|
}
|
||||||
}, {
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
Timber.i("Loading attendance summary subjects result: An exception occurred")
|
Timber.i("Loading attendance summary subjects result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it.error!!)
|
||||||
})
|
}
|
||||||
)
|
}
|
||||||
|
}.launch("subjects")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.wulkanowy.ui.modules.exam
|
package io.github.wulkanowy.ui.modules.exam
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.data.repositories.exam.ExamRepository
|
import io.github.wulkanowy.data.repositories.exam.ExamRepository
|
||||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||||
@ -8,13 +9,17 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
|||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import io.github.wulkanowy.utils.sunday
|
import io.github.wulkanowy.utils.afterLoading
|
||||||
|
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||||
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
|
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
|
||||||
import io.github.wulkanowy.utils.isHolidays
|
import io.github.wulkanowy.utils.isHolidays
|
||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||||
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import kotlinx.coroutines.flow.catch
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import org.threeten.bp.LocalDate.now
|
import org.threeten.bp.LocalDate.now
|
||||||
import org.threeten.bp.LocalDate.ofEpochDay
|
import org.threeten.bp.LocalDate.ofEpochDay
|
||||||
@ -90,59 +95,54 @@ class ExamPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setBaseDateOnHolidays() {
|
private fun setBaseDateOnHolidays() {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
flow {
|
||||||
.flatMap { rxSingle { semesterRepository.getCurrentSemester(it) } }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
emit(semesterRepository.getCurrentSemester(student))
|
||||||
.observeOn(schedulers.mainThread)
|
}.catch {
|
||||||
.subscribe({
|
Timber.i("Loading semester result: An exception occurred")
|
||||||
|
}.onEach {
|
||||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
||||||
currentDate = baseDate
|
currentDate = baseDate
|
||||||
reloadNavigation()
|
reloadNavigation()
|
||||||
}) {
|
}.launch("holidays")
|
||||||
Timber.i("Loading semester result: An exception occurred")
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||||
Timber.i("Loading exam data started")
|
|
||||||
currentDate = date
|
currentDate = date
|
||||||
disposable.apply {
|
|
||||||
clear()
|
flowWithResourceIn {
|
||||||
add(rxSingle { studentRepository.getCurrentStudent() }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.flatMap { student ->
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
examRepository.getExams(student, semester, currentDate.monday, currentDate.sunday, forceRefresh)
|
||||||
rxSingle { examRepository.getExams(student, semester, currentDate.monday, currentDate.sunday, forceRefresh) }
|
}.onEach {
|
||||||
|
when (it.status) {
|
||||||
|
Status.LOADING -> Timber.i("Loading exam data started")
|
||||||
|
Status.SUCCESS -> {
|
||||||
|
Timber.i("Loading exam result: Success")
|
||||||
|
view?.apply {
|
||||||
|
updateData(createExamItems(it.data!!))
|
||||||
|
showEmpty(it.data.isEmpty())
|
||||||
|
showErrorView(false)
|
||||||
|
showContent(it.data.isNotEmpty())
|
||||||
|
}
|
||||||
|
analytics.logEvent(
|
||||||
|
"load_data",
|
||||||
|
"type" to "exam",
|
||||||
|
"items" to it.data!!.size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
|
Timber.i("Loading exam result: An exception occurred")
|
||||||
|
errorHandler.dispatch(it.error!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map { createExamItems(it) }
|
}.afterLoading {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doFinally {
|
|
||||||
view?.run {
|
view?.run {
|
||||||
hideRefresh()
|
hideRefresh()
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
}
|
}
|
||||||
}
|
}.launch()
|
||||||
.subscribe({
|
|
||||||
Timber.i("Loading exam result: Success")
|
|
||||||
view?.apply {
|
|
||||||
updateData(it)
|
|
||||||
showEmpty(it.isEmpty())
|
|
||||||
showErrorView(false)
|
|
||||||
showContent(it.isNotEmpty())
|
|
||||||
}
|
|
||||||
analytics.logEvent(
|
|
||||||
"load_data",
|
|
||||||
"type" to "exam",
|
|
||||||
"items" to it.size,
|
|
||||||
"force_refresh" to forceRefresh
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
Timber.i("Loading exam result: An exception occurred")
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package io.github.wulkanowy.ui.modules.grade
|
package io.github.wulkanowy.ui.modules.grade
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Resource
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
@ -13,8 +15,17 @@ import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.BOTH_SEMESTERS
|
|||||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.ONE_SEMESTER
|
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode.ONE_SEMESTER
|
||||||
import io.github.wulkanowy.utils.calcAverage
|
import io.github.wulkanowy.utils.calcAverage
|
||||||
import io.github.wulkanowy.utils.changeModifier
|
import io.github.wulkanowy.utils.changeModifier
|
||||||
|
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||||
|
import kotlinx.coroutines.FlowPreview
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.flow.flatMapConcat
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@OptIn(FlowPreview::class)
|
||||||
class GradeAverageProvider @Inject constructor(
|
class GradeAverageProvider @Inject constructor(
|
||||||
private val semesterRepository: SemesterRepository,
|
private val semesterRepository: SemesterRepository,
|
||||||
private val gradeRepository: GradeRepository,
|
private val gradeRepository: GradeRepository,
|
||||||
@ -25,63 +36,64 @@ class GradeAverageProvider @Inject constructor(
|
|||||||
|
|
||||||
private val minusModifier get() = preferencesRepository.gradeMinusModifier
|
private val minusModifier get() = preferencesRepository.gradeMinusModifier
|
||||||
|
|
||||||
suspend fun getGradesDetailsWithAverage(student: Student, semesterId: Int, forceRefresh: Boolean = false): List<GradeDetailsWithAverage> {
|
fun getGradesDetailsWithAverage(student: Student, semesterId: Int, forceRefresh: Boolean) = flowWithResourceIn {
|
||||||
return semesterRepository.getSemesters(student).let { semesters ->
|
val semesters = semesterRepository.getSemesters(student)
|
||||||
|
|
||||||
when (preferencesRepository.gradeAverageMode) {
|
when (preferencesRepository.gradeAverageMode) {
|
||||||
ONE_SEMESTER -> getSemesterDetailsWithAverage(student, semesters.single { it.semesterId == semesterId }, forceRefresh)
|
ONE_SEMESTER -> getSemesterDetailsWithAverage(student, semesters.single { it.semesterId == semesterId }, forceRefresh)
|
||||||
BOTH_SEMESTERS -> calculateBothSemestersAverage(student, semesters, semesterId, forceRefresh)
|
BOTH_SEMESTERS -> calculateBothSemestersAverage(student, semesters, semesterId, forceRefresh)
|
||||||
ALL_YEAR -> calculateAllYearAverage(student, semesters, semesterId, forceRefresh)
|
ALL_YEAR -> calculateAllYearAverage(student, semesters, semesterId, forceRefresh)
|
||||||
}
|
}
|
||||||
}
|
}.distinctUntilChanged()
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun calculateBothSemestersAverage(student: Student, semesters: List<Semester>, semesterId: Int, forceRefresh: Boolean): List<GradeDetailsWithAverage> {
|
private fun calculateBothSemestersAverage(student: Student, semesters: List<Semester>, semesterId: Int, forceRefresh: Boolean): Flow<Resource<List<GradeDetailsWithAverage>>> {
|
||||||
val selectedSemester = semesters.single { it.semesterId == semesterId }
|
val selectedSemester = semesters.single { it.semesterId == semesterId }
|
||||||
val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 }
|
val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 }
|
||||||
|
|
||||||
return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).let { selectedDetails ->
|
return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).flatMapConcat { selectedDetails ->
|
||||||
val isAnyAverage = selectedDetails.any { it.average != .0 }
|
val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 }
|
||||||
|
|
||||||
if (selectedSemester != firstSemester) {
|
if (selectedSemester != firstSemester) {
|
||||||
getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).let { secondDetails ->
|
getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).map { secondDetails ->
|
||||||
selectedDetails.map { selected ->
|
secondDetails.copy(data = selectedDetails.data?.map { selected ->
|
||||||
val second = secondDetails.singleOrNull { it.subject == selected.subject }
|
val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject }
|
||||||
selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) {
|
selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) {
|
||||||
val selectedGrades = selected.grades.updateModifiers(student).calcAverage()
|
val selectedGrades = selected.grades.updateModifiers(student).calcAverage()
|
||||||
(selectedGrades + (second?.grades?.updateModifiers(student)?.calcAverage() ?: selectedGrades)) / 2
|
(selectedGrades + (second?.grades?.updateModifiers(student)?.calcAverage() ?: selectedGrades)) / 2
|
||||||
} else (selected.average + (second?.average ?: selected.average)) / 2)
|
} else (selected.average + (second?.average ?: selected.average)) / 2)
|
||||||
}
|
})
|
||||||
}
|
}.filter { it.status != Status.LOADING }.filter { it.data != null }
|
||||||
} else selectedDetails
|
} else flowOf(selectedDetails)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun calculateAllYearAverage(student: Student, semesters: List<Semester>, semesterId: Int, forceRefresh: Boolean): List<GradeDetailsWithAverage> {
|
private fun calculateAllYearAverage(student: Student, semesters: List<Semester>, semesterId: Int, forceRefresh: Boolean): Flow<Resource<List<GradeDetailsWithAverage>>> {
|
||||||
val selectedSemester = semesters.single { it.semesterId == semesterId }
|
val selectedSemester = semesters.single { it.semesterId == semesterId }
|
||||||
val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 }
|
val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 }
|
||||||
|
|
||||||
return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).let { selectedDetails ->
|
return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).flatMapConcat { selectedDetails ->
|
||||||
val isAnyAverage = selectedDetails.any { it.average != .0 }
|
val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 }
|
||||||
|
|
||||||
if (selectedSemester != firstSemester) {
|
if (selectedSemester != firstSemester) {
|
||||||
getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).let { secondDetails ->
|
getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).map { secondDetails ->
|
||||||
selectedDetails.map { selected ->
|
secondDetails.copy(data = selectedDetails.data?.map { selected ->
|
||||||
val second = secondDetails.singleOrNull { it.subject == selected.subject }
|
val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject }
|
||||||
selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) {
|
selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) {
|
||||||
(selected.grades.updateModifiers(student) + second?.grades?.updateModifiers(student).orEmpty()).calcAverage()
|
(selected.grades.updateModifiers(student) + second?.grades?.updateModifiers(student).orEmpty()).calcAverage()
|
||||||
} else selected.average)
|
} else selected.average)
|
||||||
}
|
})
|
||||||
}
|
}.filter { it.status != Status.LOADING }.filter { it.data != null }
|
||||||
} else selectedDetails
|
} else flowOf(selectedDetails)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getSemesterDetailsWithAverage(student: Student, semester: Semester, forceRefresh: Boolean): List<GradeDetailsWithAverage> {
|
private fun getSemesterDetailsWithAverage(student: Student, semester: Semester, forceRefresh: Boolean): Flow<Resource<List<GradeDetailsWithAverage>>> {
|
||||||
return gradeRepository.getGrades(student, semester, forceRefresh).let { (details, summaries) ->
|
return gradeRepository.getGrades(student, semester, forceRefresh = forceRefresh).map { res ->
|
||||||
val isAnyAverage = summaries.any { it.average != .0 }
|
val (details, summaries) = res.data ?: null to null
|
||||||
val allGrades = details.groupBy { it.subject }
|
val isAnyAverage = summaries.orEmpty().any { it.average != .0 }
|
||||||
|
val allGrades = details.orEmpty().groupBy { it.subject }
|
||||||
|
|
||||||
summaries.emulateEmptySummaries(student, semester, allGrades.toList(), isAnyAverage).map { summary ->
|
Resource(res.status, summaries?.emulateEmptySummaries(student, semester, allGrades.toList(), isAnyAverage)?.map { summary ->
|
||||||
val grades = allGrades[summary.subject].orEmpty()
|
val grades = allGrades[summary.subject].orEmpty()
|
||||||
GradeDetailsWithAverage(
|
GradeDetailsWithAverage(
|
||||||
subject = summary.subject,
|
subject = summary.subject,
|
||||||
@ -92,7 +104,7 @@ class GradeAverageProvider @Inject constructor(
|
|||||||
summary = summary,
|
summary = summary,
|
||||||
grades = grades
|
grades = grades
|
||||||
)
|
)
|
||||||
}
|
}, res.error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.wulkanowy.ui.modules.grade
|
package io.github.wulkanowy.ui.modules.grade
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
@ -7,10 +8,11 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
|||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
import io.github.wulkanowy.utils.getCurrentOrLast
|
import io.github.wulkanowy.utils.getCurrentOrLast
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class GradePresenter @Inject constructor(
|
class GradePresenter @Inject constructor(
|
||||||
@ -99,17 +101,18 @@ class GradePresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadData() {
|
private fun loadData() {
|
||||||
Timber.i("Loading grade data started")
|
flowWithResource {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.flatMap { rxSingle { semesterRepository.getSemesters(it, refreshOnNoCurrent = true) } }
|
delay(200)
|
||||||
.delay(200, MILLISECONDS)
|
semesterRepository.getSemesters(student, refreshOnNoCurrent = true)
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
}.onEach {
|
||||||
.observeOn(schedulers.mainThread)
|
when (it.status) {
|
||||||
.subscribe({
|
Status.LOADING -> Timber.i("Loading grade data started")
|
||||||
val current = it.getCurrentOrLast()
|
Status.SUCCESS -> {
|
||||||
|
val current = it.data!!.getCurrentOrLast()
|
||||||
selectedIndex = if (selectedIndex == 0) current.semesterName else selectedIndex
|
selectedIndex = if (selectedIndex == 0) current.semesterName else selectedIndex
|
||||||
schoolYear = current.schoolYear
|
schoolYear = current.schoolYear
|
||||||
semesters = it.filter { semester -> semester.diaryId == current.diaryId }
|
semesters = it.data.filter { semester -> semester.diaryId == current.diaryId }
|
||||||
view?.setCurrentSemesterName(current.semesterName, schoolYear)
|
view?.setCurrentSemesterName(current.semesterName, schoolYear)
|
||||||
|
|
||||||
view?.run {
|
view?.run {
|
||||||
@ -118,10 +121,13 @@ class GradePresenter @Inject constructor(
|
|||||||
showErrorView(false)
|
showErrorView(false)
|
||||||
showSemesterSwitch(true)
|
showSemesterSwitch(true)
|
||||||
}
|
}
|
||||||
}) {
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
Timber.i("Loading grade result: An exception occurred")
|
Timber.i("Loading grade result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it.error!!)
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
}.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.wulkanowy.ui.modules.grade.details
|
package io.github.wulkanowy.ui.modules.grade.details
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
import io.github.wulkanowy.data.db.entities.Grade
|
||||||
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
||||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||||
@ -11,8 +12,11 @@ import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider
|
|||||||
import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage
|
import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage
|
||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import kotlinx.coroutines.rx2.rxCompletable
|
import io.github.wulkanowy.utils.afterLoading
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
|
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -41,7 +45,9 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
|
|
||||||
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
currentSemesterId = semesterId
|
currentSemesterId = semesterId
|
||||||
|
|
||||||
loadData(semesterId, forceRefresh)
|
loadData(semesterId, forceRefresh)
|
||||||
|
if (!forceRefresh) view?.showErrorView(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onGradeItemSelected(grade: Grade, position: Int) {
|
fun onGradeItemSelected(grade: Grade, position: Int) {
|
||||||
@ -63,24 +69,24 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onMarkAsReadSelected(): Boolean {
|
fun onMarkAsReadSelected(): Boolean {
|
||||||
Timber.i("Select mark grades as read")
|
flowWithResource {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.flatMap { rxSingle { semesterRepository.getSemesters(it) } }
|
val semesters = semesterRepository.getSemesters(student)
|
||||||
.flatMap { rxSingle { gradeRepository.getUnreadGrades(it.first { item -> item.semesterId == currentSemesterId }) } }
|
val semester = semesters.first { item -> item.semesterId == currentSemesterId }
|
||||||
.map { it.map { grade -> grade.apply { isRead = true } } }
|
val unreadGrades = gradeRepository.getUnreadGrades(semester).first()
|
||||||
.flatMapCompletable {
|
|
||||||
Timber.i("Mark as read ${it.size} grades")
|
Timber.i("Mark as read ${unreadGrades.size} grades")
|
||||||
rxCompletable { gradeRepository.updateGrades(it) }
|
gradeRepository.updateGrades(unreadGrades.map { it.apply { isRead = true } })
|
||||||
}
|
}.onEach {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
when (it.status) {
|
||||||
.observeOn(schedulers.mainThread)
|
Status.LOADING -> Timber.i("Select mark grades as read")
|
||||||
.subscribe({
|
Status.SUCCESS -> Timber.i("Mark as read result: Success")
|
||||||
Timber.i("Mark as read result: Success")
|
Status.ERROR -> {
|
||||||
loadData(currentSemesterId, false)
|
|
||||||
}, {
|
|
||||||
Timber.i("Mark as read result: An exception occurred")
|
Timber.i("Mark as read result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it.error!!)
|
||||||
}))
|
}
|
||||||
|
}
|
||||||
|
}.launch("mark")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +125,7 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
clearView()
|
clearView()
|
||||||
}
|
}
|
||||||
disposable.clear()
|
cancelJobs("load")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateMarkAsDoneButton() {
|
fun updateMarkAsDoneButton() {
|
||||||
@ -127,29 +133,23 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
|
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
Timber.i("Loading grade details data started")
|
flowWithResourceIn {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.flatMap { rxSingle { averageProvider.getGradesDetailsWithAverage(it, semesterId, forceRefresh) } }
|
averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh)
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
}.onEach {
|
||||||
.observeOn(schedulers.mainThread)
|
when (it.status) {
|
||||||
.doFinally {
|
Status.LOADING -> Timber.i("Loading grade details data started")
|
||||||
view?.run {
|
Status.SUCCESS -> {
|
||||||
showRefresh(false)
|
|
||||||
showProgress(false)
|
|
||||||
enableSwipe(true)
|
|
||||||
notifyParentDataLoaded(semesterId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.subscribe({ grades ->
|
|
||||||
Timber.i("Loading grade details result: Success")
|
Timber.i("Loading grade details result: Success")
|
||||||
newGradesAmount = grades.sumBy { it.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } }
|
newGradesAmount = it.data!!.sumBy { item -> item.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } }
|
||||||
updateMarkAsDoneButton()
|
updateMarkAsDoneButton()
|
||||||
|
val items = createGradeItems(it.data)
|
||||||
view?.run {
|
view?.run {
|
||||||
showEmpty(grades.isEmpty())
|
showEmpty(items.isEmpty())
|
||||||
showErrorView(false)
|
showErrorView(false)
|
||||||
showContent(grades.isNotEmpty())
|
showContent(items.isNotEmpty())
|
||||||
updateData(
|
updateData(
|
||||||
data = createGradeItems(grades),
|
data = items,
|
||||||
isGradeExpandable = preferencesRepository.isGradeExpandable,
|
isGradeExpandable = preferencesRepository.isGradeExpandable,
|
||||||
gradeColorTheme = preferencesRepository.gradeColorTheme
|
gradeColorTheme = preferencesRepository.gradeColorTheme
|
||||||
)
|
)
|
||||||
@ -157,13 +157,22 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
analytics.logEvent(
|
analytics.logEvent(
|
||||||
"load_data",
|
"load_data",
|
||||||
"type" to "grade_details",
|
"type" to "grade_details",
|
||||||
"items" to grades.size,
|
"items" to it.data.size
|
||||||
"force_refresh" to forceRefresh
|
|
||||||
)
|
)
|
||||||
}) {
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
Timber.i("Loading grade details result: An exception occurred")
|
Timber.i("Loading grade details result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it.error!!)
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
}.afterLoading {
|
||||||
|
view?.run {
|
||||||
|
showRefresh(false)
|
||||||
|
showProgress(false)
|
||||||
|
enableSwipe(true)
|
||||||
|
notifyParentDataLoaded(semesterId)
|
||||||
|
}
|
||||||
|
}.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
@ -197,15 +206,15 @@ class GradeDetailsPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateGrade(grade: Grade) {
|
private fun updateGrade(grade: Grade) {
|
||||||
Timber.i("Attempt to update grade ${grade.id}")
|
flowWithResource { gradeRepository.updateGrade(grade) }.onEach {
|
||||||
disposable.add(rxCompletable { gradeRepository.updateGrade(grade) }
|
when (it.status) {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
Status.LOADING -> Timber.i("Attempt to update grade ${grade.id}")
|
||||||
.observeOn(schedulers.mainThread)
|
Status.SUCCESS -> Timber.i("Update grade result: Success")
|
||||||
.subscribe({
|
Status.ERROR -> {
|
||||||
Timber.i("Update grade result: Success")
|
|
||||||
}) { error ->
|
|
||||||
Timber.i("Update grade result: An exception occurred")
|
Timber.i("Update grade result: An exception occurred")
|
||||||
errorHandler.dispatch(error)
|
errorHandler.dispatch(it.error!!)
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
}.launch("update")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.wulkanowy.ui.modules.grade.statistics
|
package io.github.wulkanowy.ui.modules.grade.statistics
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.Subject
|
import io.github.wulkanowy.data.db.entities.Subject
|
||||||
import io.github.wulkanowy.data.repositories.gradestatistics.GradeStatisticsRepository
|
import io.github.wulkanowy.data.repositories.gradestatistics.GradeStatisticsRepository
|
||||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||||
@ -10,7 +11,9 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
|||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import io.github.wulkanowy.utils.afterLoading
|
||||||
|
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -46,6 +49,7 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
currentSemesterId = semesterId
|
currentSemesterId = semesterId
|
||||||
loadSubjects()
|
loadSubjects()
|
||||||
|
if (!forceRefresh) view?.showErrorView(false)
|
||||||
loadDataByType(semesterId, currentSubjectName, currentType, forceRefresh)
|
loadDataByType(semesterId, currentSubjectName, currentType, forceRefresh)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +69,7 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
clearView()
|
clearView()
|
||||||
}
|
}
|
||||||
disposable.clear()
|
cancelJobs("load")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSwipeRefresh() {
|
fun onSwipeRefresh() {
|
||||||
@ -103,7 +107,7 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
fun onTypeChange() {
|
fun onTypeChange() {
|
||||||
val type = view?.currentType ?: ViewType.POINTS
|
val type = view?.currentType ?: ViewType.POINTS
|
||||||
Timber.i("Select grade stats semester: $type")
|
Timber.i("Select grade stats semester: $type")
|
||||||
disposable.clear()
|
cancelJobs("load")
|
||||||
view?.run {
|
view?.run {
|
||||||
showContent(false)
|
showContent(false)
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
@ -116,38 +120,39 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadSubjects() {
|
private fun loadSubjects() {
|
||||||
Timber.i("Loading grade stats subjects started")
|
flowWithResourceIn {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.flatMap { student ->
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
subjectRepository.getSubjects(student, semester)
|
||||||
rxSingle { subjectRepository.getSubjects(student, semester) }
|
}.onEach {
|
||||||
}
|
when (it.status) {
|
||||||
}
|
Status.LOADING -> Timber.i("Loading grade stats subjects started")
|
||||||
.doOnSuccess { subjects = it }
|
Status.SUCCESS -> {
|
||||||
.map { ArrayList(it.map { subject -> subject.name }) }
|
subjects = it.data!!
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.subscribe({
|
|
||||||
Timber.i("Loading grade stats subjects result: Success")
|
Timber.i("Loading grade stats subjects result: Success")
|
||||||
view?.updateSubjects(it)
|
view?.run {
|
||||||
}, {
|
view?.updateSubjects(ArrayList(it.data.map { subject -> subject.name }))
|
||||||
|
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
Timber.i("Loading grade stats subjects result: An exception occurred")
|
Timber.i("Loading grade stats subjects result: An exception occurred")
|
||||||
errorHandler.dispatch(it)
|
errorHandler.dispatch(it.error!!)
|
||||||
})
|
}
|
||||||
)
|
}
|
||||||
|
}.launch("subjects")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) {
|
private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) {
|
||||||
currentSubjectName = if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName
|
currentSubjectName = if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName
|
||||||
currentType = type
|
currentType = type
|
||||||
|
|
||||||
Timber.i("Loading grade stats data started")
|
flowWithResourceIn {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.flatMap { student ->
|
val semesters = semesterRepository.getSemesters(student)
|
||||||
rxSingle { semesterRepository.getSemesters(student) }.flatMap { semesters ->
|
|
||||||
val semester = semesters.first { item -> item.semesterId == semesterId }
|
val semester = semesters.first { item -> item.semesterId == semesterId }
|
||||||
|
|
||||||
rxSingle {
|
|
||||||
with(gradeStatisticsRepository) {
|
with(gradeStatisticsRepository) {
|
||||||
when (type) {
|
when (type) {
|
||||||
ViewType.SEMESTER -> getGradesStatistics(student, semester, currentSubjectName, true, forceRefresh)
|
ViewType.SEMESTER -> getGradesStatistics(student, semester, currentSubjectName, true, forceRefresh)
|
||||||
@ -155,38 +160,37 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
ViewType.POINTS -> getGradesPointsStatistics(student, semester, currentSubjectName, forceRefresh)
|
ViewType.POINTS -> getGradesPointsStatistics(student, semester, currentSubjectName, forceRefresh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}.onEach {
|
||||||
|
when (it.status) {
|
||||||
|
Status.LOADING -> Timber.i("Loading grade stats data started")
|
||||||
|
Status.SUCCESS -> {
|
||||||
|
Timber.i("Loading grade stats result: Success")
|
||||||
|
view?.run {
|
||||||
|
showEmpty(it.data!!.isEmpty())
|
||||||
|
showContent(it.data.isNotEmpty())
|
||||||
|
showErrorView(false)
|
||||||
|
updateData(it.data, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||||
|
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||||
|
}
|
||||||
|
analytics.logEvent(
|
||||||
|
"load_data",
|
||||||
|
"type" to "grade_statistics",
|
||||||
|
"items" to it.data!!.size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
|
Timber.i("Loading grade stats result: An exception occurred")
|
||||||
|
errorHandler.dispatch(it.error!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}.afterLoading {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doFinally {
|
|
||||||
view?.run {
|
view?.run {
|
||||||
showRefresh(false)
|
showRefresh(false)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
notifyParentDataLoaded(semesterId)
|
notifyParentDataLoaded(semesterId)
|
||||||
}
|
}
|
||||||
}
|
}.launch("load")
|
||||||
.subscribe({
|
|
||||||
Timber.i("Loading grade stats result: Success")
|
|
||||||
view?.run {
|
|
||||||
showEmpty(it.isEmpty())
|
|
||||||
showContent(it.isNotEmpty())
|
|
||||||
showErrorView(false)
|
|
||||||
updateData(it, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList)
|
|
||||||
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
|
||||||
}
|
|
||||||
analytics.logEvent(
|
|
||||||
"load_data",
|
|
||||||
"type" to "grade_statistics",
|
|
||||||
"items" to it.size,
|
|
||||||
"force_refresh" to forceRefresh
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
Timber.i("Loading grade stats result: An exception occurred")
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.wulkanowy.ui.modules.grade.summary
|
package io.github.wulkanowy.ui.modules.grade.summary
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
@ -8,7 +9,9 @@ import io.github.wulkanowy.ui.modules.grade.GradeAverageProvider
|
|||||||
import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage
|
import io.github.wulkanowy.ui.modules.grade.GradeDetailsWithAverage
|
||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import io.github.wulkanowy.utils.afterLoading
|
||||||
|
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -30,36 +33,45 @@ class GradeSummaryPresenter @Inject constructor(
|
|||||||
|
|
||||||
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
Timber.i("Loading grade summary data started")
|
Timber.i("Loading grade summary data started")
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
|
||||||
.flatMap { rxSingle { averageProvider.getGradesDetailsWithAverage(it, semesterId, forceRefresh) } }
|
loadData(semesterId, forceRefresh)
|
||||||
.map { createGradeSummaryItems(it) }
|
if (!forceRefresh) view?.showErrorView(false)
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
}
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doFinally {
|
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
|
||||||
|
flowWithResourceIn {
|
||||||
|
val student = studentRepository.getCurrentStudent()
|
||||||
|
averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh)
|
||||||
|
}.onEach {
|
||||||
|
when (it.status) {
|
||||||
|
Status.LOADING -> Timber.i("Loading grade summary started")
|
||||||
|
Status.SUCCESS -> {
|
||||||
|
Timber.i("Loading grade summary result: Success")
|
||||||
|
view?.run {
|
||||||
|
showEmpty(it.data!!.isEmpty())
|
||||||
|
showContent(it.data.isNotEmpty())
|
||||||
|
showErrorView(false)
|
||||||
|
updateData(createGradeSummaryItems(it.data))
|
||||||
|
}
|
||||||
|
analytics.logEvent(
|
||||||
|
"load_data",
|
||||||
|
"type" to "grade_summary",
|
||||||
|
"items" to it.data!!.size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
|
Timber.i("Loading grade summary result: An exception occurred")
|
||||||
|
errorHandler.dispatch(it.error!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.afterLoading {
|
||||||
view?.run {
|
view?.run {
|
||||||
showRefresh(false)
|
showRefresh(false)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
notifyParentDataLoaded(semesterId)
|
notifyParentDataLoaded(semesterId)
|
||||||
}
|
}
|
||||||
}.subscribe({
|
}.launch()
|
||||||
Timber.i("Loading grade summary result: Success")
|
|
||||||
view?.run {
|
|
||||||
showEmpty(it.isEmpty())
|
|
||||||
showContent(it.isNotEmpty())
|
|
||||||
showErrorView(false)
|
|
||||||
updateData(it)
|
|
||||||
}
|
|
||||||
analytics.logEvent(
|
|
||||||
"load_data",
|
|
||||||
"type" to "grade_summary",
|
|
||||||
"items" to it.size,
|
|
||||||
"force_refresh" to forceRefresh
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
Timber.i("Loading grade summary result: An exception occurred")
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
@ -105,7 +117,7 @@ class GradeSummaryPresenter @Inject constructor(
|
|||||||
showEmpty(false)
|
showEmpty(false)
|
||||||
clearView()
|
clearView()
|
||||||
}
|
}
|
||||||
disposable.clear()
|
cancelJobs("load")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createGradeSummaryItems(items: List<GradeDetailsWithAverage>): List<GradeSummary> {
|
private fun createGradeSummaryItems(items: List<GradeDetailsWithAverage>): List<GradeSummary> {
|
||||||
|
@ -70,10 +70,6 @@ class HomeworkFragment : BaseFragment<FragmentHomeworkBinding>(R.layout.fragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onReloadList() {
|
|
||||||
presenter.reloadData()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clearData() {
|
override fun clearData() {
|
||||||
with(homeworkAdapter) {
|
with(homeworkAdapter) {
|
||||||
items = emptyList()
|
items = emptyList()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.wulkanowy.ui.modules.homework
|
package io.github.wulkanowy.ui.modules.homework
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.db.entities.Homework
|
import io.github.wulkanowy.data.db.entities.Homework
|
||||||
import io.github.wulkanowy.data.repositories.homework.HomeworkRepository
|
import io.github.wulkanowy.data.repositories.homework.HomeworkRepository
|
||||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||||
@ -8,13 +9,17 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
|||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||||
import io.github.wulkanowy.utils.SchedulersProvider
|
import io.github.wulkanowy.utils.SchedulersProvider
|
||||||
import io.github.wulkanowy.utils.sunday
|
import io.github.wulkanowy.utils.afterLoading
|
||||||
|
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||||
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
|
import io.github.wulkanowy.utils.getLastSchoolDayIfHoliday
|
||||||
import io.github.wulkanowy.utils.isHolidays
|
import io.github.wulkanowy.utils.isHolidays
|
||||||
import io.github.wulkanowy.utils.monday
|
import io.github.wulkanowy.utils.monday
|
||||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||||
|
import io.github.wulkanowy.utils.sunday
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import kotlinx.coroutines.rx2.rxSingle
|
import kotlinx.coroutines.flow.catch
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import org.threeten.bp.LocalDate.ofEpochDay
|
import org.threeten.bp.LocalDate.ofEpochDay
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@ -79,64 +84,54 @@ class HomeworkPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setBaseDateOnHolidays() {
|
private fun setBaseDateOnHolidays() {
|
||||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
flow {
|
||||||
.flatMap { rxSingle { semesterRepository.getCurrentSemester(it) } }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
emit(semesterRepository.getCurrentSemester(student))
|
||||||
.observeOn(schedulers.mainThread)
|
}.catch {
|
||||||
.subscribe({
|
Timber.i("Loading semester result: An exception occurred")
|
||||||
|
}.onEach {
|
||||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
||||||
currentDate = baseDate
|
currentDate = baseDate
|
||||||
reloadNavigation()
|
reloadNavigation()
|
||||||
}) {
|
}.launch("holidays")
|
||||||
Timber.i("Loading semester result: An exception occurred")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reloadData() {
|
|
||||||
loadData(currentDate, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||||
Timber.i("Loading homework data started")
|
|
||||||
currentDate = date
|
currentDate = date
|
||||||
disposable.apply {
|
|
||||||
clear()
|
flowWithResourceIn {
|
||||||
add(rxSingle { studentRepository.getCurrentStudent() }
|
val student = studentRepository.getCurrentStudent()
|
||||||
.flatMap { student ->
|
val semester = semesterRepository.getCurrentSemester(student)
|
||||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
homeworkRepository.getHomework(student, semester, date, date, forceRefresh)
|
||||||
rxSingle { homeworkRepository.getHomework(student, semester, currentDate, currentDate, forceRefresh) }
|
}.onEach {
|
||||||
|
when (it.status) {
|
||||||
|
Status.LOADING -> Timber.i("Loading homework data started")
|
||||||
|
Status.SUCCESS -> {
|
||||||
|
Timber.i("Loading homework result: Success")
|
||||||
|
view?.apply {
|
||||||
|
updateData(createHomeworkItem(it.data!!))
|
||||||
|
showEmpty(it.data.isEmpty())
|
||||||
|
showErrorView(false)
|
||||||
|
showContent(it.data.isNotEmpty())
|
||||||
|
}
|
||||||
|
analytics.logEvent(
|
||||||
|
"load_data",
|
||||||
|
"type" to "homework",
|
||||||
|
"items" to it.data!!.size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Status.ERROR -> {
|
||||||
|
Timber.i("Loading homework result: An exception occurred")
|
||||||
|
errorHandler.dispatch(it.error!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map { createHomeworkItem(it) }
|
}.afterLoading {
|
||||||
.subscribeOn(schedulers.backgroundThread)
|
|
||||||
.observeOn(schedulers.mainThread)
|
|
||||||
.doFinally {
|
|
||||||
view?.run {
|
view?.run {
|
||||||
hideRefresh()
|
hideRefresh()
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
enableSwipe(true)
|
enableSwipe(true)
|
||||||
}
|
}
|
||||||
}
|
}.launch()
|
||||||
.subscribe({
|
|
||||||
Timber.i("Loading homework result: Success")
|
|
||||||
view?.apply {
|
|
||||||
updateData(it)
|
|
||||||
showEmpty(it.isEmpty())
|
|
||||||
showErrorView(false)
|
|
||||||
showContent(it.isNotEmpty())
|
|
||||||
}
|
|
||||||
analytics.logEvent(
|
|
||||||
"load_data",
|
|
||||||
"type" to "homework",
|
|
||||||
"items" to it.size,
|
|
||||||
"force_refresh" to forceRefresh
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
Timber.i("Loading homework result: An exception occurred")
|
|
||||||
|
|
||||||
errorHandler.dispatch(it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||||
|
@ -73,7 +73,6 @@ class HomeworkDetailsDialog : BaseDialogFragment<DialogHomeworkBinding>(), Homew
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun updateMarkAsDoneLabel(isDone: Boolean) {
|
override fun updateMarkAsDoneLabel(isDone: Boolean) {
|
||||||
(parentFragment as? HomeworkFragment)?.onReloadList()
|
|
||||||
binding.homeworkDialogRead.text = view?.context?.getString(if (isDone) R.string.homework_mark_as_undone else R.string.homework_mark_as_done)
|
binding.homeworkDialogRead.text = view?.context?.getString(if (isDone) R.string.homework_mark_as_undone else R.string.homework_mark_as_done)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user