Migrate presenters from rxjava to coroutines flow (#894)
This commit is contained in:
@ -18,8 +18,7 @@
|
||||
android:supportsRtl="false"
|
||||
android:theme="@style/WulkanowyTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute"
|
||||
tools:replace="android:supportsRtl,android:allowBackup">
|
||||
tools:ignore="GoogleAppIndexingWarning,UnusedAttribute">
|
||||
<activity
|
||||
android:name=".ui.modules.splash.SplashActivity"
|
||||
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.Query
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface AttendanceDao : BaseDao<Attendance> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface AttendanceSummaryDao : BaseDao<AttendanceSummary> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.CompletedLesson
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface CompletedLessonsDao : BaseDao<CompletedLesson> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface ExamDao : BaseDao<Exam> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -10,5 +11,5 @@ import javax.inject.Singleton
|
||||
interface GradeDao : BaseDao<Grade> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -10,8 +11,8 @@ import javax.inject.Singleton
|
||||
interface GradePointsStatisticsDao : BaseDao<GradePointsStatistics> {
|
||||
|
||||
@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")
|
||||
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.Query
|
||||
import io.github.wulkanowy.data.db.entities.GradeStatistics
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -10,8 +11,8 @@ import javax.inject.Singleton
|
||||
interface GradeStatisticsDao : BaseDao<GradeStatistics> {
|
||||
|
||||
@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")
|
||||
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.Query
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -10,5 +11,5 @@ import javax.inject.Singleton
|
||||
interface GradeSummaryDao : BaseDao<GradeSummary> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface HomeworkDao : BaseDao<Homework> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface LuckyNumberDao : BaseDao<LuckyNumber> {
|
||||
|
||||
@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 io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface MessagesDao : BaseDao<Message> {
|
||||
|
||||
@Transaction
|
||||
@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")
|
||||
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")
|
||||
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.Query
|
||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface MobileDeviceDao : BaseDao<MobileDevice> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.Note
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -10,5 +11,5 @@ import javax.inject.Singleton
|
||||
interface NoteDao : BaseDao<Note> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.School
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -10,5 +11,5 @@ import javax.inject.Singleton
|
||||
interface SchoolDao : BaseDao<School> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.Subject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface SubjectDao : BaseDao<Subject> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.Teacher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@ -10,5 +11,5 @@ import javax.inject.Singleton
|
||||
interface TeacherDao : BaseDao<Teacher> {
|
||||
|
||||
@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.Query
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -11,5 +12,5 @@ import javax.inject.Singleton
|
||||
interface TimetableDao : BaseDao<Timetable> {
|
||||
|
||||
@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
|
||||
) {
|
||||
|
||||
suspend fun getAppCreators(): List<Contributor> {
|
||||
return withContext(dispatchers.backgroundThread) {
|
||||
Gson().fromJson(
|
||||
assets.open("contributors.json").bufferedReader().use { it.readText() },
|
||||
Array<Contributor>::class.java
|
||||
).toList()
|
||||
}
|
||||
suspend fun getAppCreators() = withContext(dispatchers.backgroundThread) {
|
||||
Gson().fromJson(
|
||||
assets.open("contributors.json").bufferedReader().use { it.readText() },
|
||||
Array<Contributor>::class.java
|
||||
).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.entities.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -18,7 +19,7 @@ class AttendanceLocal @Inject constructor(private val attendanceDb: AttendanceDa
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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.Student
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import org.threeten.bp.LocalDate
|
||||
@ -16,19 +17,18 @@ class AttendanceRepository @Inject constructor(
|
||||
private val remote: AttendanceRemote
|
||||
) {
|
||||
|
||||
suspend fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean): List<Attendance> {
|
||||
return local.getAttendance(semester, start.monday, end.sunday).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getAttendance(student, semester, start.monday, end.sunday)
|
||||
val old = local.getAttendance(semester, start.monday, end.sunday)
|
||||
fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { 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))
|
||||
local.saveAttendance(new.uniqueSubtract(old))
|
||||
|
||||
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)
|
||||
suspend fun excuseForAbsence(student: Student, semester: Semester, attendanceList: List<Attendance>, reason: String? = null) {
|
||||
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.entities.AttendanceSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -17,7 +18,7 @@ class AttendanceSummaryLocal @Inject constructor(private val attendanceDb: Atten
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
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.Student
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -13,15 +13,13 @@ class AttendanceSummaryRepository @Inject constructor(
|
||||
private val remote: AttendanceSummaryRemote
|
||||
) {
|
||||
|
||||
suspend fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean = false): List<AttendanceSummary> {
|
||||
return local.getAttendanceSummary(semester, subjectId).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getAttendanceSummary(student, semester, subjectId)
|
||||
|
||||
val old = local.getAttendanceSummary(semester, subjectId)
|
||||
local.deleteAttendanceSummary(old.uniqueSubtract(new))
|
||||
local.saveAttendanceSummary(new.uniqueSubtract(old))
|
||||
|
||||
return local.getAttendanceSummary(semester, subjectId)
|
||||
fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getAttendanceSummary(semester, subjectId) },
|
||||
fetch = { remote.getAttendanceSummary(student, semester, subjectId) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteAttendanceSummary(old uniqueSubtract new)
|
||||
local.saveAttendanceSummary(new uniqueSubtract old)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -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.entities.CompletedLesson
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -18,7 +19,7 @@ class CompletedLessonsLocal @Inject constructor(private val completedLessonsDb:
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
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.Student
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import org.threeten.bp.LocalDate
|
||||
@ -16,15 +16,14 @@ class CompletedLessonsRepository @Inject constructor(
|
||||
private val remote: CompletedLessonsRemote
|
||||
) {
|
||||
|
||||
suspend fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): List<CompletedLesson> {
|
||||
return local.getCompletedLessons(semester, start.monday, end.sunday).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getCompletedLessons(student, semester, start.monday, end.sunday)
|
||||
val old = local.getCompletedLessons(semester, start.monday, end.sunday)
|
||||
|
||||
local.deleteCompleteLessons(old.uniqueSubtract(new))
|
||||
local.saveCompletedLessons(new.uniqueSubtract(old))
|
||||
|
||||
local.getCompletedLessons(semester, start.monday, end.sunday)
|
||||
}.filter { it.date in start..end }
|
||||
}
|
||||
fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { 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.saveCompletedLessons(new uniqueSubtract old)
|
||||
},
|
||||
filterResult = { it.filter { item -> item.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.entities.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -10,7 +11,7 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
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.Student
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import org.threeten.bp.LocalDate
|
||||
@ -16,15 +16,14 @@ class ExamRepository @Inject constructor(
|
||||
private val remote: ExamRemote
|
||||
) {
|
||||
|
||||
suspend fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): List<Exam> {
|
||||
return local.getExams(semester, start.monday, end.sunday).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getExams(student, semester, start.monday, end.sunday)
|
||||
val old = local.getExams(semester, start.monday, end.sunday)
|
||||
|
||||
local.deleteExams(old.uniqueSubtract(new))
|
||||
local.saveExams(new.uniqueSubtract(old))
|
||||
|
||||
local.getExams(semester, start.monday, end.sunday)
|
||||
}.filter { it.date in start..end }
|
||||
}
|
||||
fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { 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.saveExams(new uniqueSubtract old)
|
||||
},
|
||||
filterResult = { it.filter { item -> item.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.GradeSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -30,7 +31,7 @@ class GradeLocal @Inject constructor(
|
||||
gradeSummaryDb.updateAll(gradesSummary)
|
||||
}
|
||||
|
||||
suspend fun getGradesDetails(semester: Semester): List<Grade> {
|
||||
fun getGradesDetails(semester: Semester): Flow<List<Grade>> {
|
||||
return gradeDb.loadAll(semester.semesterId, semester.studentId)
|
||||
}
|
||||
|
||||
@ -42,7 +43,7 @@ class GradeLocal @Inject constructor(
|
||||
gradeSummaryDb.deleteAll(gradesSummary)
|
||||
}
|
||||
|
||||
suspend fun getGradesSummary(semester: Semester): List<GradeSummary> {
|
||||
fun getGradesSummary(semester: Semester): Flow<List<GradeSummary>> {
|
||||
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.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
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 javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -15,30 +19,30 @@ class GradeRepository @Inject constructor(
|
||||
private val remote: GradeRemote
|
||||
) {
|
||||
|
||||
suspend fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean = false, notify: Boolean = false): Pair<List<Grade>, List<GradeSummary>> {
|
||||
val details = local.getGradesDetails(semester)
|
||||
val summaries = local.getGradesSummary(semester)
|
||||
|
||||
if ((details.isNotEmpty() || summaries.isNotEmpty()) && !forceRefresh) {
|
||||
return details to summaries
|
||||
fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||
shouldFetch = { (details, summaries) -> details.isEmpty() || summaries.isEmpty() || forceRefresh },
|
||||
query = { local.getGradesDetails(semester).combine(local.getGradesSummary(semester)) { details, summaries -> details to summaries } },
|
||||
fetch = { remote.getGrades(student, semester) },
|
||||
saveFetchResult = { old, new ->
|
||||
refreshGradeDetails(student, old.first, new.first, notify)
|
||||
refreshGradeSummaries(old.second, new.second, notify)
|
||||
}
|
||||
)
|
||||
|
||||
val (newDetails, newSummary) = remote.getGrades(student, semester)
|
||||
val oldGrades = local.getGradesDetails(semester)
|
||||
|
||||
private suspend fun refreshGradeDetails(student: Student, oldGrades: List<Grade>, newDetails: List<Grade>, notify: Boolean) {
|
||||
val notifyBreakDate = oldGrades.maxBy { it.date }?.date ?: student.registrationDate.toLocalDate()
|
||||
local.deleteGrades(oldGrades.uniqueSubtract(newDetails))
|
||||
local.saveGrades(newDetails.uniqueSubtract(oldGrades).onEach {
|
||||
if (it.date >= notifyBreakDate) it.apply {
|
||||
isRead = false
|
||||
if (notify) isNotified = false
|
||||
}
|
||||
})
|
||||
local.deleteGrades(oldGrades uniqueSubtract newDetails)
|
||||
local.saveGrades((newDetails uniqueSubtract oldGrades).onEach {
|
||||
if (it.date >= notifyBreakDate) it.apply {
|
||||
isRead = false
|
||||
if (notify) isNotified = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
val oldSummaries = local.getGradesSummary(semester)
|
||||
|
||||
local.deleteGradesSummary(oldSummaries.uniqueSubtract(newSummary))
|
||||
local.saveGradesSummary(newSummary.uniqueSubtract(oldSummaries).onEach { summary ->
|
||||
private suspend fun refreshGradeSummaries(oldSummaries: List<GradeSummary>, newSummary: List<GradeSummary>, notify: Boolean) {
|
||||
local.deleteGradesSummary(oldSummaries uniqueSubtract newSummary)
|
||||
local.saveGradesSummary((newSummary uniqueSubtract oldSummaries).onEach { summary ->
|
||||
val oldSummary = oldSummaries.find { oldSummary -> oldSummary.subject == summary.subject }
|
||||
summary.isPredictedGradeNotified = when {
|
||||
summary.predictedGrade.isEmpty() -> true
|
||||
@ -62,24 +66,22 @@ class GradeRepository @Inject constructor(
|
||||
else -> oldSummary.finalGradeLastChange
|
||||
}
|
||||
})
|
||||
|
||||
return local.getGradesDetails(semester) to local.getGradesSummary(semester)
|
||||
}
|
||||
|
||||
suspend fun getUnreadGrades(semester: Semester): List<Grade> {
|
||||
return local.getGradesDetails(semester).filter { grade -> !grade.isRead }
|
||||
fun getUnreadGrades(semester: Semester): Flow<List<Grade>> {
|
||||
return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isRead } }
|
||||
}
|
||||
|
||||
suspend fun getNotNotifiedGrades(semester: Semester): List<Grade> {
|
||||
return local.getGradesDetails(semester).filter { grade -> !grade.isNotified }
|
||||
fun getNotNotifiedGrades(semester: Semester): Flow<List<Grade>> {
|
||||
return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isNotified } }
|
||||
}
|
||||
|
||||
suspend fun getNotNotifiedPredictedGrades(semester: Semester): List<GradeSummary> {
|
||||
return local.getGradesSummary(semester).filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified }
|
||||
fun getNotNotifiedPredictedGrades(semester: Semester): Flow<List<GradeSummary>> {
|
||||
return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } }
|
||||
}
|
||||
|
||||
suspend fun getNotNotifiedFinalGrades(semester: Semester): List<GradeSummary> {
|
||||
return local.getGradesSummary(semester).filter { gradeSummary -> !gradeSummary.isFinalGradeNotified }
|
||||
fun getNotNotifiedFinalGrades(semester: Semester): Flow<List<GradeSummary>> {
|
||||
return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } }
|
||||
}
|
||||
|
||||
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.GradeStatistics
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -14,34 +15,14 @@ class GradeStatisticsLocal @Inject constructor(
|
||||
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)
|
||||
}
|
||||
|
||||
suspend fun getGradesPointsStatistics(semester: Semester): List<GradePointsStatistics> {
|
||||
fun getGradesPointsStatistics(semester: Semester): Flow<List<GradePointsStatistics>> {
|
||||
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>) {
|
||||
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.pojos.GradeStatisticsItem
|
||||
import io.github.wulkanowy.ui.modules.grade.statistics.ViewType
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -16,29 +17,40 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
private val remote: GradeStatisticsRemote
|
||||
) {
|
||||
|
||||
suspend fun getGradesStatistics(student: Student, semester: Semester, subjectName: String, isSemester: Boolean, forceRefresh: Boolean = false): List<GradeStatisticsItem> {
|
||||
return local.getGradesStatistics(semester, isSemester, subjectName).mapToStatisticItems().filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getGradeStatistics(student, semester, isSemester)
|
||||
val old = local.getGradesStatistics(semester, isSemester)
|
||||
|
||||
local.deleteGradesStatistics(old.uniqueSubtract(new))
|
||||
local.saveGradesStatistics(new.uniqueSubtract(old))
|
||||
|
||||
local.getGradesStatistics(semester, isSemester, subjectName).mapToStatisticItems()
|
||||
fun getGradesStatistics(student: Student, semester: Semester, subjectName: String, isSemester: Boolean, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getGradesStatistics(semester, isSemester) },
|
||||
fetch = { remote.getGradeStatistics(student, semester, isSemester) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteGradesStatistics(old uniqueSubtract new)
|
||||
local.saveGradesStatistics(new uniqueSubtract old)
|
||||
},
|
||||
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> {
|
||||
return local.getGradesPointsStatistics(semester, subjectName).mapToStatisticsItem().filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getGradePointsStatistics(student, semester)
|
||||
val old = local.getGradesPointsStatistics(semester)
|
||||
|
||||
local.deleteGradesPointsStatistics(old.uniqueSubtract(new))
|
||||
local.saveGradesPointsStatistics(new.uniqueSubtract(old))
|
||||
|
||||
local.getGradesPointsStatistics(semester, subjectName).mapToStatisticsItem()
|
||||
fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getGradesPointsStatistics(semester) },
|
||||
fetch = { remote.getGradePointsStatistics(student, semester) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteGradesPointsStatistics(old uniqueSubtract new)
|
||||
local.saveGradesPointsStatistics(new uniqueSubtract old)
|
||||
},
|
||||
mapResult = { items ->
|
||||
when (subjectName) {
|
||||
"Wszystkie" -> items
|
||||
else -> items.filter { it.subject == subjectName }
|
||||
}.mapToStatisticsItem()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
private fun List<GradeStatistics>.mapToStatisticItems() = groupBy { it.subject }.map {
|
||||
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.entities.Homework
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -22,7 +23,7 @@ class HomeworkLocal @Inject constructor(private val homeworkDb: HomeworkDao) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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.Student
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import org.threeten.bp.LocalDate
|
||||
@ -16,18 +17,15 @@ class HomeworkRepository @Inject constructor(
|
||||
private val remote: HomeworkRemote
|
||||
) {
|
||||
|
||||
suspend fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): List<Homework> {
|
||||
return local.getHomework(semester, start.monday, end.sunday).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getHomework(student, semester, start.monday, end.sunday)
|
||||
|
||||
val old = local.getHomework(semester, start.monday, end.sunday)
|
||||
|
||||
local.deleteHomework(old.uniqueSubtract(new))
|
||||
local.saveHomework(new.uniqueSubtract(old))
|
||||
|
||||
local.getHomework(semester, start.monday, end.sunday)
|
||||
fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getHomework(semester, start.monday, end.sunday) },
|
||||
fetch = { remote.getHomework(student, semester, start.monday, end.sunday) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteHomework(old uniqueSubtract new)
|
||||
local.saveHomework(new uniqueSubtract old)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
suspend fun toggleDone(homework: Homework) {
|
||||
local.updateHomework(listOf(homework.apply {
|
||||
|
@ -12,16 +12,12 @@ class LoggerRepository @Inject constructor(
|
||||
private val dispatchers: DispatchersProvider
|
||||
) {
|
||||
|
||||
suspend fun getLastLogLines(): List<String> {
|
||||
return getLastModified().readText().split("\n")
|
||||
}
|
||||
suspend fun getLastLogLines() = getLastModified().readText().split("\n")
|
||||
|
||||
suspend fun getLogFiles(): List<File> {
|
||||
return withContext(dispatchers.backgroundThread) {
|
||||
File(context.filesDir.absolutePath).listFiles(File::isFile)?.filter {
|
||||
it.name.endsWith(".log")
|
||||
}!!
|
||||
}
|
||||
suspend fun getLogFiles() = withContext(dispatchers.backgroundThread) {
|
||||
File(context.filesDir.absolutePath).listFiles(File::isFile)?.filter {
|
||||
it.name.endsWith(".log")
|
||||
}!!
|
||||
}
|
||||
|
||||
private suspend fun getLastModified(): File {
|
||||
|
@ -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.entities.LuckyNumber
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -22,7 +23,7 @@ class LuckyNumberLocal @Inject constructor(private val luckyNumberDb: LuckyNumbe
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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.Student
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate.now
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -12,31 +14,25 @@ class LuckyNumberRepository @Inject constructor(
|
||||
private val remote: LuckyNumberRemote
|
||||
) {
|
||||
|
||||
suspend fun getLuckyNumber(student: Student, forceRefresh: Boolean = false, notify: Boolean = false): LuckyNumber? {
|
||||
return local.getLuckyNumber(student, now())?.takeIf { !forceRefresh } ?: run {
|
||||
val new = remote.getLuckyNumber(student)
|
||||
val old = local.getLuckyNumber(student, now())
|
||||
|
||||
fun getLuckyNumber(student: Student, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||
shouldFetch = { it == null || forceRefresh },
|
||||
query = { local.getLuckyNumber(student, now()) },
|
||||
fetch = { remote.getLuckyNumber(student) },
|
||||
saveFetchResult = { old, new ->
|
||||
if (new != old) {
|
||||
old?.let { local.deleteLuckyNumber(it) }
|
||||
local.saveLuckyNumber(new?.apply {
|
||||
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())
|
||||
}
|
||||
|
||||
suspend fun updateLuckyNumber(luckyNumber: LuckyNumber) {
|
||||
suspend fun updateLuckyNumber(luckyNumber: 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.Student
|
||||
import io.github.wulkanowy.data.repositories.message.MessageFolder.TRASHED
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -28,7 +29,7 @@ class MessageLocal @Inject constructor(
|
||||
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)
|
||||
}
|
||||
|
||||
@ -36,7 +37,7 @@ class MessageLocal @Inject constructor(
|
||||
messageAttachmentDao.insertAttachments(attachments)
|
||||
}
|
||||
|
||||
suspend fun getMessages(student: Student, folder: MessageFolder): List<Message> {
|
||||
fun getMessages(student: Student, folder: MessageFolder): Flow<List<Message>> {
|
||||
return when (folder) {
|
||||
TRASHED -> messagesDb.loadDeleted(student.id.toInt())
|
||||
else -> messagesDb.loadAll(student.id.toInt(), folder.id)
|
||||
|
@ -1,13 +1,15 @@
|
||||
package io.github.wulkanowy.data.repositories.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.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED
|
||||
import io.github.wulkanowy.sdk.pojo.SentMessage
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -18,46 +20,37 @@ class MessageRepository @Inject constructor(
|
||||
private val remote: MessageRemote
|
||||
) {
|
||||
|
||||
suspend fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean = false, notify: Boolean = false): List<Message> {
|
||||
return local.getMessages(student, folder).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getMessages(student, semester, folder)
|
||||
val old = local.getMessages(student, folder)
|
||||
|
||||
local.deleteMessages(old.uniqueSubtract(new))
|
||||
local.saveMessages(new.uniqueSubtract(old).onEach {
|
||||
fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getMessages(student, folder) },
|
||||
fetch = { remote.getMessages(student, semester, folder) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteMessages(old uniqueSubtract new)
|
||||
local.saveMessages((new uniqueSubtract old).onEach {
|
||||
it.isNotified = !notify
|
||||
})
|
||||
|
||||
local.getMessages(student, folder)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
suspend fun getMessage(student: Student, message: Message, markAsRead: Boolean = false): MessageWithAttachment {
|
||||
return local.getMessageWithAttachment(student, message).let {
|
||||
if (it.message.content.isNotEmpty().also { status ->
|
||||
Timber.d("Message content in db empty: ${!status}")
|
||||
} && !it.message.unread) {
|
||||
return@let it
|
||||
}
|
||||
|
||||
val dbMessage = local.getMessageWithAttachment(student, message)
|
||||
|
||||
val (downloadedMessage, attachments) = remote.getMessagesContentDetails(student, dbMessage.message, markAsRead)
|
||||
|
||||
local.updateMessages(listOf(dbMessage.message.copy(unread = !markAsRead).apply {
|
||||
id = dbMessage.message.id
|
||||
fun getMessage(student: Student, message: Message, markAsRead: Boolean = false) = networkBoundResource(
|
||||
shouldFetch = {
|
||||
Timber.d("Message content in db empty: ${it.message.content.isEmpty()}")
|
||||
it.message.unread || it.message.content.isEmpty()
|
||||
},
|
||||
query = { local.getMessageWithAttachment(student, message) },
|
||||
fetch = { remote.getMessagesContentDetails(student, it.message, markAsRead) },
|
||||
saveFetchResult = { old, (downloadedMessage, attachments) ->
|
||||
local.updateMessages(listOf(old.message.copy(unread = !markAsRead).apply {
|
||||
id = old.message.id
|
||||
content = content.ifBlank { downloadedMessage }
|
||||
}))
|
||||
local.saveMessageAttachments(attachments)
|
||||
Timber.d("Message ${message.messageId} with blank content: ${dbMessage.message.content.isBlank()}, marked as read")
|
||||
|
||||
local.getMessageWithAttachment(student, message)
|
||||
Timber.d("Message ${message.messageId} with blank content: ${old.message.content.isBlank()}, marked as read")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
suspend fun getNotNotifiedMessages(student: Student): List<Message> {
|
||||
return local.getMessages(student, RECEIVED)
|
||||
.filter { message -> !message.isNotified && message.unread }
|
||||
fun getNotNotifiedMessages(student: Student): Flow<List<Message>> {
|
||||
return local.getMessages(student, RECEIVED).map { it.filter { message -> !message.isNotified && message.unread } }
|
||||
}
|
||||
|
||||
suspend fun updateMessages(messages: List<Message>) {
|
||||
@ -68,15 +61,12 @@ class MessageRepository @Inject constructor(
|
||||
return remote.sendMessage(student, subject, content, recipients)
|
||||
}
|
||||
|
||||
suspend fun deleteMessage(student: Student, message: Message): Boolean {
|
||||
val delete = remote.deleteMessage(student, message)
|
||||
suspend fun deleteMessage(student: Student, message: 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
|
||||
content = message.content
|
||||
}))
|
||||
else local.deleteMessages(listOf(message))
|
||||
|
||||
return delete // TODO: wtf
|
||||
})) else local.deleteMessages(listOf(message))
|
||||
}
|
||||
}
|
||||
|
@ -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.entities.MobileDevice
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -17,7 +18,7 @@ class MobileDeviceLocal @Inject constructor(private val mobileDb: MobileDeviceDa
|
||||
mobileDb.deleteAll(devices)
|
||||
}
|
||||
|
||||
suspend fun getDevices(semester: Semester): List<MobileDevice> {
|
||||
fun getDevices(semester: Semester): Flow<List<MobileDevice>> {
|
||||
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.Student
|
||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -14,20 +15,19 @@ class MobileDeviceRepository @Inject constructor(
|
||||
private val remote: MobileDeviceRemote
|
||||
) {
|
||||
|
||||
suspend fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean = false): List<MobileDevice> {
|
||||
return local.getDevices(semester).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getDevices(student, semester)
|
||||
val old = local.getDevices(semester)
|
||||
|
||||
fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getDevices(semester) },
|
||||
fetch = { remote.getDevices(student, semester) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteDevices(old uniqueSubtract new)
|
||||
local.saveDevices(new uniqueSubtract old)
|
||||
|
||||
local.getDevices(semester)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice): Boolean {
|
||||
return remote.unregisterDevice(student, semester, device)
|
||||
suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) {
|
||||
remote.unregisterDevice(student, semester, device)
|
||||
local.deleteDevices(listOf(device))
|
||||
}
|
||||
|
||||
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.entities.Note
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -21,7 +22,7 @@ class NoteLocal @Inject constructor(private val noteDb: NoteDao) {
|
||||
noteDb.deleteAll(notes)
|
||||
}
|
||||
|
||||
suspend fun getNotes(student: Student): List<Note> {
|
||||
fun getNotes(student: Student): Flow<List<Note>> {
|
||||
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.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -13,29 +16,27 @@ class NoteRepository @Inject constructor(
|
||||
private val remote: NoteRemote
|
||||
) {
|
||||
|
||||
suspend fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean = false, notify: Boolean = false): List<Note> {
|
||||
return local.getNotes(student).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getNotes(student, semester)
|
||||
val old = local.getNotes(student)
|
||||
|
||||
local.deleteNotes(old.uniqueSubtract(new))
|
||||
local.saveNotes(new.uniqueSubtract(old).onEach {
|
||||
fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getNotes(student) },
|
||||
fetch = { remote.getNotes(student, semester) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteNotes(old uniqueSubtract new)
|
||||
local.saveNotes((new uniqueSubtract old).onEach {
|
||||
if (it.date >= student.registrationDate.toLocalDate()) it.apply {
|
||||
isRead = false
|
||||
if (notify) isNotified = false
|
||||
}
|
||||
})
|
||||
|
||||
local.getNotes(student)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
suspend fun getNotNotifiedNotes(student: Student): List<Note> {
|
||||
return local.getNotes(student).filter { note -> !note.isNotified }
|
||||
fun getNotNotifiedNotes(student: Student): Flow<List<Note>> {
|
||||
return local.getNotes(student).map { it.filter { note -> !note.isNotified } }
|
||||
}
|
||||
|
||||
suspend fun updateNote(note: Note) {
|
||||
return local.updateNotes(listOf(note))
|
||||
local.updateNotes(listOf(note))
|
||||
}
|
||||
|
||||
suspend fun updateNotes(notes: List<Note>) {
|
||||
|
@ -14,13 +14,17 @@ class RecipientRepository @Inject constructor(
|
||||
private val remote: RecipientRemote
|
||||
) {
|
||||
|
||||
suspend fun getRecipients(student: Student, role: Int, unit: ReportingUnit, forceRefresh: Boolean = false): List<Recipient> {
|
||||
return local.getRecipients(student, role, unit).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getRecipients(student, role, unit)
|
||||
val old = local.getRecipients(student, role, unit)
|
||||
suspend fun refreshRecipients(student: Student, role: Int, unit: ReportingUnit) {
|
||||
val new = remote.getRecipients(student, role, unit)
|
||||
val old = local.getRecipients(student, role, unit)
|
||||
|
||||
local.deleteRecipients(old.uniqueSubtract(new))
|
||||
local.saveRecipients(new.uniqueSubtract(old))
|
||||
local.deleteRecipients(old uniqueSubtract new)
|
||||
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)
|
||||
}
|
||||
|
@ -12,23 +12,27 @@ class ReportingUnitRepository @Inject constructor(
|
||||
private val remote: ReportingUnitRemote
|
||||
) {
|
||||
|
||||
suspend fun getReportingUnits(student: Student, forceRefresh: Boolean = false): List<ReportingUnit> {
|
||||
return local.getReportingUnits(student).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getReportingUnits(student)
|
||||
val old = local.getReportingUnits(student)
|
||||
suspend fun refreshReportingUnits(student: Student) {
|
||||
val new = remote.getReportingUnits(student)
|
||||
val old = local.getReportingUnits(student)
|
||||
|
||||
local.deleteReportingUnits(old.uniqueSubtract(new))
|
||||
local.saveReportingUnits(new.uniqueSubtract(old))
|
||||
local.deleteReportingUnits(old.uniqueSubtract(new))
|
||||
local.saveReportingUnits(new.uniqueSubtract(old))
|
||||
}
|
||||
|
||||
suspend fun getReportingUnits(student: Student): List<ReportingUnit> {
|
||||
return local.getReportingUnits(student).ifEmpty {
|
||||
refreshReportingUnits(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 {
|
||||
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.entities.School
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) {
|
||||
@ -15,7 +16,7 @@ class SchoolLocal @Inject constructor(private val schoolDb: SchoolDao) {
|
||||
schoolDb.deleteAll(listOf(school))
|
||||
}
|
||||
|
||||
suspend fun getSchool(semester: Semester): School? {
|
||||
fun getSchool(semester: Semester): Flow<School?> {
|
||||
return schoolDb.load(semester.studentId, semester.classId)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
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.Student
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -12,18 +12,16 @@ class SchoolRepository @Inject constructor(
|
||||
private val remote: SchoolRemote
|
||||
) {
|
||||
|
||||
suspend fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean = false): School {
|
||||
return local.getSchool(semester).takeIf { it != null && !forceRefresh } ?: run {
|
||||
val new = remote.getSchoolInfo(student, semester)
|
||||
val old = local.getSchool(semester)
|
||||
|
||||
fun getSchoolInfo(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it == null || forceRefresh },
|
||||
query = { local.getSchool(semester) },
|
||||
fetch = { remote.getSchoolInfo(student, semester) },
|
||||
saveFetchResult = { old, new ->
|
||||
if (new != old && old != null) {
|
||||
local.deleteSchool(old)
|
||||
local.saveSchool(new)
|
||||
}
|
||||
local.saveSchool(new)
|
||||
|
||||
local.getSchool(semester)!!
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -1,22 +1,24 @@
|
||||
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.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.DispatchersProvider
|
||||
import io.github.wulkanowy.utils.getCurrentOrLast
|
||||
import io.github.wulkanowy.utils.isCurrent
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class SemesterRepository @Inject constructor(
|
||||
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> {
|
||||
return local.getSemesters(student).let { semesters ->
|
||||
suspend fun getSemesters(student: Student, forceRefresh: Boolean = false, refreshOnNoCurrent: Boolean = false) = withContext(dispatchers.backgroundThread) {
|
||||
local.getSemesters(student).let { semesters ->
|
||||
semesters.filter {
|
||||
!forceRefresh && when {
|
||||
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 {
|
||||
return getSemesters(student, forceRefresh).getCurrentOrLast()
|
||||
suspend fun getCurrentSemester(student: Student, forceRefresh: Boolean = false) = withContext(dispatchers.backgroundThread) {
|
||||
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.entities.Student
|
||||
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.encrypt
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class StudentLocal @Inject constructor(
|
||||
private val studentDb: StudentDao,
|
||||
private val dispatchers: DispatchersProvider,
|
||||
private val context: Context
|
||||
) {
|
||||
|
||||
suspend fun saveStudents(students: List<Student>): List<Long> {
|
||||
return studentDb.insertAll(students.map {
|
||||
suspend fun saveStudents(students: List<Student>) = withContext(dispatchers.backgroundThread) {
|
||||
studentDb.insertAll(students.map {
|
||||
if (Sdk.Mode.valueOf(it.loginMode) != Sdk.Mode.API) it.copy(password = encrypt(it.password, context))
|
||||
else it
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun getStudents(decryptPass: Boolean): List<Student> {
|
||||
return studentDb.loadAll().map {
|
||||
suspend fun getStudents(decryptPass: Boolean) = withContext(dispatchers.backgroundThread) {
|
||||
studentDb.loadAll().map {
|
||||
it.apply {
|
||||
if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getStudentById(id: Int): Student? {
|
||||
return studentDb.loadById(id)?.apply {
|
||||
suspend fun getStudentById(id: Int) = withContext(dispatchers.backgroundThread) {
|
||||
studentDb.loadById(id)?.apply {
|
||||
if (Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getCurrentStudent(decryptPass: Boolean): Student? {
|
||||
return studentDb.loadCurrent()?.apply {
|
||||
suspend fun getCurrentStudent(decryptPass: Boolean) = withContext(dispatchers.backgroundThread) {
|
||||
studentDb.loadCurrent()?.apply {
|
||||
if (decryptPass && Sdk.Mode.valueOf(loginMode) != Sdk.Mode.API) password = decrypt(password)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun setCurrentStudent(student: Student) {
|
||||
return studentDb.run {
|
||||
suspend fun setCurrentStudent(student: Student) = withContext(dispatchers.backgroundThread) {
|
||||
studentDb.run {
|
||||
resetCurrent()
|
||||
updateCurrent(student.id)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun logoutStudent(student: Student) {
|
||||
return studentDb.delete(student)
|
||||
suspend fun logoutStudent(student: Student) = withContext(dispatchers.backgroundThread) {
|
||||
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.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Subject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -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.Student
|
||||
import io.github.wulkanowy.data.db.entities.Subject
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -13,15 +13,13 @@ class SubjectRepository @Inject constructor(
|
||||
private val remote: SubjectRemote
|
||||
) {
|
||||
|
||||
suspend fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false): List<Subject> {
|
||||
return local.getSubjects(semester).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getSubjects(student, semester)
|
||||
val old = local.getSubjects(semester)
|
||||
|
||||
local.deleteSubjects(old.uniqueSubtract(new))
|
||||
local.saveSubjects(new.uniqueSubtract(old))
|
||||
|
||||
local.getSubjects(semester)
|
||||
fun getSubjects(student: Student, semester: Semester, forceRefresh: Boolean = false) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getSubjects(semester) },
|
||||
fetch = { remote.getSubjects(student, semester) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteSubjects(old uniqueSubtract new)
|
||||
local.saveSubjects(new uniqueSubtract old)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -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.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Teacher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) {
|
||||
@ -15,7 +16,7 @@ class TeacherLocal @Inject constructor(private val teacherDb: TeacherDao) {
|
||||
teacherDb.deleteAll(teachers)
|
||||
}
|
||||
|
||||
suspend fun getTeachers(semester: Semester): List<Teacher> {
|
||||
fun getTeachers(semester: Semester): Flow<List<Teacher>> {
|
||||
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.Student
|
||||
import io.github.wulkanowy.data.db.entities.Teacher
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -13,15 +13,13 @@ class TeacherRepository @Inject constructor(
|
||||
private val remote: TeacherRemote
|
||||
) {
|
||||
|
||||
suspend fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean = false): List<Teacher> {
|
||||
return local.getTeachers(semester).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getTeachers(student, semester)
|
||||
val old = local.getTeachers(semester)
|
||||
|
||||
local.deleteTeachers(old.uniqueSubtract(new))
|
||||
local.saveTeachers(new.uniqueSubtract(old))
|
||||
|
||||
local.getTeachers(semester)
|
||||
fun getTeachers(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getTeachers(semester) },
|
||||
fetch = { remote.getTeachers(student, semester) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteTeachers(old uniqueSubtract new)
|
||||
local.saveTeachers(new uniqueSubtract old)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -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.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -18,7 +19,7 @@ class TimetableLocal @Inject constructor(private val timetableDb: TimetableDao)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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.Student
|
||||
import io.github.wulkanowy.data.db.entities.Timetable
|
||||
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -18,11 +19,11 @@ class TimetableRepository @Inject constructor(
|
||||
private val schedulerHelper: TimetableNotificationSchedulerHelper
|
||||
) {
|
||||
|
||||
suspend fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean = false): List<Timetable> {
|
||||
return local.getTimetable(semester, start.monday, start.sunday).filter { !forceRefresh }.ifEmpty {
|
||||
val new = remote.getTimetable(student, semester, start.monday, start.sunday)
|
||||
val old = local.getTimetable(semester, start.monday, start.sunday)
|
||||
|
||||
fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { local.getTimetable(semester, start.monday, end.sunday).map { schedulerHelper.scheduleNotifications(it, student); it } },
|
||||
fetch = { remote.getTimetable(student, semester, start.monday, end.sunday) },
|
||||
saveFetchResult = { old, new ->
|
||||
local.deleteTimetable(old.uniqueSubtract(new).also { schedulerHelper.cancelScheduled(it) })
|
||||
local.saveTimetable(new.uniqueSubtract(old).also { schedulerHelper.scheduleNotifications(it, student) }.map { item ->
|
||||
item.also { new ->
|
||||
@ -34,8 +35,7 @@ class TimetableRepository @Inject constructor(
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
local.getTimetable(semester, start.monday, start.sunday)
|
||||
}.filter { it.date in start..end }.also { schedulerHelper.scheduleNotifications(it, student) }
|
||||
}
|
||||
},
|
||||
filterResult = { it.filter { item -> item.date in start..end } }
|
||||
)
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ class AttendanceSummaryWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
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.Student
|
||||
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.sunday
|
||||
import io.reactivex.Completable
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import org.threeten.bp.LocalDate.now
|
||||
@ -13,6 +13,6 @@ import javax.inject.Inject
|
||||
class AttendanceWork @Inject constructor(private val attendanceRepository: AttendanceRepository) : Work {
|
||||
|
||||
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.Student
|
||||
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.sunday
|
||||
import io.reactivex.Completable
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import org.threeten.bp.LocalDate.now
|
||||
@ -15,7 +15,6 @@ class CompletedLessonWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
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 {
|
||||
|
||||
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 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 {
|
||||
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.utils.getCompatColor
|
||||
import io.reactivex.Completable
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import javax.inject.Inject
|
||||
@ -32,14 +33,14 @@ class GradeWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
override fun create(student: Student, semester: Semester): Completable {
|
||||
return rxCompletable { gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable) }
|
||||
.concatWith(Completable.concatArray(rxSingle { gradeRepository.getNotNotifiedGrades(semester) }.flatMapCompletable {
|
||||
return rxCompletable { gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable).waitForResult() }
|
||||
.concatWith(Completable.concatArray(rxSingle { gradeRepository.getNotNotifiedGrades(semester).first() }.flatMapCompletable {
|
||||
if (it.isNotEmpty()) notifyDetails(it)
|
||||
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)
|
||||
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)
|
||||
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.Student
|
||||
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.sunday
|
||||
import io.reactivex.Completable
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import org.threeten.bp.LocalDate.now
|
||||
@ -13,6 +13,6 @@ import javax.inject.Inject
|
||||
class HomeworkWork @Inject constructor(private val homeworkRepository: HomeworkRepository) : Work {
|
||||
|
||||
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.utils.getCompatColor
|
||||
import io.reactivex.Completable
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import kotlinx.coroutines.rx2.rxMaybe
|
||||
import javax.inject.Inject
|
||||
@ -31,8 +32,8 @@ class LuckyNumberWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
override fun create(student: Student, semester: Semester): Completable {
|
||||
return rxMaybe { luckyNumberRepository.getLuckyNumber(student, true, preferencesRepository.isNotificationsEnable) }
|
||||
.flatMap { rxMaybe { luckyNumberRepository.getNotNotifiedLuckyNumber(student) } }
|
||||
return rxMaybe { luckyNumberRepository.getLuckyNumber(student, true, preferencesRepository.isNotificationsEnable).waitForResult() }
|
||||
.flatMap { rxMaybe { luckyNumberRepository.getNotNotifiedLuckyNumber(student).first() } }
|
||||
.flatMapCompletable {
|
||||
notify(it)
|
||||
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.utils.getCompatColor
|
||||
import io.reactivex.Completable
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import javax.inject.Inject
|
||||
@ -32,8 +33,8 @@ class MessageWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
override fun create(student: Student, semester: Semester): Completable {
|
||||
return rxSingle { messageRepository.getMessages(student, semester, RECEIVED, true, preferencesRepository.isNotificationsEnable) }
|
||||
.flatMap { rxSingle { messageRepository.getNotNotifiedMessages(student) } }
|
||||
return rxSingle { messageRepository.getMessages(student, semester, RECEIVED, true, preferencesRepository.isNotificationsEnable).waitForResult() }
|
||||
.flatMap { rxSingle { messageRepository.getNotNotifiedMessages(student).first() } }
|
||||
.flatMapCompletable {
|
||||
if (it.isNotEmpty()) notify(it)
|
||||
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.utils.getCompatColor
|
||||
import io.reactivex.Completable
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import javax.inject.Inject
|
||||
@ -31,8 +32,8 @@ class NoteWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
override fun create(student: Student, semester: Semester): Completable {
|
||||
return rxSingle { noteRepository.getNotes(student, semester, true, preferencesRepository.isNotificationsEnable) }
|
||||
.flatMap { rxSingle { noteRepository.getNotNotifiedNotes(student) } }
|
||||
return rxSingle { noteRepository.getNotes(student, semester, true, preferencesRepository.isNotificationsEnable).waitForResult() }
|
||||
.flatMap { rxSingle { noteRepository.getNotNotifiedNotes(student).first() } }
|
||||
.flatMapCompletable {
|
||||
if (it.isNotEmpty()) notify(it)
|
||||
rxCompletable { noteRepository.updateNotes(it.onEach { note -> note.isNotified = true }) }
|
||||
|
@ -15,10 +15,11 @@ class RecipientWork @Inject constructor(
|
||||
) : Work {
|
||||
|
||||
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 ->
|
||||
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 {
|
||||
|
||||
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 {
|
||||
|
||||
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
|
||||
|
||||
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.Student
|
||||
import io.reactivex.Completable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.takeWhile
|
||||
|
||||
interface Work {
|
||||
|
||||
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
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.reactivex.Completable
|
||||
import io.github.wulkanowy.utils.flowWithResource
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
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 kotlin.coroutines.CoroutineContext
|
||||
|
||||
open class BasePresenter<T : BaseView>(
|
||||
protected val errorHandler: ErrorHandler,
|
||||
protected val studentRepository: StudentRepository,
|
||||
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()
|
||||
|
||||
var view: T? = null
|
||||
|
||||
open fun onAttachView(view: T) {
|
||||
job = Job()
|
||||
this.view = view
|
||||
errorHandler.apply {
|
||||
showErrorMessage = view::showError
|
||||
@ -28,30 +43,48 @@ open class BasePresenter<T : BaseView>(
|
||||
}
|
||||
|
||||
fun onExpiredLoginSelected() {
|
||||
Timber.i("Attempt to switch the student after the session expires")
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent(false) }
|
||||
.flatMapCompletable { rxCompletable { studentRepository.logoutStudent(it) } }
|
||||
.andThen(rxSingle { studentRepository.getSavedStudents(false) })
|
||||
.flatMapCompletable {
|
||||
if (it.isNotEmpty()) {
|
||||
Timber.i("Switching current student")
|
||||
rxCompletable { studentRepository.switchStudent(it[0]) }
|
||||
} else Completable.complete()
|
||||
flowWithResource {
|
||||
val student = studentRepository.getCurrentStudent(false)
|
||||
studentRepository.logoutStudent(student)
|
||||
|
||||
val students = studentRepository.getSavedStudents(false)
|
||||
if (students.isNotEmpty()) {
|
||||
Timber.i("Switching current student")
|
||||
studentRepository.switchStudent(students[0])
|
||||
}
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
Timber.i("Switch student result: Open login view")
|
||||
view?.openClearLoginView()
|
||||
}, {
|
||||
Timber.i("Switch student result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}))
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Attempt to switch the student after the session expires")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Switch student result: Open login view")
|
||||
view?.openClearLoginView()
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Switch student result: An exception occurred")
|
||||
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() {
|
||||
view = null
|
||||
disposable.clear()
|
||||
job.cancel()
|
||||
errorHandler.clear()
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,10 @@ open class ErrorHandler @Inject constructor(protected val resources: Resources,
|
||||
}
|
||||
|
||||
protected open fun proceed(error: Throwable) {
|
||||
showErrorMessage(resources.getString(error), error)
|
||||
when (error) {
|
||||
is ScramblerException, is BadCredentialsException -> onSessionExpired()
|
||||
is NoCurrentStudentException -> onNoCurrentStudent()
|
||||
else -> showErrorMessage(resources.getString(error), error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
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.repositories.appcreator.AppCreatorRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
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
|
||||
|
||||
class ContributorPresenter @Inject constructor(
|
||||
@ -31,10 +33,15 @@ class ContributorPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData() {
|
||||
disposable.add(rxSingle { appCreatorRepository.getAppCreators() }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally { view?.showProgress(false) }
|
||||
.subscribe({ view?.run { updateData(it) } }, { errorHandler.dispatch(it) }))
|
||||
flowWithResource { appCreatorRepository.getAppCreators() }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> view?.showProgress(true)
|
||||
Status.SUCCESS -> view?.run {
|
||||
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) {
|
||||
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) }
|
||||
}
|
||||
|
@ -1,15 +1,22 @@
|
||||
package io.github.wulkanowy.ui.modules.about.license
|
||||
|
||||
import com.mikepenz.aboutlibraries.entity.Library
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.DispatchersProvider
|
||||
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
|
||||
|
||||
class LicensePresenter @Inject constructor(
|
||||
schedulers: SchedulersProvider,
|
||||
private val dispatchers: DispatchersProvider,
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository
|
||||
) : BasePresenter<LicenseView>(errorHandler, studentRepository, schedulers) {
|
||||
@ -21,14 +28,22 @@ class LicensePresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onItemSelected(library: Library) {
|
||||
view?.run { library.license?.licenseDescription?.let { openLicense(it) } }
|
||||
view?.run { library.licenses?.firstOrNull()?.licenseDescription?.let { openLicense(it) } }
|
||||
}
|
||||
|
||||
private fun loadData() {
|
||||
disposable.add(Single.fromCallable { view?.appLibraries.orEmpty() }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnEvent { _, _ -> view?.showProgress(false) }
|
||||
.subscribe({ view?.run { updateData(it) } }, { errorHandler.dispatch(it) }))
|
||||
flowWithResource {
|
||||
withContext(dispatchers.backgroundThread) {
|
||||
view?.appLibraries.orEmpty()
|
||||
}
|
||||
}.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
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.repositories.logger.LoggerRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
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 javax.inject.Inject
|
||||
|
||||
@ -23,16 +25,19 @@ class LogViewerPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onShareLogsSelected(): Boolean {
|
||||
disposable.add(rxSingle { loggerRepository.getLogFiles() }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({ files ->
|
||||
Timber.i("Loading logs files result: ${files.joinToString { it.name }}")
|
||||
view?.shareLogs(files)
|
||||
}, {
|
||||
Timber.i("Loading logs files result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}))
|
||||
flowWithResource { loggerRepository.getLogFiles() }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.d("Loading logs files started")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading logs files result: ${it.data!!.joinToString { file -> file.name }}")
|
||||
view?.shareLogs(it.data)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading logs files result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.launch("share")
|
||||
return true
|
||||
}
|
||||
|
||||
@ -41,15 +46,18 @@ class LogViewerPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadLogFile() {
|
||||
disposable.add(rxSingle { loggerRepository.getLastLogLines() }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
Timber.i("Loading last log file result: load ${it.size} lines")
|
||||
view?.setLines(it)
|
||||
}, {
|
||||
Timber.i("Loading last log file result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}))
|
||||
flowWithResource { loggerRepository.getLastLogLines() }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.d("Loading last log file started")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading last log file result: load ${it.data!!.size} lines")
|
||||
view?.setLines(it.data)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading last log file result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.launch("file")
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
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.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.services.sync.SyncManager
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.reactivex.Single
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import io.github.wulkanowy.utils.afterLoading
|
||||
import io.github.wulkanowy.utils.flowWithResource
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -37,20 +38,20 @@ class AccountPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onLogoutConfirm() {
|
||||
Timber.i("Attempt to logout current user ")
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent(false) }
|
||||
.flatMapCompletable { rxCompletable { studentRepository.logoutStudent(it) } }
|
||||
.andThen(rxSingle { studentRepository.getSavedStudents(false) })
|
||||
.flatMap {
|
||||
if (it.isNotEmpty()) rxCompletable { studentRepository.switchStudent(it[0]) }.toSingle { it }
|
||||
else Single.just(it)
|
||||
flowWithResource {
|
||||
val student = studentRepository.getCurrentStudent(false)
|
||||
studentRepository.logoutStudent(student)
|
||||
|
||||
val students = studentRepository.getSavedStudents(false)
|
||||
if (students.isNotEmpty()) {
|
||||
studentRepository.switchStudent(students[0])
|
||||
}
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally { view?.dismissView() }
|
||||
.subscribe({
|
||||
view?.apply {
|
||||
if (it.isEmpty()) {
|
||||
students
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Attempt to logout current user ")
|
||||
Status.SUCCESS -> view?.run {
|
||||
if (it.data!!.isEmpty()) {
|
||||
Timber.i("Logout result: Open login view")
|
||||
syncManager.stopSyncWorker()
|
||||
openClearLoginView()
|
||||
@ -59,30 +60,35 @@ class AccountPresenter @Inject constructor(
|
||||
recreateMainView()
|
||||
}
|
||||
}
|
||||
}, {
|
||||
Timber.i("Logout result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}))
|
||||
Status.ERROR -> {
|
||||
Timber.i("Logout result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.dismissView()
|
||||
}.launch("logout")
|
||||
}
|
||||
|
||||
fun onItemSelected(student: Student) {
|
||||
Timber.i("Select student item ${student.id}")
|
||||
if (student.isCurrent) {
|
||||
view?.dismissView()
|
||||
} else {
|
||||
Timber.i("Attempt to change a student")
|
||||
disposable.add(rxSingle { studentRepository.switchStudent(student) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally { view?.dismissView() }
|
||||
.subscribe({
|
||||
} else flowWithResource { studentRepository.switchStudent(student) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Attempt to change a student")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Change a student result: Success")
|
||||
view?.recreateMainView()
|
||||
}, {
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Change a student result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}))
|
||||
}
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.dismissView()
|
||||
}.launch("switch")
|
||||
}
|
||||
|
||||
private fun createAccountItems(items: List<Student>): List<AccountItem<*>> {
|
||||
@ -94,17 +100,18 @@ class AccountPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData() {
|
||||
Timber.i("Loading account data started")
|
||||
disposable.add(rxSingle { studentRepository.getSavedStudents(false) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.map { createAccountItems(it) }
|
||||
.subscribe({
|
||||
Timber.i("Loading account result: Success")
|
||||
view?.updateData(it)
|
||||
}, {
|
||||
Timber.i("Loading account result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}))
|
||||
flowWithResource { studentRepository.getSavedStudents(false) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading account data started")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading account result: Success")
|
||||
view?.updateData(createAccountItems(it.data!!))
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading account result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.github.wulkanowy.ui.modules.attendance
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
|
||||
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.utils.FirebaseAnalyticsHelper
|
||||
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.isHolidays
|
||||
import io.github.wulkanowy.utils.nextSchoolDay
|
||||
import io.github.wulkanowy.utils.previousOrSameSchoolDay
|
||||
import io.github.wulkanowy.utils.previousSchoolDay
|
||||
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.now
|
||||
import org.threeten.bp.LocalDate.ofEpochDay
|
||||
@ -168,100 +174,93 @@ class AttendancePresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun setBaseDateOnHolidays() {
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { rxSingle { semesterRepository.getCurrentSemester(it) } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
||||
currentDate = baseDate
|
||||
reloadNavigation()
|
||||
}) {
|
||||
Timber.i("Loading semester result: An exception occurred")
|
||||
})
|
||||
flow {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
emit(semesterRepository.getCurrentSemester(student))
|
||||
}.catch {
|
||||
Timber.i("Loading semester result: An exception occurred")
|
||||
}.onEach {
|
||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
||||
currentDate = baseDate
|
||||
reloadNavigation()
|
||||
}.launch("holidays")
|
||||
}
|
||||
|
||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading attendance data started")
|
||||
currentDate = date
|
||||
disposable.apply {
|
||||
clear()
|
||||
add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { student ->
|
||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
||||
rxSingle { attendanceRepository.getAttendance(student, semester, date, date, forceRefresh) }
|
||||
}
|
||||
}
|
||||
.map { list ->
|
||||
if (prefRepository.isShowPresent) list
|
||||
else list.filter { !it.presence }
|
||||
}
|
||||
.map { items -> items.sortedBy { it.number } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
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)
|
||||
showEmpty(it.isEmpty())
|
||||
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.isNotEmpty())
|
||||
showExcuseButton(it.any { item -> item.excusable })
|
||||
showContent(it.data.isNotEmpty())
|
||||
showExcuseButton(it.data.any { item -> item.excusable })
|
||||
}
|
||||
analytics.logEvent(
|
||||
"load_data",
|
||||
"type" to "attendance",
|
||||
"items" to it.size,
|
||||
"force_refresh" to forceRefresh
|
||||
"items" to it.data!!.size
|
||||
)
|
||||
}) {
|
||||
Timber.i("Loading attendance result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading attendance result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun excuseAbsence(reason: String?, toExcuseList: List<Attendance>) {
|
||||
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) }
|
||||
}
|
||||
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")
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
showExcuseButton(false)
|
||||
}
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.apply {
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
showExcuseButton(false)
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Excusing for absence result: Success")
|
||||
analytics.logEvent("excuse_absence", "items" to attendanceToExcuseList.size)
|
||||
attendanceToExcuseList.clear()
|
||||
view?.apply {
|
||||
view?.run {
|
||||
showExcuseButton(false)
|
||||
showMessage(excuseSuccessString)
|
||||
showContent(true)
|
||||
showProgress(false)
|
||||
}
|
||||
loadData(currentDate, true)
|
||||
}) {
|
||||
loadData(currentDate, forceRefresh = true)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Excusing for absence result: An exception occurred")
|
||||
view?.showProgress(false)
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
}
|
||||
errorHandler.dispatch(it.error!!)
|
||||
loadData(currentDate)
|
||||
}
|
||||
}
|
||||
}.launch("excuse")
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
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.repositories.attendancesummary.AttendanceSummaryRepository
|
||||
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.utils.FirebaseAnalyticsHelper
|
||||
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 timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
@ -73,46 +76,43 @@ class AttendanceSummaryPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(subjectId: Int, forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading attendance summary data started")
|
||||
currentSubjectId = subjectId
|
||||
disposable.apply {
|
||||
clear()
|
||||
add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { student ->
|
||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap {
|
||||
rxSingle { attendanceSummaryRepository.getAttendanceSummary(student, it, subjectId, forceRefresh) }
|
||||
}
|
||||
}
|
||||
.map { items -> items.sortedByDescending { if (it.month.value <= Month.JUNE.value) it.month.value + 12 else it.month.value } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
attendanceSummaryRepository.getAttendanceSummary(student, semester, 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.isEmpty())
|
||||
showContent(it.isNotEmpty())
|
||||
updateDataSet(it)
|
||||
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.size,
|
||||
"force_refresh" to forceRefresh,
|
||||
"items" to it.data!!.size,
|
||||
"item_id" to subjectId
|
||||
)
|
||||
}) {
|
||||
Timber.i("Loading attendance summary result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading attendance summary result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
@ -127,27 +127,27 @@ class AttendanceSummaryPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadSubjects() {
|
||||
Timber.i("Loading attendance summary subjects started")
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { student ->
|
||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
||||
rxSingle { subjectRepository.getSubjects(student, semester) }
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
subjectRepository.getSubjects(student, semester)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading attendance summary subjects started")
|
||||
Status.SUCCESS -> {
|
||||
subjects = it.data!!
|
||||
|
||||
Timber.i("Loading attendance summary subjects result: Success")
|
||||
view?.run {
|
||||
view?.updateSubjects(ArrayList(it.data.map { subject -> subject.name }))
|
||||
showSubjects(true)
|
||||
}
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading attendance summary subjects result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
.doOnSuccess { subjects = it }
|
||||
.map { ArrayList(it.map { subject -> subject.name }) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
Timber.i("Loading attendance summary subjects result: Success")
|
||||
view?.run {
|
||||
view?.updateSubjects(it)
|
||||
showSubjects(true)
|
||||
}
|
||||
}, {
|
||||
Timber.i("Loading attendance summary subjects result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
)
|
||||
}.launch("subjects")
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
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.repositories.exam.ExamRepository
|
||||
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.utils.FirebaseAnalyticsHelper
|
||||
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.isHolidays
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
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.now
|
||||
import org.threeten.bp.LocalDate.ofEpochDay
|
||||
@ -90,59 +95,54 @@ class ExamPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun setBaseDateOnHolidays() {
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { rxSingle { semesterRepository.getCurrentSemester(it) } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
||||
currentDate = baseDate
|
||||
reloadNavigation()
|
||||
}) {
|
||||
Timber.i("Loading semester result: An exception occurred")
|
||||
})
|
||||
flow {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
emit(semesterRepository.getCurrentSemester(student))
|
||||
}.catch {
|
||||
Timber.i("Loading semester result: An exception occurred")
|
||||
}.onEach {
|
||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
||||
currentDate = baseDate
|
||||
reloadNavigation()
|
||||
}.launch("holidays")
|
||||
}
|
||||
|
||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading exam data started")
|
||||
currentDate = date
|
||||
disposable.apply {
|
||||
clear()
|
||||
add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { student ->
|
||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
||||
rxSingle { examRepository.getExams(student, semester, currentDate.monday, currentDate.sunday, forceRefresh) }
|
||||
}
|
||||
}
|
||||
.map { createExamItems(it) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
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(it)
|
||||
showEmpty(it.isEmpty())
|
||||
updateData(createExamItems(it.data!!))
|
||||
showEmpty(it.data.isEmpty())
|
||||
showErrorView(false)
|
||||
showContent(it.isNotEmpty())
|
||||
showContent(it.data.isNotEmpty())
|
||||
}
|
||||
analytics.logEvent(
|
||||
"load_data",
|
||||
"type" to "exam",
|
||||
"items" to it.size,
|
||||
"force_refresh" to forceRefresh
|
||||
"items" to it.data!!.size
|
||||
)
|
||||
}) {
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading exam result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
}
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
|
@ -1,5 +1,7 @@
|
||||
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.GradeSummary
|
||||
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.utils.calcAverage
|
||||
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
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
class GradeAverageProvider @Inject constructor(
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val gradeRepository: GradeRepository,
|
||||
@ -25,63 +36,64 @@ class GradeAverageProvider @Inject constructor(
|
||||
|
||||
private val minusModifier get() = preferencesRepository.gradeMinusModifier
|
||||
|
||||
suspend fun getGradesDetailsWithAverage(student: Student, semesterId: Int, forceRefresh: Boolean = false): List<GradeDetailsWithAverage> {
|
||||
return semesterRepository.getSemesters(student).let { semesters ->
|
||||
when (preferencesRepository.gradeAverageMode) {
|
||||
ONE_SEMESTER -> getSemesterDetailsWithAverage(student, semesters.single { it.semesterId == semesterId }, forceRefresh)
|
||||
BOTH_SEMESTERS -> calculateBothSemestersAverage(student, semesters, semesterId, forceRefresh)
|
||||
ALL_YEAR -> calculateAllYearAverage(student, semesters, semesterId, forceRefresh)
|
||||
}
|
||||
}
|
||||
}
|
||||
fun getGradesDetailsWithAverage(student: Student, semesterId: Int, forceRefresh: Boolean) = flowWithResourceIn {
|
||||
val semesters = semesterRepository.getSemesters(student)
|
||||
|
||||
private suspend fun calculateBothSemestersAverage(student: Student, semesters: List<Semester>, semesterId: Int, forceRefresh: Boolean): List<GradeDetailsWithAverage> {
|
||||
when (preferencesRepository.gradeAverageMode) {
|
||||
ONE_SEMESTER -> getSemesterDetailsWithAverage(student, semesters.single { it.semesterId == semesterId }, forceRefresh)
|
||||
BOTH_SEMESTERS -> calculateBothSemestersAverage(student, semesters, semesterId, forceRefresh)
|
||||
ALL_YEAR -> calculateAllYearAverage(student, semesters, semesterId, forceRefresh)
|
||||
}
|
||||
}.distinctUntilChanged()
|
||||
|
||||
private fun calculateBothSemestersAverage(student: Student, semesters: List<Semester>, semesterId: Int, forceRefresh: Boolean): Flow<Resource<List<GradeDetailsWithAverage>>> {
|
||||
val selectedSemester = semesters.single { it.semesterId == semesterId }
|
||||
val firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 }
|
||||
|
||||
return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).let { selectedDetails ->
|
||||
val isAnyAverage = selectedDetails.any { it.average != .0 }
|
||||
return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).flatMapConcat { selectedDetails ->
|
||||
val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 }
|
||||
|
||||
if (selectedSemester != firstSemester) {
|
||||
getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).let { secondDetails ->
|
||||
selectedDetails.map { selected ->
|
||||
val second = secondDetails.singleOrNull { it.subject == selected.subject }
|
||||
getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).map { secondDetails ->
|
||||
secondDetails.copy(data = selectedDetails.data?.map { selected ->
|
||||
val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject }
|
||||
selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) {
|
||||
val selectedGrades = selected.grades.updateModifiers(student).calcAverage()
|
||||
(selectedGrades + (second?.grades?.updateModifiers(student)?.calcAverage() ?: selectedGrades)) / 2
|
||||
} else (selected.average + (second?.average ?: selected.average)) / 2)
|
||||
}
|
||||
}
|
||||
} else selectedDetails
|
||||
})
|
||||
}.filter { it.status != Status.LOADING }.filter { it.data != null }
|
||||
} 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 firstSemester = semesters.single { it.diaryId == selectedSemester.diaryId && it.semesterName == 1 }
|
||||
|
||||
return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).let { selectedDetails ->
|
||||
val isAnyAverage = selectedDetails.any { it.average != .0 }
|
||||
return getSemesterDetailsWithAverage(student, selectedSemester, forceRefresh).flatMapConcat { selectedDetails ->
|
||||
val isAnyAverage = selectedDetails.data.orEmpty().any { it.average != .0 }
|
||||
|
||||
if (selectedSemester != firstSemester) {
|
||||
getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).let { secondDetails ->
|
||||
selectedDetails.map { selected ->
|
||||
val second = secondDetails.singleOrNull { it.subject == selected.subject }
|
||||
getSemesterDetailsWithAverage(student, firstSemester, forceRefresh).map { secondDetails ->
|
||||
secondDetails.copy(data = selectedDetails.data?.map { selected ->
|
||||
val second = secondDetails.data.orEmpty().singleOrNull { it.subject == selected.subject }
|
||||
selected.copy(average = if (!isAnyAverage || preferencesRepository.gradeAverageForceCalc) {
|
||||
(selected.grades.updateModifiers(student) + second?.grades?.updateModifiers(student).orEmpty()).calcAverage()
|
||||
} else selected.average)
|
||||
}
|
||||
}
|
||||
} else selectedDetails
|
||||
})
|
||||
}.filter { it.status != Status.LOADING }.filter { it.data != null }
|
||||
} else flowOf(selectedDetails)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getSemesterDetailsWithAverage(student: Student, semester: Semester, forceRefresh: Boolean): List<GradeDetailsWithAverage> {
|
||||
return gradeRepository.getGrades(student, semester, forceRefresh).let { (details, summaries) ->
|
||||
val isAnyAverage = summaries.any { it.average != .0 }
|
||||
val allGrades = details.groupBy { it.subject }
|
||||
private fun getSemesterDetailsWithAverage(student: Student, semester: Semester, forceRefresh: Boolean): Flow<Resource<List<GradeDetailsWithAverage>>> {
|
||||
return gradeRepository.getGrades(student, semester, forceRefresh = forceRefresh).map { res ->
|
||||
val (details, summaries) = res.data ?: null to null
|
||||
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()
|
||||
GradeDetailsWithAverage(
|
||||
subject = summary.subject,
|
||||
@ -92,7 +104,7 @@ class GradeAverageProvider @Inject constructor(
|
||||
summary = summary,
|
||||
grades = grades
|
||||
)
|
||||
}
|
||||
}, res.error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
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.repositories.semester.SemesterRepository
|
||||
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.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.flowWithResource
|
||||
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 java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
import javax.inject.Inject
|
||||
|
||||
class GradePresenter @Inject constructor(
|
||||
@ -99,29 +101,33 @@ class GradePresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData() {
|
||||
Timber.i("Loading grade data started")
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { rxSingle { semesterRepository.getSemesters(it, refreshOnNoCurrent = true) } }
|
||||
.delay(200, MILLISECONDS)
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
val current = it.getCurrentOrLast()
|
||||
selectedIndex = if (selectedIndex == 0) current.semesterName else selectedIndex
|
||||
schoolYear = current.schoolYear
|
||||
semesters = it.filter { semester -> semester.diaryId == current.diaryId }
|
||||
view?.setCurrentSemesterName(current.semesterName, schoolYear)
|
||||
flowWithResource {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
delay(200)
|
||||
semesterRepository.getSemesters(student, refreshOnNoCurrent = true)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading grade data started")
|
||||
Status.SUCCESS -> {
|
||||
val current = it.data!!.getCurrentOrLast()
|
||||
selectedIndex = if (selectedIndex == 0) current.semesterName else selectedIndex
|
||||
schoolYear = current.schoolYear
|
||||
semesters = it.data.filter { semester -> semester.diaryId == current.diaryId }
|
||||
view?.setCurrentSemesterName(current.semesterName, schoolYear)
|
||||
|
||||
view?.run {
|
||||
Timber.i("Loading grade result: Attempt load index $currentPageIndex")
|
||||
loadChild(currentPageIndex)
|
||||
showErrorView(false)
|
||||
showSemesterSwitch(true)
|
||||
view?.run {
|
||||
Timber.i("Loading grade result: Attempt load index $currentPageIndex")
|
||||
loadChild(currentPageIndex)
|
||||
showErrorView(false)
|
||||
showSemesterSwitch(true)
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Timber.i("Loading grade result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading grade result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
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.repositories.grade.GradeRepository
|
||||
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.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import io.github.wulkanowy.utils.afterLoading
|
||||
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 javax.inject.Inject
|
||||
|
||||
@ -41,7 +45,9 @@ class GradeDetailsPresenter @Inject constructor(
|
||||
|
||||
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
||||
currentSemesterId = semesterId
|
||||
|
||||
loadData(semesterId, forceRefresh)
|
||||
if (!forceRefresh) view?.showErrorView(false)
|
||||
}
|
||||
|
||||
fun onGradeItemSelected(grade: Grade, position: Int) {
|
||||
@ -63,24 +69,24 @@ class GradeDetailsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onMarkAsReadSelected(): Boolean {
|
||||
Timber.i("Select mark grades as read")
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { rxSingle { semesterRepository.getSemesters(it) } }
|
||||
.flatMap { rxSingle { gradeRepository.getUnreadGrades(it.first { item -> item.semesterId == currentSemesterId }) } }
|
||||
.map { it.map { grade -> grade.apply { isRead = true } } }
|
||||
.flatMapCompletable {
|
||||
Timber.i("Mark as read ${it.size} grades")
|
||||
rxCompletable { gradeRepository.updateGrades(it) }
|
||||
flowWithResource {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semesters = semesterRepository.getSemesters(student)
|
||||
val semester = semesters.first { item -> item.semesterId == currentSemesterId }
|
||||
val unreadGrades = gradeRepository.getUnreadGrades(semester).first()
|
||||
|
||||
Timber.i("Mark as read ${unreadGrades.size} grades")
|
||||
gradeRepository.updateGrades(unreadGrades.map { it.apply { isRead = true } })
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Select mark grades as read")
|
||||
Status.SUCCESS -> Timber.i("Mark as read result: Success")
|
||||
Status.ERROR -> {
|
||||
Timber.i("Mark as read result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
Timber.i("Mark as read result: Success")
|
||||
loadData(currentSemesterId, false)
|
||||
}, {
|
||||
Timber.i("Mark as read result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}))
|
||||
}.launch("mark")
|
||||
return true
|
||||
}
|
||||
|
||||
@ -119,7 +125,7 @@ class GradeDetailsPresenter @Inject constructor(
|
||||
showEmpty(false)
|
||||
clearView()
|
||||
}
|
||||
disposable.clear()
|
||||
cancelJobs("load")
|
||||
}
|
||||
|
||||
fun updateMarkAsDoneButton() {
|
||||
@ -127,43 +133,46 @@ class GradeDetailsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
|
||||
Timber.i("Loading grade details data started")
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { rxSingle { averageProvider.getGradesDetailsWithAverage(it, semesterId, forceRefresh) } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally {
|
||||
view?.run {
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
notifyParentDataLoaded(semesterId)
|
||||
}
|
||||
}
|
||||
.subscribe({ grades ->
|
||||
Timber.i("Loading grade details result: Success")
|
||||
newGradesAmount = grades.sumBy { it.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } }
|
||||
updateMarkAsDoneButton()
|
||||
view?.run {
|
||||
showEmpty(grades.isEmpty())
|
||||
showErrorView(false)
|
||||
showContent(grades.isNotEmpty())
|
||||
updateData(
|
||||
data = createGradeItems(grades),
|
||||
isGradeExpandable = preferencesRepository.isGradeExpandable,
|
||||
gradeColorTheme = preferencesRepository.gradeColorTheme
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading grade details data started")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading grade details result: Success")
|
||||
newGradesAmount = it.data!!.sumBy { item -> item.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } }
|
||||
updateMarkAsDoneButton()
|
||||
val items = createGradeItems(it.data)
|
||||
view?.run {
|
||||
showEmpty(items.isEmpty())
|
||||
showErrorView(false)
|
||||
showContent(items.isNotEmpty())
|
||||
updateData(
|
||||
data = items,
|
||||
isGradeExpandable = preferencesRepository.isGradeExpandable,
|
||||
gradeColorTheme = preferencesRepository.gradeColorTheme
|
||||
)
|
||||
}
|
||||
analytics.logEvent(
|
||||
"load_data",
|
||||
"type" to "grade_details",
|
||||
"items" to it.data.size
|
||||
)
|
||||
}
|
||||
analytics.logEvent(
|
||||
"load_data",
|
||||
"type" to "grade_details",
|
||||
"items" to grades.size,
|
||||
"force_refresh" to forceRefresh
|
||||
)
|
||||
}) {
|
||||
Timber.i("Loading grade details result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading grade details result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
notifyParentDataLoaded(semesterId)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
@ -197,15 +206,15 @@ class GradeDetailsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun updateGrade(grade: Grade) {
|
||||
Timber.i("Attempt to update grade ${grade.id}")
|
||||
disposable.add(rxCompletable { gradeRepository.updateGrade(grade) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
Timber.i("Update grade result: Success")
|
||||
}) { error ->
|
||||
Timber.i("Update grade result: An exception occurred")
|
||||
errorHandler.dispatch(error)
|
||||
})
|
||||
flowWithResource { gradeRepository.updateGrade(grade) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Attempt to update grade ${grade.id}")
|
||||
Status.SUCCESS -> Timber.i("Update grade result: Success")
|
||||
Status.ERROR -> {
|
||||
Timber.i("Update grade result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.launch("update")
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
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.repositories.gradestatistics.GradeStatisticsRepository
|
||||
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.utils.FirebaseAnalyticsHelper
|
||||
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 javax.inject.Inject
|
||||
|
||||
@ -46,6 +49,7 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
||||
currentSemesterId = semesterId
|
||||
loadSubjects()
|
||||
if (!forceRefresh) view?.showErrorView(false)
|
||||
loadDataByType(semesterId, currentSubjectName, currentType, forceRefresh)
|
||||
}
|
||||
|
||||
@ -65,7 +69,7 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
showEmpty(false)
|
||||
clearView()
|
||||
}
|
||||
disposable.clear()
|
||||
cancelJobs("load")
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
@ -103,7 +107,7 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
fun onTypeChange() {
|
||||
val type = view?.currentType ?: ViewType.POINTS
|
||||
Timber.i("Select grade stats semester: $type")
|
||||
disposable.clear()
|
||||
cancelJobs("load")
|
||||
view?.run {
|
||||
showContent(false)
|
||||
showProgress(true)
|
||||
@ -116,77 +120,77 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadSubjects() {
|
||||
Timber.i("Loading grade stats subjects started")
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { student ->
|
||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
||||
rxSingle { subjectRepository.getSubjects(student, semester) }
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
subjectRepository.getSubjects(student, semester)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading grade stats subjects started")
|
||||
Status.SUCCESS -> {
|
||||
subjects = it.data!!
|
||||
|
||||
Timber.i("Loading grade stats subjects result: Success")
|
||||
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")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
.doOnSuccess { subjects = it }
|
||||
.map { ArrayList(it.map { subject -> subject.name }) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
Timber.i("Loading grade stats subjects result: Success")
|
||||
view?.updateSubjects(it)
|
||||
}, {
|
||||
Timber.i("Loading grade stats subjects result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
)
|
||||
}.launch("subjects")
|
||||
}
|
||||
|
||||
private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) {
|
||||
currentSubjectName = if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName
|
||||
currentType = type
|
||||
|
||||
Timber.i("Loading grade stats data started")
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { student ->
|
||||
rxSingle { semesterRepository.getSemesters(student) }.flatMap { semesters ->
|
||||
val semester = semesters.first { item -> item.semesterId == semesterId }
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semesters = semesterRepository.getSemesters(student)
|
||||
val semester = semesters.first { item -> item.semesterId == semesterId }
|
||||
|
||||
rxSingle {
|
||||
with(gradeStatisticsRepository) {
|
||||
when (type) {
|
||||
ViewType.SEMESTER -> getGradesStatistics(student, semester, currentSubjectName, true, forceRefresh)
|
||||
ViewType.PARTIAL -> getGradesStatistics(student, semester, currentSubjectName, false, forceRefresh)
|
||||
ViewType.POINTS -> getGradesPointsStatistics(student, semester, currentSubjectName, forceRefresh)
|
||||
}
|
||||
}
|
||||
with(gradeStatisticsRepository) {
|
||||
when (type) {
|
||||
ViewType.SEMESTER -> getGradesStatistics(student, semester, currentSubjectName, true, forceRefresh)
|
||||
ViewType.PARTIAL -> getGradesStatistics(student, semester, currentSubjectName, false, 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!!)
|
||||
}
|
||||
}
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally {
|
||||
view?.run {
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
notifyParentDataLoaded(semesterId)
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
notifyParentDataLoaded(semesterId)
|
||||
}
|
||||
.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)
|
||||
})
|
||||
}.launch("load")
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
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.repositories.student.StudentRepository
|
||||
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.utils.FirebaseAnalyticsHelper
|
||||
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 javax.inject.Inject
|
||||
|
||||
@ -30,36 +33,45 @@ class GradeSummaryPresenter @Inject constructor(
|
||||
|
||||
fun onParentViewLoadData(semesterId: Int, forceRefresh: Boolean) {
|
||||
Timber.i("Loading grade summary data started")
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { rxSingle { averageProvider.getGradesDetailsWithAverage(it, semesterId, forceRefresh) } }
|
||||
.map { createGradeSummaryItems(it) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally {
|
||||
view?.run {
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
notifyParentDataLoaded(semesterId)
|
||||
|
||||
loadData(semesterId, forceRefresh)
|
||||
if (!forceRefresh) view?.showErrorView(false)
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
}.subscribe({
|
||||
Timber.i("Loading grade summary result: Success")
|
||||
view?.run {
|
||||
showEmpty(it.isEmpty())
|
||||
showContent(it.isNotEmpty())
|
||||
showErrorView(false)
|
||||
updateData(it)
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading grade summary result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
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)
|
||||
})
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
notifyParentDataLoaded(semesterId)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
@ -105,7 +117,7 @@ class GradeSummaryPresenter @Inject constructor(
|
||||
showEmpty(false)
|
||||
clearView()
|
||||
}
|
||||
disposable.clear()
|
||||
cancelJobs("load")
|
||||
}
|
||||
|
||||
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() {
|
||||
with(homeworkAdapter) {
|
||||
items = emptyList()
|
||||
|
@ -1,5 +1,6 @@
|
||||
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.repositories.homework.HomeworkRepository
|
||||
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.utils.FirebaseAnalyticsHelper
|
||||
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.isHolidays
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||
import io.github.wulkanowy.utils.sunday
|
||||
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.ofEpochDay
|
||||
import timber.log.Timber
|
||||
@ -79,64 +84,54 @@ class HomeworkPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun setBaseDateOnHolidays() {
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { rxSingle { semesterRepository.getCurrentSemester(it) } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
||||
currentDate = baseDate
|
||||
reloadNavigation()
|
||||
}) {
|
||||
Timber.i("Loading semester result: An exception occurred")
|
||||
})
|
||||
}
|
||||
|
||||
fun reloadData() {
|
||||
loadData(currentDate, false)
|
||||
flow {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
emit(semesterRepository.getCurrentSemester(student))
|
||||
}.catch {
|
||||
Timber.i("Loading semester result: An exception occurred")
|
||||
}.onEach {
|
||||
baseDate = baseDate.getLastSchoolDayIfHoliday(it.schoolYear)
|
||||
currentDate = baseDate
|
||||
reloadNavigation()
|
||||
}.launch("holidays")
|
||||
}
|
||||
|
||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading homework data started")
|
||||
currentDate = date
|
||||
disposable.apply {
|
||||
clear()
|
||||
add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { student ->
|
||||
rxSingle { semesterRepository.getCurrentSemester(student) }.flatMap { semester ->
|
||||
rxSingle { homeworkRepository.getHomework(student, semester, currentDate, currentDate, forceRefresh) }
|
||||
}
|
||||
}
|
||||
.map { createHomeworkItem(it) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
homeworkRepository.getHomework(student, semester, date, date, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading homework data started")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading homework result: Success")
|
||||
view?.apply {
|
||||
updateData(it)
|
||||
showEmpty(it.isEmpty())
|
||||
updateData(createHomeworkItem(it.data!!))
|
||||
showEmpty(it.data.isEmpty())
|
||||
showErrorView(false)
|
||||
showContent(it.isNotEmpty())
|
||||
showContent(it.data.isNotEmpty())
|
||||
}
|
||||
analytics.logEvent(
|
||||
"load_data",
|
||||
"type" to "homework",
|
||||
"items" to it.size,
|
||||
"force_refresh" to forceRefresh
|
||||
"items" to it.data!!.size
|
||||
)
|
||||
}) {
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading homework result: An exception occurred")
|
||||
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
}
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
|
@ -73,7 +73,6 @@ class HomeworkDetailsDialog : BaseDialogFragment<DialogHomeworkBinding>(), Homew
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.wulkanowy.ui.modules.homework.details
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.entities.Homework
|
||||
import io.github.wulkanowy.data.repositories.homework.HomeworkRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
@ -7,7 +8,8 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
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 javax.inject.Inject
|
||||
|
||||
@ -26,20 +28,19 @@ class HomeworkDetailsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun toggleDone(homework: Homework) {
|
||||
Timber.i("Homework details update start")
|
||||
disposable.add(rxSingle { homeworkRepository.toggleDone(homework) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
Timber.i("Homework details update: Success")
|
||||
view?.run {
|
||||
updateMarkAsDoneLabel(homework.isDone)
|
||||
flowWithResource { homeworkRepository.toggleDone(homework) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Homework details update start")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Homework details update: Success")
|
||||
view?.updateMarkAsDoneLabel(homework.isDone)
|
||||
analytics.logEvent("homework_mark_as_done")
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Homework details update result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
analytics.logEvent("homework_mark_as_done")
|
||||
}) {
|
||||
Timber.i("Homework details update result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}
|
||||
)
|
||||
}.launch("toggle")
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.wulkanowy.ui.modules.login.advanced
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
@ -7,9 +8,10 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.afterLoading
|
||||
import io.github.wulkanowy.utils.flowWithResource
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import io.reactivex.Single
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -126,35 +128,42 @@ class LoginAdvancedPresenter @Inject constructor(
|
||||
fun onSignInClick() {
|
||||
if (!validateCredentials()) return
|
||||
|
||||
disposable.add(getStudentsAppropriatesToLoginType()
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.apply {
|
||||
flowWithResource { getStudentsAppropriatesToLoginType() }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> view?.run {
|
||||
Timber.i("Login started")
|
||||
hideSoftKeyboard()
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
}
|
||||
Timber.i("Login started")
|
||||
}
|
||||
.doFinally {
|
||||
view?.apply {
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Login result: Success")
|
||||
analytics.logEvent("registration_form",
|
||||
"success" to true,
|
||||
"students" to it.data!!.size,
|
||||
"error" to "No error"
|
||||
)
|
||||
view?.notifyParentAccountLogged(it.data)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Login result: An exception occurred")
|
||||
analytics.logEvent(
|
||||
"registration_form",
|
||||
"success" to false, "students" to -1,
|
||||
"error" to it.error!!.message.ifNullOrBlank { "No message" }
|
||||
)
|
||||
loginErrorHandler.dispatch(it.error)
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
Timber.i("Login result: Success")
|
||||
analytics.logEvent("registration_form", "success" to true, "students" to it.size, "error" to "No error")
|
||||
view?.notifyParentAccountLogged(it)
|
||||
}, {
|
||||
Timber.i("Login result: An exception occurred")
|
||||
analytics.logEvent("registration_form", "success" to false, "students" to -1, "error" to it.message.ifNullOrBlank { "No message" })
|
||||
loginErrorHandler.dispatch(it)
|
||||
}))
|
||||
}.afterLoading {
|
||||
view?.apply {
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
}
|
||||
}.launch("login")
|
||||
}
|
||||
|
||||
private fun getStudentsAppropriatesToLoginType(): Single<List<Student>> {
|
||||
private suspend fun getStudentsAppropriatesToLoginType(): List<Student> {
|
||||
val email = view?.formUsernameValue.orEmpty()
|
||||
val password = view?.formPassValue.orEmpty()
|
||||
val endpoint = view?.formHostValue.orEmpty()
|
||||
@ -163,12 +172,10 @@ class LoginAdvancedPresenter @Inject constructor(
|
||||
val symbol = view?.formSymbolValue.orEmpty()
|
||||
val token = view?.formTokenValue.orEmpty()
|
||||
|
||||
return rxSingle {
|
||||
when (Sdk.Mode.valueOf(view?.formLoginType ?: "")) {
|
||||
Sdk.Mode.API -> studentRepository.getStudentsApi(pin, symbol, token)
|
||||
Sdk.Mode.SCRAPPER -> studentRepository.getStudentsScrapper(email, password, endpoint, symbol)
|
||||
Sdk.Mode.HYBRID -> studentRepository.getStudentsHybrid(email, password, endpoint, symbol)
|
||||
}
|
||||
return when (Sdk.Mode.valueOf(view?.formLoginType.orEmpty())) {
|
||||
Sdk.Mode.API -> studentRepository.getStudentsApi(pin, symbol, token)
|
||||
Sdk.Mode.SCRAPPER -> studentRepository.getStudentsScrapper(email, password, endpoint, symbol)
|
||||
Sdk.Mode.HYBRID -> studentRepository.getStudentsHybrid(email, password, endpoint, symbol)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,15 @@
|
||||
package io.github.wulkanowy.ui.modules.login.form
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.afterLoading
|
||||
import io.github.wulkanowy.utils.flowWithResource
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -75,34 +78,44 @@ class LoginFormPresenter @Inject constructor(
|
||||
|
||||
if (!validateCredentials(email, password, host)) return
|
||||
|
||||
disposable.add(rxSingle { studentRepository.getStudentsScrapper(email, password, host, symbol) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.apply {
|
||||
flowWithResource { studentRepository.getStudentsScrapper(email, password, host, symbol) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> view?.run {
|
||||
Timber.i("Login started")
|
||||
hideSoftKeyboard()
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
}
|
||||
Timber.i("Login started")
|
||||
}
|
||||
.doFinally {
|
||||
view?.apply {
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Login result: Success")
|
||||
analytics.logEvent(
|
||||
"registration_form",
|
||||
"success" to true,
|
||||
"students" to it.data!!.size,
|
||||
"scrapperBaseUrl" to host,
|
||||
"error" to "No error"
|
||||
)
|
||||
view?.notifyParentAccountLogged(it.data, Triple(email, password, host))
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Login result: An exception occurred")
|
||||
analytics.logEvent(
|
||||
"registration_form",
|
||||
"success" to false,
|
||||
"students" to -1,
|
||||
"scrapperBaseUrl" to host,
|
||||
"error" to it.error!!.message.ifNullOrBlank { "No message" })
|
||||
loginErrorHandler.dispatch(it.error)
|
||||
lastError = it.error
|
||||
view?.showContact(true)
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
Timber.i("Login result: Success")
|
||||
analytics.logEvent("registration_form", "success" to true, "students" to it.size, "scrapperBaseUrl" to host, "error" to "No error")
|
||||
view?.notifyParentAccountLogged(it, Triple(email, password, host))
|
||||
}, {
|
||||
Timber.i("Login result: An exception occurred")
|
||||
analytics.logEvent("registration_form", "success" to false, "students" to -1, "scrapperBaseUrl" to host, "error" to it.message.ifNullOrBlank { "No message" })
|
||||
loginErrorHandler.dispatch(it)
|
||||
lastError = it
|
||||
view?.showContact(true)
|
||||
}))
|
||||
}.afterLoading {
|
||||
view?.apply {
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
}
|
||||
}.launch("login")
|
||||
}
|
||||
|
||||
fun onFaqClick() {
|
||||
|
@ -1,12 +1,15 @@
|
||||
package io.github.wulkanowy.ui.modules.login.recover
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.repositories.recover.RecoverRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.afterLoading
|
||||
import io.github.wulkanowy.utils.flowWithResource
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -56,24 +59,22 @@ class LoginRecoverPresenter @Inject constructor(
|
||||
|
||||
if (!validateInput(username, host)) return
|
||||
|
||||
disposable.add(rxSingle { recoverRepository.getReCaptchaSiteKey(host, symbol.ifBlank { "Default" }) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.run {
|
||||
flowWithResource { recoverRepository.getReCaptchaSiteKey(host, symbol.ifBlank { "Default" }) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> view?.run {
|
||||
hideSoftKeyboard()
|
||||
showRecoverForm(false)
|
||||
showProgress(true)
|
||||
showErrorView(false)
|
||||
showCaptcha(false)
|
||||
}
|
||||
Status.SUCCESS -> view?.loadReCaptcha(siteKey = it.data!!.first, url = it.data.second)
|
||||
Status.ERROR -> {
|
||||
Timber.i("Obtain captcha site key result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
.subscribe({ (resetUrl, siteKey) ->
|
||||
view?.loadReCaptcha(siteKey, resetUrl)
|
||||
}) {
|
||||
Timber.i("Obtain captcha site key result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
}.launch("captcha")
|
||||
}
|
||||
|
||||
private fun validateInput(username: String, host: String): Boolean {
|
||||
@ -97,35 +98,28 @@ class LoginRecoverPresenter @Inject constructor(
|
||||
val host = view?.recoverHostValue.orEmpty()
|
||||
val symbol = view?.formHostSymbol.ifNullOrBlank { "Default" }
|
||||
|
||||
with(disposable) {
|
||||
clear()
|
||||
add(rxSingle { recoverRepository.sendRecoverRequest(host, symbol, username, reCaptchaResponse) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.run {
|
||||
showProgress(true)
|
||||
showRecoverForm(false)
|
||||
showCaptcha(false)
|
||||
}
|
||||
flowWithResource { recoverRepository.sendRecoverRequest(host, symbol, username, reCaptchaResponse) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> view?.run {
|
||||
showProgress(true)
|
||||
showRecoverForm(false)
|
||||
showCaptcha(false)
|
||||
}
|
||||
.doFinally {
|
||||
view?.showProgress(false)
|
||||
}
|
||||
.subscribe({
|
||||
view?.run {
|
||||
showSuccessView(true)
|
||||
setSuccessTitle(it.substringBefore(". "))
|
||||
setSuccessMessage(it.substringAfter(". "))
|
||||
}
|
||||
|
||||
Status.SUCCESS -> view?.run {
|
||||
showSuccessView(true)
|
||||
setSuccessTitle(it.data!!.substringBefore(". "))
|
||||
setSuccessMessage(it.data.substringAfter(". "))
|
||||
analytics.logEvent("account_recover", "register" to host, "symbol" to symbol, "success" to true)
|
||||
}) {
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Send recover request result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
errorHandler.dispatch(it.error!!)
|
||||
analytics.logEvent("account_recover", "register" to host, "symbol" to symbol, "success" to false)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.showProgress(false)
|
||||
}.launch("verified")
|
||||
}
|
||||
|
||||
fun onDetailsClick() {
|
||||
|
@ -1,14 +1,15 @@
|
||||
package io.github.wulkanowy.ui.modules.login.studentselect
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.flowWithResource
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import java.io.Serializable
|
||||
import javax.inject.Inject
|
||||
@ -28,7 +29,7 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
|
||||
fun onAttachView(view: LoginStudentSelectView, students: Serializable?) {
|
||||
super.onAttachView(view)
|
||||
view.run {
|
||||
with(view) {
|
||||
initView()
|
||||
showContact(false)
|
||||
enableSignIn(false)
|
||||
@ -73,22 +74,20 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
private fun loadData(students: List<Student>) {
|
||||
resetSelectedState()
|
||||
this.students = students
|
||||
disposable.add(rxSingle { studentRepository.getSavedStudents(false) }
|
||||
.map { savedStudents ->
|
||||
students.map { student ->
|
||||
student to savedStudents.any { compareStudents(student, it) }
|
||||
|
||||
flowWithResource { studentRepository.getSavedStudents(false) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.d("Login student select students load started")
|
||||
Status.SUCCESS -> view?.updateData(students.map { student ->
|
||||
student to it.data!!.any { item -> compareStudents(student, item) }
|
||||
})
|
||||
Status.ERROR -> {
|
||||
errorHandler.dispatch(it.error!!)
|
||||
lastError = it.error
|
||||
view?.updateData(students.map { student -> student to false })
|
||||
}
|
||||
}
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
view?.updateData(it)
|
||||
}, {
|
||||
errorHandler.dispatch(it)
|
||||
lastError = it
|
||||
view?.updateData(students.map { student -> student to false })
|
||||
})
|
||||
)
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun resetSelectedState() {
|
||||
@ -97,33 +96,35 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun registerStudents(students: List<Student>) {
|
||||
disposable.add(rxSingle { studentRepository.saveStudents(students) }
|
||||
.map { students.first().apply { id = it.first() } }
|
||||
.flatMapCompletable { rxCompletable { studentRepository.switchStudent(it) } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.apply {
|
||||
flowWithResource {
|
||||
val savedStudents = studentRepository.saveStudents(students)
|
||||
val firstRegistered = students.first().apply { id = savedStudents.first() }
|
||||
studentRepository.switchStudent(firstRegistered)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> view?.run {
|
||||
Timber.i("Registration started")
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
}
|
||||
Timber.i("Registration started")
|
||||
}
|
||||
.subscribe({
|
||||
students.forEach { analytics.logEvent("registration_student_select", "success" to true, "scrapperBaseUrl" to it.scrapperBaseUrl, "symbol" to it.symbol, "error" to "No error") }
|
||||
Timber.i("Registration result: Success")
|
||||
view?.openMainView()
|
||||
}, { error ->
|
||||
students.forEach { analytics.logEvent("registration_student_select", "success" to false, "scrapperBaseUrl" to it.scrapperBaseUrl, "symbol" to it.symbol, "error" to error.message.ifNullOrBlank { "No message" }) }
|
||||
Timber.i("Registration result: An exception occurred ")
|
||||
loginErrorHandler.dispatch(error)
|
||||
lastError = error
|
||||
view?.apply {
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
showContact(true)
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Registration result: Success")
|
||||
view?.openMainView()
|
||||
logRegisterEvent(students)
|
||||
}
|
||||
}))
|
||||
Status.ERROR -> {
|
||||
Timber.i("Registration result: An exception occurred ")
|
||||
view?.apply {
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
showContact(true)
|
||||
}
|
||||
lastError = it.error
|
||||
loginErrorHandler.dispatch(it.error!!)
|
||||
logRegisterEvent(students, it.error)
|
||||
}
|
||||
}
|
||||
}.launch("register")
|
||||
}
|
||||
|
||||
fun onDiscordClick() {
|
||||
@ -133,4 +134,15 @@ class LoginStudentSelectPresenter @Inject constructor(
|
||||
fun onEmailClick() {
|
||||
view?.openEmail(lastError?.message.ifNullOrBlank { "empty" })
|
||||
}
|
||||
|
||||
private fun logRegisterEvent(students: List<Student>, error: Throwable? = null) {
|
||||
students.forEach { student ->
|
||||
analytics.logEvent(
|
||||
"registration_student_select",
|
||||
"success" to (error != null),
|
||||
"scrapperBaseUrl" to student.scrapperBaseUrl,
|
||||
"symbol" to student.symbol,
|
||||
"error" to (error?.message?.ifBlank { "No message" } ?: "No error"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
package io.github.wulkanowy.ui.modules.login.symbol
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.modules.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.github.wulkanowy.utils.afterLoading
|
||||
import io.github.wulkanowy.utils.flowWithResource
|
||||
import io.github.wulkanowy.utils.ifNullOrBlank
|
||||
import io.reactivex.Single
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import java.io.Serializable
|
||||
import javax.inject.Inject
|
||||
@ -47,44 +49,55 @@ class LoginSymbolPresenter @Inject constructor(
|
||||
return
|
||||
}
|
||||
|
||||
disposable.add(
|
||||
Single.fromCallable { loginData }
|
||||
.flatMap { rxSingle { studentRepository.getStudentsScrapper(it.first, it.second, it.third, symbol) } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.apply {
|
||||
hideSoftKeyboard()
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
}
|
||||
flowWithResource { studentRepository.getStudentsScrapper(loginData!!.first, loginData!!.second, loginData!!.third, symbol) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> view?.run {
|
||||
Timber.i("Login with symbol started")
|
||||
hideSoftKeyboard()
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
}
|
||||
.doFinally {
|
||||
view?.apply {
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
analytics.logEvent("registration_symbol", "success" to true, "students" to it.size, "scrapperBaseUrl" to loginData?.third, "symbol" to symbol, "error" to "No error")
|
||||
view?.apply {
|
||||
if (it.isEmpty()) {
|
||||
Status.SUCCESS -> {
|
||||
view?.run {
|
||||
if (it.data!!.isEmpty()) {
|
||||
Timber.i("Login with symbol result: Empty student list")
|
||||
setErrorSymbolIncorrect()
|
||||
view?.showContact(true)
|
||||
} else {
|
||||
Timber.i("Login with symbol result: Success")
|
||||
notifyParentAccountLogged(it)
|
||||
notifyParentAccountLogged(it.data)
|
||||
}
|
||||
}
|
||||
}, {
|
||||
analytics.logEvent(
|
||||
"registration_symbol",
|
||||
"success" to true,
|
||||
"students" to it.data!!.size,
|
||||
"scrapperBaseUrl" to loginData?.third,
|
||||
"symbol" to symbol,
|
||||
"error" to "No error"
|
||||
)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Login with symbol result: An exception occurred")
|
||||
analytics.logEvent("registration_symbol", "success" to false, "students" to -1, "scrapperBaseUrl" to loginData?.third, "symbol" to symbol, "error" to it.message.ifNullOrBlank { "No message" })
|
||||
loginErrorHandler.dispatch(it)
|
||||
lastError = it
|
||||
analytics.logEvent(
|
||||
"registration_symbol",
|
||||
"success" to false,
|
||||
"students" to -1,
|
||||
"scrapperBaseUrl" to loginData?.third,
|
||||
"symbol" to symbol,
|
||||
"error" to it.error!!.message.ifNullOrBlank { "No message" }
|
||||
)
|
||||
loginErrorHandler.dispatch(it.error)
|
||||
lastError = it.error
|
||||
view?.showContact(true)
|
||||
}))
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.apply {
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
}
|
||||
}.launch("login")
|
||||
}
|
||||
|
||||
fun onParentInitSymbolView(loginData: Triple<String, String, String>) {
|
||||
|
@ -1,13 +1,15 @@
|
||||
package io.github.wulkanowy.ui.modules.luckynumber
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.repositories.luckynumber.LuckyNumberRepository
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import kotlinx.coroutines.rx2.rxMaybe
|
||||
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 javax.inject.Inject
|
||||
|
||||
@ -34,47 +36,47 @@ class LuckyNumberPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading lucky number started")
|
||||
disposable.apply {
|
||||
clear()
|
||||
add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMapMaybe { rxMaybe { luckyNumberRepository.getLuckyNumber(it, forceRefresh) } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
luckyNumberRepository.getLuckyNumber(student, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading lucky number started")
|
||||
Status.SUCCESS -> {
|
||||
if (it.data != null) {
|
||||
Timber.i("Loading lucky number result: Success")
|
||||
view?.apply {
|
||||
updateData(it.data)
|
||||
showContent(true)
|
||||
showEmpty(false)
|
||||
showErrorView(false)
|
||||
}
|
||||
analytics.logEvent(
|
||||
"load_item",
|
||||
"type" to "lucky_number",
|
||||
"number" to it.data.luckyNumber
|
||||
)
|
||||
} else {
|
||||
Timber.i("Loading lucky number result: No lucky number found")
|
||||
view?.run {
|
||||
showContent(false)
|
||||
showEmpty(true)
|
||||
showErrorView(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
Timber.i("Loading lucky number result: Success")
|
||||
view?.apply {
|
||||
updateData(it)
|
||||
showContent(true)
|
||||
showEmpty(false)
|
||||
showErrorView(false)
|
||||
}
|
||||
analytics.logEvent(
|
||||
"load_item",
|
||||
"type" to "lucky_number",
|
||||
"number" to it.luckyNumber,
|
||||
"force_refresh" to forceRefresh
|
||||
)
|
||||
}, {
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading lucky number result: An exception occurred")
|
||||
errorHandler.dispatch(it)
|
||||
}, {
|
||||
Timber.i("Loading lucky number result: No lucky number found")
|
||||
view?.run {
|
||||
showContent(false)
|
||||
showEmpty(true)
|
||||
showErrorView(false)
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.wulkanowy.ui.modules.luckynumberwidget
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
@ -8,7 +9,9 @@ import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getStudentWidgetKey
|
||||
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider.Companion.getThemeWidgetKey
|
||||
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 javax.inject.Inject
|
||||
|
||||
class LuckyNumberWidgetConfigurePresenter @Inject constructor(
|
||||
@ -46,23 +49,25 @@ class LuckyNumberWidgetConfigurePresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData() {
|
||||
disposable.add(rxSingle { studentRepository.getSavedStudents(false) }
|
||||
.map { it to appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) } }
|
||||
.map { (students, currentStudentId) ->
|
||||
students.map { student -> student to (student.id == currentStudentId) }
|
||||
}
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.subscribe({
|
||||
when {
|
||||
it.isEmpty() -> view?.openLoginView()
|
||||
it.size == 1 -> {
|
||||
selectedStudent = it.single().first
|
||||
view?.showThemeDialog()
|
||||
flowWithResource { studentRepository.getSavedStudents(false) }.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.d("Lucky number widget configure students data load")
|
||||
Status.SUCCESS -> {
|
||||
val widgetId = appWidgetId?.let { id -> sharedPref.getLong(getStudentWidgetKey(id), 0) }
|
||||
when {
|
||||
it.data!!.isEmpty() -> view?.openLoginView()
|
||||
it.data.size == 1 -> {
|
||||
selectedStudent = it.data.single()
|
||||
view?.showThemeDialog()
|
||||
}
|
||||
else -> view?.updateData(it.data.map { student ->
|
||||
student to (student.id == widgetId)
|
||||
})
|
||||
}
|
||||
else -> view?.updateData(it)
|
||||
}
|
||||
}, { errorHandler.dispatch(it) }))
|
||||
Status.ERROR -> errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun registerStudent(student: Student?) {
|
||||
|
@ -15,6 +15,7 @@ import android.view.View.VISIBLE
|
||||
import android.widget.RemoteViews
|
||||
import dagger.android.AndroidInjection
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||
@ -24,6 +25,8 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.reactivex.Maybe
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.takeWhile
|
||||
import kotlinx.coroutines.rx2.rxMaybe
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import timber.log.Timber
|
||||
@ -157,7 +160,7 @@ class LuckyNumberWidgetProvider : AppWidgetProvider() {
|
||||
else -> Maybe.empty()
|
||||
}
|
||||
}
|
||||
.flatMap { rxMaybe { luckyNumberRepository.getLuckyNumber(it) } }
|
||||
.flatMap { rxMaybe { luckyNumberRepository.getLuckyNumber(it, false).takeWhile { it.status == Status.LOADING }.first().data } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.blockingGet()
|
||||
} catch (e: Exception) {
|
||||
|
@ -5,7 +5,6 @@ import android.view.View
|
||||
import android.view.View.INVISIBLE
|
||||
import android.view.View.VISIBLE
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.repositories.message.MessageFolder.RECEIVED
|
||||
import io.github.wulkanowy.data.repositories.message.MessageFolder.SENT
|
||||
import io.github.wulkanowy.data.repositories.message.MessageFolder.TRASHED
|
||||
@ -77,10 +76,6 @@ class MessageFragment : BaseFragment<FragmentMessageBinding>(R.layout.fragment_m
|
||||
binding.messageProgress.visibility = if (show) VISIBLE else INVISIBLE
|
||||
}
|
||||
|
||||
fun onDeleteMessage(message: Message) {
|
||||
presenter.onDeleteMessage(message)
|
||||
}
|
||||
|
||||
fun onChildFragmentLoaded() {
|
||||
presenter.onChildViewLoaded()
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package io.github.wulkanowy.ui.modules.message
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.repositories.student.StudentRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.SchedulersProvider
|
||||
import io.reactivex.Completable
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
import javax.inject.Inject
|
||||
|
||||
class MessagePresenter @Inject constructor(
|
||||
@ -18,12 +17,12 @@ class MessagePresenter @Inject constructor(
|
||||
|
||||
override fun onAttachView(view: MessageView) {
|
||||
super.onAttachView(view)
|
||||
disposable.add(Completable.timer(150, MILLISECONDS, schedulers.mainThread)
|
||||
.subscribe {
|
||||
view.initView()
|
||||
Timber.i("Message view was initialized")
|
||||
loadData()
|
||||
})
|
||||
launch {
|
||||
delay(150)
|
||||
view.initView()
|
||||
Timber.i("Message view was initialized")
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
|
||||
fun onPageSelected(index: Int) {
|
||||
@ -46,15 +45,6 @@ class MessagePresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun onDeleteMessage(message: Message) {
|
||||
view?.notifyChildMessageDeleted(
|
||||
when (message.removed) {
|
||||
true -> 2
|
||||
else -> message.folderId - 1
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun onSendMessageButtonClicked() {
|
||||
view?.openSendMessage()
|
||||
}
|
||||
|
@ -203,10 +203,6 @@ class MessagePreviewFragment :
|
||||
(activity as MainActivity).popView()
|
||||
}
|
||||
|
||||
override fun notifyParentMessageDeleted(message: Message) {
|
||||
parentFragmentManager.fragments.forEach { if (it is MessageFragment) it.onDeleteMessage(message) }
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putSerializable(MESSAGE_ID_KEY, presenter.message)
|
||||
super.onSaveInstanceState(outState)
|
||||
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.message.preview
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Build
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.entities.Message
|
||||
import io.github.wulkanowy.data.db.entities.MessageAttachment
|
||||
import io.github.wulkanowy.data.repositories.message.MessageRepository
|
||||
@ -11,8 +12,11 @@ import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.AppInfo
|
||||
import io.github.wulkanowy.utils.FirebaseAnalyticsHelper
|
||||
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.toFormattedString
|
||||
import kotlinx.coroutines.rx2.rxSingle
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -54,33 +58,35 @@ class MessagePreviewPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(message: Message) {
|
||||
Timber.i("Loading message ${message.messageId} preview started")
|
||||
disposable.apply {
|
||||
clear()
|
||||
add(rxSingle { studentRepository.getStudentById(message.studentId) }
|
||||
.flatMap { rxSingle { messageRepository.getMessage(it, message, true) } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doFinally { view?.showProgress(false) }
|
||||
.subscribe({ message ->
|
||||
Timber.i("Loading message ${message.message.messageId} preview result: Success ")
|
||||
this@MessagePreviewPresenter.message = message.message
|
||||
this@MessagePreviewPresenter.attachments = message.attachments
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getStudentById(message.studentId)
|
||||
messageRepository.getMessage(student, message, true)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading message ${message.messageId} preview started")
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading message ${it.data!!.message.messageId} preview result: Success ")
|
||||
this@MessagePreviewPresenter.message = it.data.message
|
||||
this@MessagePreviewPresenter.attachments = it.data.attachments
|
||||
view?.apply {
|
||||
setMessageWithAttachment(message)
|
||||
setMessageWithAttachment(it.data)
|
||||
initOptions()
|
||||
}
|
||||
analytics.logEvent(
|
||||
"load_item",
|
||||
"type" to "message_preview",
|
||||
"length" to message.message.content.length
|
||||
"length" to it.data.message.content.length
|
||||
)
|
||||
}) {
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Loading message ${message.messageId} preview result: An exception occurred ")
|
||||
retryCallback = { onMessageLoadRetry(message) }
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
}
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.showProgress(false)
|
||||
}.launch()
|
||||
}
|
||||
|
||||
fun onReply(): Boolean {
|
||||
@ -152,34 +158,37 @@ class MessagePreviewPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun deleteMessage() {
|
||||
message?.let { message ->
|
||||
disposable.add(rxSingle { studentRepository.getCurrentStudent() }
|
||||
.flatMap { rxSingle { messageRepository.deleteMessage(it, message) } }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
message ?: return
|
||||
|
||||
view?.run {
|
||||
showContent(false)
|
||||
showProgress(true)
|
||||
showOptions(false)
|
||||
showErrorView(false)
|
||||
}
|
||||
|
||||
flowWithResource {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
messageRepository.deleteMessage(student, message!!)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.d("Message ${message?.id} delete started")
|
||||
Status.SUCCESS -> {
|
||||
Timber.d("Message ${message?.id} delete success")
|
||||
view?.run {
|
||||
showContent(false)
|
||||
showProgress(true)
|
||||
showOptions(false)
|
||||
showErrorView(false)
|
||||
}
|
||||
}
|
||||
.doFinally {
|
||||
view?.showProgress(false)
|
||||
}
|
||||
.subscribe({
|
||||
view?.run {
|
||||
notifyParentMessageDeleted(message)
|
||||
showMessage(deleteMessageSuccessString)
|
||||
popView()
|
||||
}
|
||||
}, { error ->
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.d("Message ${message?.id} delete failed")
|
||||
retryCallback = { onMessageDelete() }
|
||||
errorHandler.dispatch(error)
|
||||
})
|
||||
)
|
||||
}
|
||||
errorHandler.dispatch(it.error!!)
|
||||
}
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.showProgress(false)
|
||||
}.launch("delete")
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user