forked from github/wulkanowy-mirror
Auto-refresh displayed data after some time (#1068)
* Auto-refresh displayed data after some time * Use refresh interval from settings * Auto-refresh exams * Add refresh utils * Auto-refresh timetable * Auto-refresh grade details and summary * Auto-refresh grades * Auto-refresh attendance summary * Add cacheKey variables * Auto-refres completed lessons * Auto-refres conferences * Auto-refres homework * Auto-refresh messages * Auto-refresh mobile devices * Auto-refresh notes * Fix tests * Fix instrumentation tests * Create AutoRefreshHelper
This commit is contained in:
parent
64cc49055b
commit
a1d4b3d19e
@ -1,5 +1,6 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import android.content.Context
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.room.Room
|
||||
import androidx.room.testing.MigrationTestHelper
|
||||
@ -22,10 +23,11 @@ abstract class AbstractMigrationTest {
|
||||
)
|
||||
|
||||
fun getMigratedRoomDatabase(): AppDatabase {
|
||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
val database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
|
||||
AppDatabase::class.java, dbName)
|
||||
.addMigrations(*AppDatabase.getMigrations(SharedPrefProvider(PreferenceManager
|
||||
.getDefaultSharedPreferences(ApplicationProvider.getApplicationContext())))
|
||||
.getDefaultSharedPreferences(context)))
|
||||
)
|
||||
.build()
|
||||
// close the database and release any stream resources when the test finishes
|
||||
|
@ -6,7 +6,9 @@ import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) {
|
||||
class SharedPrefProvider @Inject constructor(
|
||||
private val sharedPref: SharedPreferences
|
||||
) {
|
||||
|
||||
companion object {
|
||||
const val APP_VERSION_CODE_KEY = "app_version_code"
|
||||
|
@ -12,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")
|
||||
fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow<List<CompletedLesson>>
|
||||
fun loadAll(studentId: Int, diaryId: Int, from: LocalDate, end: LocalDate): Flow<List<CompletedLesson>>
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.Absent
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
@ -21,11 +23,14 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class AttendanceRepository @Inject constructor(
|
||||
private val attendanceDb: AttendanceDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "attendance"
|
||||
|
||||
fun getAttendance(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) },
|
||||
query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
@ -35,6 +40,8 @@ class AttendanceRepository @Inject constructor(
|
||||
saveFetchResult = { old, new ->
|
||||
attendanceDb.deleteAll(old uniqueSubtract new)
|
||||
attendanceDb.insertAll(new uniqueSubtract old)
|
||||
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
|
||||
},
|
||||
filterResult = { it.filter { item -> item.date in start..end } }
|
||||
)
|
||||
|
@ -5,6 +5,8 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
@ -14,11 +16,14 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class AttendanceSummaryRepository @Inject constructor(
|
||||
private val attendanceDb: AttendanceSummaryDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "attendance_summary"
|
||||
|
||||
fun getAttendanceSummary(student: Student, semester: Semester, subjectId: Int, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) },
|
||||
query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
@ -28,6 +33,7 @@ class AttendanceSummaryRepository @Inject constructor(
|
||||
saveFetchResult = { old, new ->
|
||||
attendanceDb.deleteAll(old uniqueSubtract new)
|
||||
attendanceDb.insertAll(new uniqueSubtract old)
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
@ -17,12 +19,15 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class CompletedLessonsRepository @Inject constructor(
|
||||
private val completedLessonsDb: CompletedLessonsDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "completed"
|
||||
|
||||
fun getCompletedLessons(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
query = { completedLessonsDb.loadAll(semester.diaryId, semester.studentId, start, end) },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) },
|
||||
query = { completedLessonsDb.loadAll(semester.studentId, semester.diaryId, start.monday, end.sunday) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
.getCompletedLessons(start.monday, end.sunday)
|
||||
@ -31,6 +36,7 @@ class CompletedLessonsRepository @Inject constructor(
|
||||
saveFetchResult = { old, new ->
|
||||
completedLessonsDb.deleteAll(old uniqueSubtract new)
|
||||
completedLessonsDb.insertAll(new uniqueSubtract old)
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
|
||||
},
|
||||
filterResult = { it.filter { item -> item.date in start..end } }
|
||||
)
|
||||
|
@ -5,6 +5,8 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
@ -14,11 +16,14 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class ConferenceRepository @Inject constructor(
|
||||
private val conferenceDb: ConferenceDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "conference"
|
||||
|
||||
fun getConferences(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) },
|
||||
query = { conferenceDb.loadAll(semester.diaryId, student.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
@ -28,6 +33,7 @@ class ConferenceRepository @Inject constructor(
|
||||
saveFetchResult = { old, new ->
|
||||
conferenceDb.deleteAll(old uniqueSubtract new)
|
||||
conferenceDb.insertAll(new uniqueSubtract old)
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -5,7 +5,9 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.endExamsDay
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.startExamsDay
|
||||
@ -17,11 +19,14 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class ExamRepository @Inject constructor(
|
||||
private val examDb: ExamDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "exam"
|
||||
|
||||
fun getExams(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) },
|
||||
query = { examDb.loadAll(semester.diaryId, semester.studentId, start.startExamsDay, start.endExamsDay) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
@ -31,6 +36,7 @@ class ExamRepository @Inject constructor(
|
||||
saveFetchResult = { old, new ->
|
||||
examDb.deleteAll(old uniqueSubtract new)
|
||||
examDb.insertAll(new uniqueSubtract old)
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
|
||||
},
|
||||
filterResult = { it.filter { item -> item.date in start..end } }
|
||||
)
|
||||
|
@ -8,6 +8,8 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
@ -22,11 +24,14 @@ import javax.inject.Singleton
|
||||
class GradeRepository @Inject constructor(
|
||||
private val gradeDb: GradeDao,
|
||||
private val gradeSummaryDb: GradeSummaryDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "grade"
|
||||
|
||||
fun getGrades(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||
shouldFetch = { (details, summaries) -> details.isEmpty() || summaries.isEmpty() || forceRefresh },
|
||||
shouldFetch = { (details, summaries) -> details.isEmpty() || summaries.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) },
|
||||
query = {
|
||||
gradeDb.loadAll(semester.semesterId, semester.studentId).combine(gradeSummaryDb.loadAll(semester.semesterId, semester.studentId)) { details, summaries ->
|
||||
details to summaries
|
||||
@ -42,6 +47,8 @@ class GradeRepository @Inject constructor(
|
||||
saveFetchResult = { (oldDetails, oldSummary), (newDetails, newSummary) ->
|
||||
refreshGradeDetails(student, oldDetails, newDetails, notify)
|
||||
refreshGradeSummaries(oldSummary, newSummary, notify)
|
||||
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester))
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -12,6 +12,8 @@ import io.github.wulkanowy.data.mappers.mapPointsToStatisticsItems
|
||||
import io.github.wulkanowy.data.mappers.mapSemesterToStatisticItems
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
@ -24,11 +26,16 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
private val gradePartialStatisticsDb: GradePartialStatisticsDao,
|
||||
private val gradePointsStatisticsDb: GradePointsStatisticsDao,
|
||||
private val gradeSemesterStatisticsDb: GradeSemesterStatisticsDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val partialCacheKey = "grade_stats_partial"
|
||||
private val semesterCacheKey = "grade_stats_semester"
|
||||
private val pointsCacheKey = "grade_stats_points"
|
||||
|
||||
fun getGradesPartialStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(partialCacheKey, semester)) },
|
||||
query = { gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
@ -38,6 +45,7 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
saveFetchResult = { old, new ->
|
||||
gradePartialStatisticsDb.deleteAll(old uniqueSubtract new)
|
||||
gradePartialStatisticsDb.insertAll(new uniqueSubtract old)
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(partialCacheKey, semester))
|
||||
},
|
||||
mapResult = { items ->
|
||||
when (subjectName) {
|
||||
@ -63,7 +71,7 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
)
|
||||
|
||||
fun getGradesSemesterStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(semesterCacheKey, semester)) },
|
||||
query = { gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
@ -73,6 +81,7 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
saveFetchResult = { old, new ->
|
||||
gradeSemesterStatisticsDb.deleteAll(old uniqueSubtract new)
|
||||
gradeSemesterStatisticsDb.insertAll(new uniqueSubtract old)
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(semesterCacheKey, semester))
|
||||
},
|
||||
mapResult = { items ->
|
||||
val itemsWithAverage = items.map { item ->
|
||||
@ -103,7 +112,7 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
)
|
||||
|
||||
fun getGradesPointsStatistics(student: Student, semester: Semester, subjectName: String, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(pointsCacheKey, semester)) },
|
||||
query = { gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
@ -113,6 +122,7 @@ class GradeStatisticsRepository @Inject constructor(
|
||||
saveFetchResult = { old, new ->
|
||||
gradePointsStatisticsDb.deleteAll(old uniqueSubtract new)
|
||||
gradePointsStatisticsDb.insertAll(new uniqueSubtract old)
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(pointsCacheKey, semester))
|
||||
},
|
||||
mapResult = { items ->
|
||||
when (subjectName) {
|
||||
|
@ -6,6 +6,8 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
@ -18,11 +20,14 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class HomeworkRepository @Inject constructor(
|
||||
private val homeworkDb: HomeworkDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "homework"
|
||||
|
||||
fun getHomework(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) },
|
||||
query = { homeworkDb.loadAll(semester.semesterId, semester.studentId, start.monday, end.sunday) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
@ -32,6 +37,8 @@ class HomeworkRepository @Inject constructor(
|
||||
saveFetchResult = { old, new ->
|
||||
homeworkDb.deleteAll(old uniqueSubtract new)
|
||||
homeworkDb.insertAll(new uniqueSubtract old)
|
||||
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -6,13 +6,15 @@ import io.github.wulkanowy.data.db.entities.Message
|
||||
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.mappers.mapFromEntities
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.data.enums.MessageFolder
|
||||
import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
|
||||
import io.github.wulkanowy.data.mappers.mapFromEntities
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.Folder
|
||||
import io.github.wulkanowy.sdk.pojo.SentMessage
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
@ -27,12 +29,15 @@ import javax.inject.Singleton
|
||||
class MessageRepository @Inject constructor(
|
||||
private val messagesDb: MessagesDao,
|
||||
private val messageAttachmentDao: MessageAttachmentDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "message"
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun getMessages(student: Student, semester: Semester, folder: MessageFolder, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, student, folder)) },
|
||||
query = { messagesDb.loadAll(student.id.toInt(), folder.id) },
|
||||
fetch = { sdk.init(student).getMessages(Folder.valueOf(folder.name), now().minusMonths(3), now()).mapToEntities(student) },
|
||||
saveFetchResult = { old, new ->
|
||||
@ -40,6 +45,8 @@ class MessageRepository @Inject constructor(
|
||||
messagesDb.insertAll((new uniqueSubtract old).onEach {
|
||||
it.isNotified = !notify
|
||||
})
|
||||
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student, folder))
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -8,6 +8,8 @@ import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.data.mappers.mapToMobileDeviceToken
|
||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
@ -17,11 +19,14 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class MobileDeviceRepository @Inject constructor(
|
||||
private val mobileDb: MobileDeviceDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "devices"
|
||||
|
||||
fun getDevices(student: Student, semester: Semester, forceRefresh: Boolean) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, student)) },
|
||||
query = { mobileDb.loadAll(semester.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
@ -31,6 +36,8 @@ class MobileDeviceRepository @Inject constructor(
|
||||
saveFetchResult = { old, new ->
|
||||
mobileDb.deleteAll(old uniqueSubtract new)
|
||||
mobileDb.insertAll(new uniqueSubtract old)
|
||||
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, student))
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -6,6 +6,8 @@ import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
@ -17,11 +19,14 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class NoteRepository @Inject constructor(
|
||||
private val noteDb: NoteDao,
|
||||
private val sdk: Sdk
|
||||
private val sdk: Sdk,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "note"
|
||||
|
||||
fun getNotes(student: Student, semester: Semester, forceRefresh: Boolean, notify: Boolean = false) = networkBoundResource(
|
||||
shouldFetch = { it.isEmpty() || forceRefresh },
|
||||
shouldFetch = { it.isEmpty() || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester)) },
|
||||
query = { noteDb.loadAll(student.studentId) },
|
||||
fetch = {
|
||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
||||
@ -36,6 +41,8 @@ class NoteRepository @Inject constructor(
|
||||
if (notify) isNotified = false
|
||||
}
|
||||
})
|
||||
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester))
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -9,6 +9,8 @@ import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.getRefreshKey
|
||||
import io.github.wulkanowy.utils.init
|
||||
import io.github.wulkanowy.utils.monday
|
||||
import io.github.wulkanowy.utils.networkBoundResource
|
||||
@ -25,11 +27,14 @@ class TimetableRepository @Inject constructor(
|
||||
private val timetableDb: TimetableDao,
|
||||
private val timetableAdditionalDb: TimetableAdditionalDao,
|
||||
private val sdk: Sdk,
|
||||
private val schedulerHelper: TimetableNotificationSchedulerHelper
|
||||
private val schedulerHelper: TimetableNotificationSchedulerHelper,
|
||||
private val refreshHelper: AutoRefreshHelper,
|
||||
) {
|
||||
|
||||
private val cacheKey = "timetable"
|
||||
|
||||
fun getTimetable(student: Student, semester: Semester, start: LocalDate, end: LocalDate, forceRefresh: Boolean, refreshAdditional: Boolean = false) = networkBoundResource(
|
||||
shouldFetch = { (timetable, additional) -> timetable.isEmpty() || (additional.isEmpty() && refreshAdditional) || forceRefresh },
|
||||
shouldFetch = { (timetable, additional) -> timetable.isEmpty() || (additional.isEmpty() && refreshAdditional) || forceRefresh || refreshHelper.isShouldBeRefreshed(getRefreshKey(cacheKey, semester, start, end)) },
|
||||
query = {
|
||||
timetableDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday)
|
||||
.map { schedulerHelper.scheduleNotifications(it, student); it }
|
||||
@ -47,6 +52,7 @@ class TimetableRepository @Inject constructor(
|
||||
refreshTimetable(student, oldTimetable, newTimetable)
|
||||
refreshAdditional(oldAdditional, newAdditional)
|
||||
|
||||
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
|
||||
},
|
||||
filterResult = { (timetable, additional) ->
|
||||
timetable.filter { item ->
|
||||
|
@ -191,8 +191,8 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
||||
binding. attendanceRecycler.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
binding.attendanceSwipe.isRefreshing = false
|
||||
override fun showRefresh(show: Boolean) {
|
||||
binding.attendanceSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun showPreButton(show: Boolean) {
|
||||
|
@ -51,23 +51,23 @@ class AttendancePresenter @Inject constructor(
|
||||
view.initView()
|
||||
Timber.i("Attendance view was initialized")
|
||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
loadData()
|
||||
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onPreviousDay() {
|
||||
view?.finishActionMode()
|
||||
attendanceToExcuseList.clear()
|
||||
loadData(currentDate.previousSchoolDay)
|
||||
reloadView()
|
||||
reloadView(currentDate.previousSchoolDay)
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onNextDay() {
|
||||
view?.finishActionMode()
|
||||
attendanceToExcuseList.clear()
|
||||
loadData(currentDate.nextSchoolDay)
|
||||
reloadView()
|
||||
reloadView(currentDate.nextSchoolDay)
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onPickDate() {
|
||||
@ -75,13 +75,13 @@ class AttendancePresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||
loadData(LocalDate.of(year, month, day))
|
||||
reloadView()
|
||||
reloadView(LocalDate.of(year, month, day))
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
Timber.i("Force refreshing the attendance")
|
||||
loadData(currentDate, true)
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onRetry() {
|
||||
@ -89,7 +89,7 @@ class AttendancePresenter @Inject constructor(
|
||||
showErrorView(false)
|
||||
showProgress(true)
|
||||
}
|
||||
loadData(currentDate, true)
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onDetailsClick() {
|
||||
@ -102,8 +102,8 @@ class AttendancePresenter @Inject constructor(
|
||||
if (view.currentStackSize == 1) {
|
||||
baseDate.also {
|
||||
if (currentDate != it) {
|
||||
loadData(it)
|
||||
reloadView()
|
||||
reloadView(it)
|
||||
loadData()
|
||||
} else if (!view.isViewEmpty) view.resetView()
|
||||
}
|
||||
} else view.popView()
|
||||
@ -184,17 +184,27 @@ class AttendancePresenter @Inject constructor(
|
||||
}.launch("holidays")
|
||||
}
|
||||
|
||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading attendance data started")
|
||||
currentDate = date
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
attendanceRepository.getAttendance(student, semester, date, date, forceRefresh)
|
||||
attendanceRepository.getAttendance(student, semester, currentDate, currentDate, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> view?.showExcuseButton(false)
|
||||
Status.LOADING -> {
|
||||
view?.showExcuseButton(false)
|
||||
if (!it.data.isNullOrEmpty()) {
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateData(it.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading attendance result: Success")
|
||||
view?.apply {
|
||||
@ -220,7 +230,7 @@ class AttendancePresenter @Inject constructor(
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
@ -250,12 +260,12 @@ class AttendancePresenter @Inject constructor(
|
||||
showContent(true)
|
||||
showProgress(false)
|
||||
}
|
||||
loadData(currentDate, forceRefresh = true)
|
||||
loadData(forceRefresh = true)
|
||||
}
|
||||
Status.ERROR -> {
|
||||
Timber.i("Excusing for absence result: An exception occurred")
|
||||
errorHandler.dispatch(it.error!!)
|
||||
loadData(currentDate)
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
}.launch("excuse")
|
||||
@ -272,11 +282,14 @@ class AttendancePresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun reloadView() {
|
||||
private fun reloadView(date: LocalDate) {
|
||||
currentDate = date
|
||||
|
||||
Timber.i("Reload attendance view with the date ${currentDate.toFormattedString()}")
|
||||
view?.apply {
|
||||
showProgress(true)
|
||||
enableSwipe(false)
|
||||
showRefresh(false)
|
||||
showContent(false)
|
||||
showEmpty(false)
|
||||
showErrorView(false)
|
||||
|
@ -24,7 +24,7 @@ interface AttendanceView : BaseView {
|
||||
|
||||
fun clearData()
|
||||
|
||||
fun hideRefresh()
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun resetView()
|
||||
|
||||
|
@ -121,8 +121,8 @@ class AttendanceSummaryFragment :
|
||||
binding.attendanceSummarySubjectsContainer.visibility = if (show) VISIBLE else INVISIBLE
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
binding.attendanceSummarySwipe.isRefreshing = false
|
||||
override fun showRefresh(show: Boolean) {
|
||||
binding.attendanceSummarySwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.github.wulkanowy.ui.modules.attendance.summary
|
||||
|
||||
import io.github.wulkanowy.data.Status
|
||||
import io.github.wulkanowy.data.db.entities.AttendanceSummary
|
||||
import io.github.wulkanowy.data.db.entities.Subject
|
||||
import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository
|
||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
@ -74,6 +75,8 @@ class AttendanceSummaryPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(subjectId: Int, forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading attendance summary data started")
|
||||
|
||||
currentSubjectId = subjectId
|
||||
|
||||
flowWithResourceIn {
|
||||
@ -82,15 +85,23 @@ class AttendanceSummaryPresenter @Inject constructor(
|
||||
attendanceSummaryRepository.getAttendanceSummary(student, semester, subjectId, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading attendance summary data started")
|
||||
Status.LOADING -> {
|
||||
if (!it.data.isNullOrEmpty()) {
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateDataSet(sortItems(it.data))
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading attendance summary result: Success")
|
||||
view?.apply {
|
||||
showEmpty(it.data!!.isEmpty())
|
||||
showContent(it.data.isNotEmpty())
|
||||
updateDataSet(it.data.sortedByDescending { item ->
|
||||
if (item.month.value <= Month.JUNE.value) item.month.value + 12 else item.month.value
|
||||
})
|
||||
updateDataSet(sortItems(it.data))
|
||||
}
|
||||
analytics.logEvent(
|
||||
"load_data",
|
||||
@ -106,13 +117,17 @@ class AttendanceSummaryPresenter @Inject constructor(
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun sortItems(items: List<AttendanceSummary>) = items.sortedByDescending { item ->
|
||||
if (item.month.value <= Month.JUNE.value) item.month.value + 12 else item.month.value
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
view?.run {
|
||||
if (isViewEmpty) {
|
||||
|
@ -9,7 +9,7 @@ interface AttendanceSummaryView : BaseView {
|
||||
|
||||
fun initView()
|
||||
|
||||
fun hideRefresh()
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun showContent(show: Boolean)
|
||||
|
||||
|
@ -67,8 +67,8 @@ class ConferenceFragment : BaseFragment<FragmentConferenceBinding>(R.layout.frag
|
||||
}
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
binding.conferenceSwipe.isRefreshing = false
|
||||
override fun showRefresh(show: Boolean) {
|
||||
binding.conferenceSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
|
@ -59,13 +59,25 @@ class ConferencePresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading conference data started")
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
conferenceRepository.getConferences(student, semester, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading conference data started")
|
||||
Status.LOADING -> {
|
||||
if (!it.data.isNullOrEmpty()) {
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateData(it.data.sortedByDescending { conference -> conference.date })
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading conference result: Success")
|
||||
view?.run {
|
||||
@ -87,7 +99,7 @@ class ConferencePresenter @Inject constructor(
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ interface ConferenceView : BaseView {
|
||||
|
||||
fun clearData()
|
||||
|
||||
fun hideRefresh()
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun showEmpty(show: Boolean)
|
||||
|
||||
|
@ -65,8 +65,8 @@ class ExamFragment : BaseFragment<FragmentExamBinding>(R.layout.fragment_exam),
|
||||
}
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
binding.examSwipe.isRefreshing = false
|
||||
override fun showRefresh(show: Boolean) {
|
||||
binding.examSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun updateData(data: List<ExamItem<*>>) {
|
||||
|
@ -45,24 +45,24 @@ class ExamPresenter @Inject constructor(
|
||||
view.initView()
|
||||
Timber.i("Exam view was initialized")
|
||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
loadData()
|
||||
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onPreviousWeek() {
|
||||
loadData(currentDate.minusDays(7))
|
||||
reloadView()
|
||||
reloadView(currentDate.minusDays(7))
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onNextWeek() {
|
||||
loadData(currentDate.plusDays(7))
|
||||
reloadView()
|
||||
reloadView(currentDate.plusDays(7))
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
Timber.i("Force refreshing the exam")
|
||||
loadData(currentDate, true)
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onRetry() {
|
||||
@ -70,7 +70,7 @@ class ExamPresenter @Inject constructor(
|
||||
showErrorView(false)
|
||||
showProgress(true)
|
||||
}
|
||||
loadData(currentDate, true)
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onDetailsClick() {
|
||||
@ -86,8 +86,8 @@ class ExamPresenter @Inject constructor(
|
||||
Timber.i("Exam view is reselected")
|
||||
baseDate.also {
|
||||
if (currentDate != it) {
|
||||
loadData(it)
|
||||
reloadView()
|
||||
reloadView(it)
|
||||
loadData()
|
||||
} else if (view?.isViewEmpty == false) view?.resetView()
|
||||
}
|
||||
}
|
||||
@ -105,8 +105,8 @@ class ExamPresenter @Inject constructor(
|
||||
}.launch("holidays")
|
||||
}
|
||||
|
||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||
currentDate = date
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading exam data started")
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
@ -114,7 +114,17 @@ class ExamPresenter @Inject constructor(
|
||||
examRepository.getExams(student, semester, currentDate.monday, currentDate.sunday, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading exam data started")
|
||||
Status.LOADING -> {
|
||||
if (!it.data.isNullOrEmpty()) {
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateData(createExamItems(it.data))
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading exam result: Success")
|
||||
view?.apply {
|
||||
@ -136,7 +146,7 @@ class ExamPresenter @Inject constructor(
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
@ -162,7 +172,9 @@ class ExamPresenter @Inject constructor(
|
||||
}.flatten()
|
||||
}
|
||||
|
||||
private fun reloadView() {
|
||||
private fun reloadView(date: LocalDate) {
|
||||
currentDate = date
|
||||
|
||||
Timber.i("Reload exam view with the date ${currentDate.toFormattedString()}")
|
||||
view?.apply {
|
||||
showProgress(true)
|
||||
|
@ -15,7 +15,7 @@ interface ExamView : BaseView {
|
||||
|
||||
fun clearData()
|
||||
|
||||
fun hideRefresh()
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun resetView()
|
||||
|
||||
|
@ -137,15 +137,35 @@ class GradeDetailsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
|
||||
Timber.i("Loading grade details data started")
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading grade details data started")
|
||||
Status.LOADING -> {
|
||||
val items = createGradeItems(it.data.orEmpty())
|
||||
if (items.isNotEmpty()) {
|
||||
Timber.i("Loading gradle details result: load cached data")
|
||||
view?.run {
|
||||
updateNewGradesAmount(it.data.orEmpty())
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateData(
|
||||
data = items,
|
||||
isGradeExpandable = preferencesRepository.isGradeExpandable,
|
||||
gradeColorTheme = preferencesRepository.gradeColorTheme
|
||||
)
|
||||
notifyParentDataLoaded(semesterId)
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading grade details result: Success")
|
||||
newGradesAmount = it.data!!.sumBy { item -> item.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } }
|
||||
updateNewGradesAmount(it.data!!)
|
||||
updateMarkAsDoneButton()
|
||||
val items = createGradeItems(it.data)
|
||||
view?.run {
|
||||
@ -179,6 +199,10 @@ class GradeDetailsPresenter @Inject constructor(
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun updateNewGradesAmount(grades: List<GradeDetailsWithAverage>) {
|
||||
newGradesAmount = grades.sumBy { item -> item.grades.sumBy { grade -> if (!grade.isRead) 1 else 0 } }
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
view?.run {
|
||||
if (isViewEmpty) {
|
||||
|
@ -2,6 +2,7 @@ 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.pojos.GradeStatisticsItem
|
||||
import io.github.wulkanowy.data.repositories.GradeStatisticsRepository
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
||||
@ -143,6 +144,8 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadDataByType(semesterId: Int, subjectName: String, type: ViewType, forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading grade stats data started")
|
||||
|
||||
currentSubjectName = if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName
|
||||
currentType = type
|
||||
|
||||
@ -160,17 +163,24 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
}
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading grade stats data started")
|
||||
Status.LOADING -> {
|
||||
val isNoContent = it.data == null || checkIsNoContent(it.data, type)
|
||||
if (!isNoContent) {
|
||||
view?.run {
|
||||
showEmpty(isNoContent)
|
||||
showContent(!isNoContent)
|
||||
showErrorView(false)
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
updateData(it.data!!, preferencesRepository.gradeColorTheme, preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading grade stats result: Success")
|
||||
view?.run {
|
||||
val isNoContent = it.data!!.isEmpty() || when (type) {
|
||||
ViewType.SEMESTER -> it.data.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0
|
||||
ViewType.PARTIAL -> it.data.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0
|
||||
ViewType.POINTS -> it.data.firstOrNull()?.points?.let { points ->
|
||||
points.student == .0 && points.others == .0
|
||||
} ?: false
|
||||
}
|
||||
val isNoContent = checkIsNoContent(it.data!!, type)
|
||||
showEmpty(isNoContent)
|
||||
showContent(!isNoContent)
|
||||
showErrorView(false)
|
||||
@ -198,6 +208,16 @@ class GradeStatisticsPresenter @Inject constructor(
|
||||
}.launch("load")
|
||||
}
|
||||
|
||||
private fun checkIsNoContent(items: List<GradeStatisticsItem>, type: ViewType): Boolean {
|
||||
return items.isEmpty() || when (type) {
|
||||
ViewType.SEMESTER -> items.firstOrNull()?.semester?.amounts.orEmpty().sum() == 0
|
||||
ViewType.PARTIAL -> items.firstOrNull()?.partial?.classAmounts.orEmpty().sum() == 0
|
||||
ViewType.POINTS -> items.firstOrNull()?.points?.let { points ->
|
||||
points.student == .0 && points.others == .0
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
view?.run {
|
||||
if (isViewEmpty) {
|
||||
|
@ -37,12 +37,26 @@ class GradeSummaryPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(semesterId: Int, forceRefresh: Boolean) {
|
||||
Timber.i("Loading grade summary started")
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
averageProvider.getGradesDetailsWithAverage(student, semesterId, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading grade summary started")
|
||||
Status.LOADING -> {
|
||||
val items = createGradeSummaryItems(it.data.orEmpty())
|
||||
if (items.isNotEmpty()) {
|
||||
Timber.i("Loading grade summary result: load cached data")
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateData(items)
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading grade summary result: Success")
|
||||
val items = createGradeSummaryItems(it.data!!)
|
||||
|
@ -83,8 +83,8 @@ class HomeworkFragment : BaseFragment<FragmentHomeworkBinding>(R.layout.fragment
|
||||
binding.homeworkNavDate.text = date
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
binding.homeworkSwipe.isRefreshing = false
|
||||
override fun showRefresh(show: Boolean) {
|
||||
binding.homeworkSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun showEmpty(show: Boolean) {
|
||||
|
@ -44,24 +44,24 @@ class HomeworkPresenter @Inject constructor(
|
||||
view.initView()
|
||||
Timber.i("Homework view was initialized")
|
||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
loadData()
|
||||
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onPreviousDay() {
|
||||
loadData(currentDate.minusDays(7))
|
||||
reloadView()
|
||||
reloadView(currentDate.minusDays(7))
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onNextDay() {
|
||||
loadData(currentDate.plusDays(7))
|
||||
reloadView()
|
||||
reloadView(currentDate.plusDays(7))
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
Timber.i("Force refreshing the homework")
|
||||
loadData(currentDate, true)
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onRetry() {
|
||||
@ -69,7 +69,7 @@ class HomeworkPresenter @Inject constructor(
|
||||
showErrorView(false)
|
||||
showProgress(true)
|
||||
}
|
||||
loadData(currentDate, true)
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onDetailsClick() {
|
||||
@ -94,16 +94,26 @@ class HomeworkPresenter @Inject constructor(
|
||||
}.launch("holidays")
|
||||
}
|
||||
|
||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||
currentDate = date
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading homework data started")
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
homeworkRepository.getHomework(student, semester, date, date, forceRefresh)
|
||||
homeworkRepository.getHomework(student, semester, currentDate, currentDate, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading homework data started")
|
||||
Status.LOADING -> {
|
||||
if (!it.data.isNullOrEmpty()) {
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateData(createHomeworkItem(it.data))
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading homework result: Success")
|
||||
view?.apply {
|
||||
@ -125,7 +135,7 @@ class HomeworkPresenter @Inject constructor(
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
@ -151,7 +161,9 @@ class HomeworkPresenter @Inject constructor(
|
||||
}.flatten()
|
||||
}
|
||||
|
||||
private fun reloadView() {
|
||||
private fun reloadView(date: LocalDate) {
|
||||
currentDate = date
|
||||
|
||||
Timber.i("Reload homework view with the date ${currentDate.toFormattedString()}")
|
||||
view?.apply {
|
||||
showProgress(true)
|
||||
|
@ -15,7 +15,7 @@ interface HomeworkView : BaseView {
|
||||
|
||||
fun updateNavigationWeek(date: String)
|
||||
|
||||
fun hideRefresh()
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun showEmpty(show: Boolean)
|
||||
|
||||
|
@ -85,13 +85,27 @@ class MessageTabPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(forceRefresh: Boolean) {
|
||||
Timber.i("Loading $folder message data started")
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
messageRepository.getMessages(student, semester, folder, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading $folder message data started")
|
||||
Status.LOADING -> {
|
||||
if (!it.data.isNullOrEmpty()) {
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
messages = it.data
|
||||
updateData(getFilteredData(lastSearchQuery))
|
||||
notifyParentDataLoaded()
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading $folder message result: Success")
|
||||
messages = it.data!!
|
||||
|
@ -100,8 +100,8 @@ class MobileDeviceFragment :
|
||||
}
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
binding.mobileDevicesSwipe.isRefreshing = false
|
||||
override fun showRefresh(show: Boolean) {
|
||||
binding.mobileDevicesSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
|
@ -51,13 +51,25 @@ class MobileDevicePresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading mobile devices data started")
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
mobileDeviceRepository.getDevices(student, semester, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading mobile devices data started")
|
||||
Status.LOADING -> {
|
||||
if (!it.data.isNullOrEmpty()) {
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateData(it.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading mobile devices result: Success")
|
||||
view?.run {
|
||||
@ -79,7 +91,7 @@ class MobileDevicePresenter @Inject constructor(
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ interface MobileDeviceView : BaseView {
|
||||
|
||||
fun showUndo(device: MobileDevice, position: Int)
|
||||
|
||||
fun hideRefresh()
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun showProgress(show: Boolean)
|
||||
|
||||
|
@ -105,8 +105,8 @@ class NoteFragment : BaseFragment<FragmentNoteBinding>(R.layout.fragment_note),
|
||||
binding.noteRecycler.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
binding.noteSwipe.isRefreshing = false
|
||||
override fun showRefresh(show: Boolean) {
|
||||
binding.noteSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -52,13 +52,25 @@ class NotePresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading note data started")
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
noteRepository.getNotes(student, semester, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading note data started")
|
||||
Status.LOADING -> {
|
||||
if (!it.data.isNullOrEmpty()) {
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateData(it.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading note result: Success")
|
||||
view?.apply {
|
||||
@ -80,7 +92,7 @@ class NotePresenter @Inject constructor(
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ interface NoteView : BaseView {
|
||||
|
||||
fun showContent(show: Boolean)
|
||||
|
||||
fun hideRefresh()
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun showNoteDialog(note: Note)
|
||||
}
|
||||
|
@ -113,8 +113,8 @@ class TimetableFragment : BaseFragment<FragmentTimetableBinding>(R.layout.fragme
|
||||
binding.timetableNavDate.text = date
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
binding.timetableSwipe.isRefreshing = false
|
||||
override fun showRefresh(show: Boolean) {
|
||||
binding.timetableSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun resetView() {
|
||||
|
@ -34,7 +34,7 @@ class TimetablePresenter @Inject constructor(
|
||||
private val timetableRepository: TimetableRepository,
|
||||
private val semesterRepository: SemesterRepository,
|
||||
private val prefRepository: PreferencesRepository,
|
||||
private val analytics: AnalyticsHelper
|
||||
private val analytics: AnalyticsHelper,
|
||||
) : BasePresenter<TimetableView>(errorHandler, studentRepository) {
|
||||
|
||||
private var baseDate: LocalDate = now().nextOrSameSchoolDay
|
||||
@ -49,19 +49,19 @@ class TimetablePresenter @Inject constructor(
|
||||
view.initView()
|
||||
Timber.i("Timetable was initialized")
|
||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
loadData()
|
||||
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onPreviousDay() {
|
||||
loadData(currentDate.previousSchoolDay)
|
||||
reloadView()
|
||||
reloadView(currentDate.previousSchoolDay)
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onNextDay() {
|
||||
loadData(currentDate.nextSchoolDay)
|
||||
reloadView()
|
||||
reloadView(currentDate.nextSchoolDay)
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onPickDate() {
|
||||
@ -69,13 +69,13 @@ class TimetablePresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||
loadData(of(year, month, day))
|
||||
reloadView()
|
||||
reloadView(of(year, month, day))
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
Timber.i("Force refreshing the timetable")
|
||||
loadData(currentDate, true)
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onRetry() {
|
||||
@ -83,7 +83,7 @@ class TimetablePresenter @Inject constructor(
|
||||
showErrorView(false)
|
||||
showProgress(true)
|
||||
}
|
||||
loadData(currentDate, true)
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onDetailsClick() {
|
||||
@ -96,8 +96,8 @@ class TimetablePresenter @Inject constructor(
|
||||
if (view.currentStackSize == 1) {
|
||||
baseDate.also {
|
||||
if (currentDate != it) {
|
||||
loadData(it)
|
||||
reloadView()
|
||||
reloadView(it)
|
||||
loadData()
|
||||
} else if (!view.isViewEmpty) view.resetView()
|
||||
}
|
||||
} else view.popView()
|
||||
@ -132,27 +132,30 @@ class TimetablePresenter @Inject constructor(
|
||||
}.launch("holidays")
|
||||
}
|
||||
|
||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||
currentDate = date
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading timetable data started")
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
timetableRepository.getTimetable(student, semester, date, date, forceRefresh)
|
||||
timetableRepository.getTimetable(student, semester, currentDate, currentDate, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading timetable data started")
|
||||
Status.LOADING -> {
|
||||
if (!it.data?.first.isNullOrEmpty()) {
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateData(it.data!!.first)
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading timetable result: Success")
|
||||
view?.apply {
|
||||
updateData(
|
||||
showWholeClassPlanType = prefRepository.showWholeClassPlan,
|
||||
showGroupsInPlanType = prefRepository.showGroupsInPlan,
|
||||
showTimetableTimers = prefRepository.showTimetableTimers,
|
||||
data = it.data!!.first
|
||||
.filter { item -> if (prefRepository.showWholeClassPlan == "no") item.isStudentPlan else true }
|
||||
.sortedWith(compareBy({ item -> item.number }, { item -> !item.isStudentPlan }))
|
||||
)
|
||||
updateData(it.data!!.first)
|
||||
showEmpty(it.data.first.isEmpty())
|
||||
showErrorView(false)
|
||||
showContent(it.data.first.isNotEmpty())
|
||||
@ -170,13 +173,26 @@ class TimetablePresenter @Inject constructor(
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
}.launch()
|
||||
}
|
||||
|
||||
private fun updateData(lessons: List<Timetable>) {
|
||||
view?.updateData(
|
||||
showWholeClassPlanType = prefRepository.showWholeClassPlan,
|
||||
showGroupsInPlanType = prefRepository.showGroupsInPlan,
|
||||
showTimetableTimers = prefRepository.showTimetableTimers,
|
||||
data = createItems(lessons)
|
||||
)
|
||||
}
|
||||
|
||||
private fun createItems(items: List<Timetable>) = items.filter { item ->
|
||||
if (prefRepository.showWholeClassPlan == "no") item.isStudentPlan else true
|
||||
}.sortedWith(compareBy({ item -> item.number }, { item -> !item.isStudentPlan }))
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
view?.run {
|
||||
if (isViewEmpty) {
|
||||
@ -188,7 +204,9 @@ class TimetablePresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun reloadView() {
|
||||
private fun reloadView(date: LocalDate) {
|
||||
currentDate = date
|
||||
|
||||
Timber.i("Reload timetable view with the date ${currentDate.toFormattedString()}")
|
||||
view?.apply {
|
||||
showProgress(true)
|
||||
|
@ -18,7 +18,7 @@ interface TimetableView : BaseView {
|
||||
|
||||
fun clearData()
|
||||
|
||||
fun hideRefresh()
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun resetView()
|
||||
|
||||
|
@ -89,8 +89,8 @@ class CompletedLessonsFragment :
|
||||
binding.completedLessonsNavDate.text = date
|
||||
}
|
||||
|
||||
override fun hideRefresh() {
|
||||
binding.completedLessonsSwipe.isRefreshing = false
|
||||
override fun showRefresh(show: Boolean) {
|
||||
binding.completedLessonsSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun showEmpty(show: Boolean) {
|
||||
|
@ -50,19 +50,19 @@ class CompletedLessonsPresenter @Inject constructor(
|
||||
this.view?.showEmpty(true)
|
||||
Timber.i("Completed lessons feature disabled by school")
|
||||
}
|
||||
loadData(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
reloadView(ofEpochDay(date ?: baseDate.toEpochDay()))
|
||||
loadData()
|
||||
if (currentDate.isHolidays) setBaseDateOnHolidays()
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onPreviousDay() {
|
||||
loadData(currentDate.previousSchoolDay)
|
||||
reloadView()
|
||||
reloadView(currentDate.previousSchoolDay)
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onNextDay() {
|
||||
loadData(currentDate.nextSchoolDay)
|
||||
reloadView()
|
||||
reloadView(currentDate.nextSchoolDay)
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onPickDate() {
|
||||
@ -70,13 +70,13 @@ class CompletedLessonsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onDateSet(year: Int, month: Int, day: Int) {
|
||||
loadData(LocalDate.of(year, month, day))
|
||||
reloadView()
|
||||
reloadView(LocalDate.of(year, month, day))
|
||||
loadData()
|
||||
}
|
||||
|
||||
fun onSwipeRefresh() {
|
||||
Timber.i("Force refreshing the completed lessons")
|
||||
loadData(currentDate, true)
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onRetry() {
|
||||
@ -84,7 +84,7 @@ class CompletedLessonsPresenter @Inject constructor(
|
||||
showErrorView(false)
|
||||
showProgress(true)
|
||||
}
|
||||
loadData(currentDate, true)
|
||||
loadData(true)
|
||||
}
|
||||
|
||||
fun onDetailsClick() {
|
||||
@ -109,16 +109,26 @@ class CompletedLessonsPresenter @Inject constructor(
|
||||
}.launch("holidays")
|
||||
}
|
||||
|
||||
private fun loadData(date: LocalDate, forceRefresh: Boolean = false) {
|
||||
currentDate = date
|
||||
private fun loadData(forceRefresh: Boolean = false) {
|
||||
Timber.i("Loading completed lessons data started")
|
||||
|
||||
flowWithResourceIn {
|
||||
val student = studentRepository.getCurrentStudent()
|
||||
val semester = semesterRepository.getCurrentSemester(student)
|
||||
completedLessonsRepository.getCompletedLessons(student, semester, date, date, forceRefresh)
|
||||
completedLessonsRepository.getCompletedLessons(student, semester, currentDate, currentDate, forceRefresh)
|
||||
}.onEach {
|
||||
when (it.status) {
|
||||
Status.LOADING -> Timber.i("Loading completed lessons data started")
|
||||
Status.LOADING -> {
|
||||
if (!it.data.isNullOrEmpty()) {
|
||||
view?.run {
|
||||
enableSwipe(true)
|
||||
showRefresh(true)
|
||||
showProgress(false)
|
||||
showContent(true)
|
||||
updateData(it.data.sortedBy { item -> item.number })
|
||||
}
|
||||
}
|
||||
}
|
||||
Status.SUCCESS -> {
|
||||
Timber.i("Loading completed lessons lessons result: Success")
|
||||
view?.apply {
|
||||
@ -140,7 +150,7 @@ class CompletedLessonsPresenter @Inject constructor(
|
||||
}
|
||||
}.afterLoading {
|
||||
view?.run {
|
||||
hideRefresh()
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
enableSwipe(true)
|
||||
}
|
||||
@ -158,7 +168,9 @@ class CompletedLessonsPresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun reloadView() {
|
||||
private fun reloadView(date: LocalDate) {
|
||||
currentDate = date
|
||||
|
||||
Timber.i("Reload completed lessons view with the date ${currentDate.toFormattedString()}")
|
||||
view?.apply {
|
||||
showProgress(true)
|
||||
|
@ -16,7 +16,7 @@ interface CompletedLessonsView : BaseView {
|
||||
|
||||
fun updateNavigationDay(date: String)
|
||||
|
||||
fun hideRefresh()
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun showEmpty(show: Boolean)
|
||||
|
||||
|
@ -84,7 +84,7 @@ fun <T> flowWithResourceIn(block: suspend () -> Flow<Resource<T>>) = flow {
|
||||
block()
|
||||
.catch { emit(Resource.error(it)) }
|
||||
.collect {
|
||||
if (it.status != Status.LOADING) { // LOADING is already emitted
|
||||
if (it.status != Status.LOADING || (it.status == Status.LOADING && it.data != null)) { // LOADING without data is already emitted
|
||||
emit(it)
|
||||
}
|
||||
}
|
||||
|
50
app/src/main/java/io/github/wulkanowy/utils/RefreshUtils.kt
Normal file
50
app/src/main/java/io/github/wulkanowy/utils/RefreshUtils.kt
Normal file
@ -0,0 +1,50 @@
|
||||
package io.github.wulkanowy.utils
|
||||
|
||||
import android.content.Context
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.SharedPrefProvider
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.enums.MessageFolder
|
||||
import timber.log.Timber
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import javax.inject.Inject
|
||||
|
||||
fun getRefreshKey(name: String, semester: Semester, start: LocalDate, end: LocalDate): String {
|
||||
return "${name}_${semester.studentId}_${semester.semesterId}_${start.monday}_${end.sunday}"
|
||||
}
|
||||
|
||||
fun getRefreshKey(name: String, semester: Semester): String {
|
||||
return "${name}_${semester.studentId}_${semester.semesterId}"
|
||||
}
|
||||
|
||||
fun getRefreshKey(name: String, student: Student): String {
|
||||
return "${name}_${student.userLoginId}"
|
||||
}
|
||||
|
||||
fun getRefreshKey(name: String, student: Student, folder: MessageFolder): String {
|
||||
return "${name}_${student.id}_${folder.id}"
|
||||
}
|
||||
|
||||
class AutoRefreshHelper @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val sharedPref: SharedPrefProvider
|
||||
) {
|
||||
|
||||
fun isShouldBeRefreshed(key: String): Boolean {
|
||||
val timestamp = sharedPref.getLong(key, 0).toLocalDateTime()
|
||||
val servicesInterval = sharedPref.getString(context.getString(R.string.pref_key_services_interval), context.getString(R.string.pref_default_services_interval)).toLong()
|
||||
|
||||
val shouldBeRefreshed = timestamp < LocalDateTime.now().minusMinutes(servicesInterval)
|
||||
|
||||
Timber.d("Check if $key need to be refreshed: $shouldBeRefreshed (last refresh: $timestamp, interval: $servicesInterval min)")
|
||||
|
||||
return shouldBeRefreshed
|
||||
}
|
||||
|
||||
fun updateLastRefreshTimestamp(key: String) {
|
||||
sharedPref.putLong(key, LocalDateTime.now().toTimestamp())
|
||||
}
|
||||
}
|
@ -5,11 +5,13 @@ import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.getSemesterEntity
|
||||
import io.github.wulkanowy.getStudentEntity
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.toFirstResult
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.impl.annotations.SpyK
|
||||
import io.mockk.just
|
||||
@ -30,6 +32,9 @@ class AttendanceRepositoryTest {
|
||||
@MockK
|
||||
private lateinit var attendanceDb: AttendanceDao
|
||||
|
||||
@MockK(relaxUnitFun = true)
|
||||
private lateinit var refreshHelper: AutoRefreshHelper
|
||||
|
||||
private val semester = getSemesterEntity()
|
||||
|
||||
private val student = getStudentEntity()
|
||||
@ -48,8 +53,9 @@ class AttendanceRepositoryTest {
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
every { refreshHelper.isShouldBeRefreshed(any()) } returns false
|
||||
|
||||
attendanceRepository = AttendanceRepository(attendanceDb, sdk)
|
||||
attendanceRepository = AttendanceRepository(attendanceDb, sdk, refreshHelper)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -5,11 +5,13 @@ import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.getSemesterEntity
|
||||
import io.github.wulkanowy.getStudentEntity
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.toFirstResult
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.impl.annotations.SpyK
|
||||
import io.mockk.just
|
||||
@ -30,6 +32,9 @@ class CompletedLessonsRepositoryTest {
|
||||
@MockK
|
||||
private lateinit var completedLessonDb: CompletedLessonsDao
|
||||
|
||||
@MockK(relaxUnitFun = true)
|
||||
private lateinit var refreshHelper: AutoRefreshHelper
|
||||
|
||||
private val semester = getSemesterEntity()
|
||||
|
||||
private val student = getStudentEntity()
|
||||
@ -48,8 +53,9 @@ class CompletedLessonsRepositoryTest {
|
||||
@Before
|
||||
fun initApi() {
|
||||
MockKAnnotations.init(this)
|
||||
every { refreshHelper.isShouldBeRefreshed(any()) } returns false
|
||||
|
||||
completedLessonRepository = CompletedLessonsRepository(completedLessonDb, sdk)
|
||||
completedLessonRepository = CompletedLessonsRepository(completedLessonDb, sdk, refreshHelper)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -5,11 +5,13 @@ import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.getSemesterEntity
|
||||
import io.github.wulkanowy.getStudentEntity
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.toFirstResult
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.impl.annotations.SpyK
|
||||
import io.mockk.just
|
||||
@ -29,6 +31,9 @@ class ExamRemoteTest {
|
||||
@MockK
|
||||
private lateinit var examDb: ExamDao
|
||||
|
||||
@MockK(relaxUnitFun = true)
|
||||
private lateinit var refreshHelper: AutoRefreshHelper
|
||||
|
||||
private val semester = getSemesterEntity()
|
||||
|
||||
private val student = getStudentEntity()
|
||||
@ -49,8 +54,9 @@ class ExamRemoteTest {
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
every { refreshHelper.isShouldBeRefreshed(any()) } returns false
|
||||
|
||||
examRepository = ExamRepository(examDb, sdk)
|
||||
examRepository = ExamRepository(examDb, sdk, refreshHelper)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -6,11 +6,13 @@ import io.github.wulkanowy.data.mappers.mapToEntities
|
||||
import io.github.wulkanowy.getSemesterEntity
|
||||
import io.github.wulkanowy.getStudentEntity
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.toFirstResult
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.impl.annotations.SpyK
|
||||
import io.mockk.just
|
||||
@ -36,6 +38,9 @@ class GradeRepositoryTest {
|
||||
@MockK
|
||||
private lateinit var gradeSummaryDb: GradeSummaryDao
|
||||
|
||||
@MockK(relaxUnitFun = true)
|
||||
private lateinit var refreshHelper: AutoRefreshHelper
|
||||
|
||||
private val semester = getSemesterEntity()
|
||||
|
||||
private val student = getStudentEntity()
|
||||
@ -45,8 +50,9 @@ class GradeRepositoryTest {
|
||||
@Before
|
||||
fun initApi() {
|
||||
MockKAnnotations.init(this)
|
||||
every { refreshHelper.isShouldBeRefreshed(any()) } returns false
|
||||
|
||||
gradeRepository = GradeRepository(gradeDb, gradeSummaryDb, sdk)
|
||||
gradeRepository = GradeRepository(gradeDb, gradeSummaryDb, sdk, refreshHelper)
|
||||
|
||||
coEvery { gradeDb.deleteAll(any()) } just Runs
|
||||
coEvery { gradeDb.insertAll(any()) } returns listOf()
|
||||
|
@ -9,11 +9,13 @@ import io.github.wulkanowy.getStudentEntity
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.GradeStatisticsItem
|
||||
import io.github.wulkanowy.sdk.pojo.GradeStatisticsSubject
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.toFirstResult
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.impl.annotations.SpyK
|
||||
import io.mockk.just
|
||||
@ -37,6 +39,9 @@ class GradeStatisticsRepositoryTest {
|
||||
@MockK
|
||||
private lateinit var gradeSemesterStatisticsDb: GradeSemesterStatisticsDao
|
||||
|
||||
@MockK(relaxUnitFun = true)
|
||||
private lateinit var refreshHelper: AutoRefreshHelper
|
||||
|
||||
private val semester = getSemesterEntity()
|
||||
|
||||
private val student = getStudentEntity()
|
||||
@ -51,8 +56,9 @@ class GradeStatisticsRepositoryTest {
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
every { refreshHelper.isShouldBeRefreshed(any()) } returns false
|
||||
|
||||
gradeStatisticsRepository = GradeStatisticsRepository(gradePartialStatisticsDb, gradePointsStatisticsDb, gradeSemesterStatisticsDb, sdk)
|
||||
gradeStatisticsRepository = GradeStatisticsRepository(gradePartialStatisticsDb, gradePointsStatisticsDb, gradeSemesterStatisticsDb, sdk, refreshHelper)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -8,11 +8,13 @@ import io.github.wulkanowy.data.db.entities.MessageWithAttachment
|
||||
import io.github.wulkanowy.getStudentEntity
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.MessageDetails
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.toFirstResult
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.impl.annotations.SpyK
|
||||
import io.mockk.just
|
||||
@ -36,6 +38,9 @@ class MessageRepositoryTest {
|
||||
@MockK
|
||||
private lateinit var messageAttachmentDao: MessageAttachmentDao
|
||||
|
||||
@MockK(relaxUnitFun = true)
|
||||
private lateinit var refreshHelper: AutoRefreshHelper
|
||||
|
||||
private val student = getStudentEntity()
|
||||
|
||||
private lateinit var messageRepository: MessageRepository
|
||||
@ -43,8 +48,9 @@ class MessageRepositoryTest {
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
every { refreshHelper.isShouldBeRefreshed(any()) } returns false
|
||||
|
||||
messageRepository = MessageRepository(messageDb, messageAttachmentDao, sdk)
|
||||
messageRepository = MessageRepository(messageDb, messageAttachmentDao, sdk, refreshHelper)
|
||||
}
|
||||
|
||||
@Test(expected = NoSuchElementException::class)
|
||||
|
@ -6,11 +6,13 @@ import io.github.wulkanowy.getSemesterEntity
|
||||
import io.github.wulkanowy.getStudentEntity
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.Device
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.toFirstResult
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.impl.annotations.SpyK
|
||||
import io.mockk.just
|
||||
@ -29,6 +31,9 @@ class MobileDeviceRepositoryTest {
|
||||
@MockK
|
||||
private lateinit var mobileDeviceDb: MobileDeviceDao
|
||||
|
||||
@MockK(relaxUnitFun = true)
|
||||
private lateinit var refreshHelper: AutoRefreshHelper
|
||||
|
||||
private val semester = getSemesterEntity()
|
||||
|
||||
private val student = getStudentEntity()
|
||||
@ -43,8 +48,9 @@ class MobileDeviceRepositoryTest {
|
||||
@Before
|
||||
fun initTest() {
|
||||
MockKAnnotations.init(this)
|
||||
every { refreshHelper.isShouldBeRefreshed(any()) } returns false
|
||||
|
||||
mobileDeviceRepository = MobileDeviceRepository(mobileDeviceDb, sdk)
|
||||
mobileDeviceRepository = MobileDeviceRepository(mobileDeviceDb, sdk, refreshHelper)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -7,11 +7,13 @@ import io.github.wulkanowy.getSemesterEntity
|
||||
import io.github.wulkanowy.getStudentEntity
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
||||
import io.github.wulkanowy.utils.toFirstResult
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.impl.annotations.SpyK
|
||||
import io.mockk.just
|
||||
@ -39,6 +41,9 @@ class TimetableRepositoryTest {
|
||||
@MockK
|
||||
private lateinit var timetableAdditionalDao: TimetableAdditionalDao
|
||||
|
||||
@MockK(relaxUnitFun = true)
|
||||
private lateinit var refreshHelper: AutoRefreshHelper
|
||||
|
||||
private val student = getStudentEntity()
|
||||
|
||||
private val semester = getSemesterEntity()
|
||||
@ -52,7 +57,9 @@ class TimetableRepositoryTest {
|
||||
@Before
|
||||
fun initApi() {
|
||||
MockKAnnotations.init(this)
|
||||
timetableRepository = TimetableRepository(timetableDb, timetableAdditionalDao, sdk, timetableNotificationSchedulerHelper)
|
||||
every { refreshHelper.isShouldBeRefreshed(any()) } returns false
|
||||
|
||||
timetableRepository = TimetableRepository(timetableDb, timetableAdditionalDao, sdk, timetableNotificationSchedulerHelper, refreshHelper)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user