1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2024-09-19 23:09:09 -05:00

Add widget updating on data sync (#2487)

---------

Co-authored-by: Faierbel <RafalBO99@outlook.com>
This commit is contained in:
Michael 2024-03-17 21:06:40 +01:00 committed by GitHub
parent 961bc24f27
commit 34d34a050a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 75 additions and 5 deletions

View File

@ -6,6 +6,8 @@ import io.github.wulkanowy.data.db.entities.LuckyNumber
import io.github.wulkanowy.data.db.entities.Student import io.github.wulkanowy.data.db.entities.Student
import io.github.wulkanowy.data.mappers.mapToEntity import io.github.wulkanowy.data.mappers.mapToEntity
import io.github.wulkanowy.data.networkBoundResource import io.github.wulkanowy.data.networkBoundResource
import io.github.wulkanowy.ui.modules.luckynumberwidget.LuckyNumberWidgetProvider
import io.github.wulkanowy.utils.AppWidgetUpdater
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
@ -18,6 +20,7 @@ import javax.inject.Singleton
class LuckyNumberRepository @Inject constructor( class LuckyNumberRepository @Inject constructor(
private val luckyNumberDb: LuckyNumberDao, private val luckyNumberDb: LuckyNumberDao,
private val wulkanowySdkFactory: WulkanowySdkFactory, private val wulkanowySdkFactory: WulkanowySdkFactory,
private val appWidgetUpdater: AppWidgetUpdater,
) { ) {
private val saveFetchResultMutex = Mutex() private val saveFetchResultMutex = Mutex()
@ -26,6 +29,7 @@ class LuckyNumberRepository @Inject constructor(
student: Student, student: Student,
forceRefresh: Boolean, forceRefresh: Boolean,
notify: Boolean = false, notify: Boolean = false,
isFromAppWidget: Boolean = false
) = networkBoundResource( ) = networkBoundResource(
mutex = saveFetchResultMutex, mutex = saveFetchResultMutex,
isResultEmpty = { it == null }, isResultEmpty = { it == null },
@ -44,6 +48,9 @@ class LuckyNumberRepository @Inject constructor(
oldItems = listOfNotNull(oldLuckyNumber), oldItems = listOfNotNull(oldLuckyNumber),
newItems = listOf(newLuckyNumber.apply { if (notify) isNotified = false }), newItems = listOf(newLuckyNumber.apply { if (notify) isNotified = false }),
) )
if (!isFromAppWidget) {
appWidgetUpdater.updateAllAppWidgetsByProvider(LuckyNumberWidgetProvider::class)
}
} }
} }
) )

View File

@ -13,6 +13,8 @@ import io.github.wulkanowy.data.mappers.mapToEntities
import io.github.wulkanowy.data.networkBoundResource import io.github.wulkanowy.data.networkBoundResource
import io.github.wulkanowy.data.pojos.TimetableFull import io.github.wulkanowy.data.pojos.TimetableFull
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
import io.github.wulkanowy.ui.modules.timetablewidget.TimetableWidgetProvider
import io.github.wulkanowy.utils.AppWidgetUpdater
import io.github.wulkanowy.utils.AutoRefreshHelper import io.github.wulkanowy.utils.AutoRefreshHelper
import io.github.wulkanowy.utils.getRefreshKey import io.github.wulkanowy.utils.getRefreshKey
import io.github.wulkanowy.utils.monday import io.github.wulkanowy.utils.monday
@ -26,6 +28,7 @@ import java.time.LocalDate
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class TimetableRepository @Inject constructor( class TimetableRepository @Inject constructor(
private val timetableDb: TimetableDao, private val timetableDb: TimetableDao,
@ -34,6 +37,7 @@ class TimetableRepository @Inject constructor(
private val wulkanowySdkFactory: WulkanowySdkFactory, private val wulkanowySdkFactory: WulkanowySdkFactory,
private val schedulerHelper: TimetableNotificationSchedulerHelper, private val schedulerHelper: TimetableNotificationSchedulerHelper,
private val refreshHelper: AutoRefreshHelper, private val refreshHelper: AutoRefreshHelper,
private val appWidgetUpdater: AppWidgetUpdater,
) { ) {
private val saveFetchResultMutex = Mutex() private val saveFetchResultMutex = Mutex()
@ -52,7 +56,8 @@ class TimetableRepository @Inject constructor(
forceRefresh: Boolean, forceRefresh: Boolean,
refreshAdditional: Boolean = false, refreshAdditional: Boolean = false,
notify: Boolean = false, notify: Boolean = false,
timetableType: TimetableType = TimetableType.NORMAL timetableType: TimetableType = TimetableType.NORMAL,
isFromAppWidget: Boolean = false
) = networkBoundResource( ) = networkBoundResource(
mutex = saveFetchResultMutex, mutex = saveFetchResultMutex,
isResultEmpty = { isResultEmpty = {
@ -83,6 +88,9 @@ class TimetableRepository @Inject constructor(
refreshDayHeaders(timetableOld.headers, timetableNew.headers) refreshDayHeaders(timetableOld.headers, timetableNew.headers)
refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end)) refreshHelper.updateLastRefreshTimestamp(getRefreshKey(cacheKey, semester, start, end))
if (!isFromAppWidget) {
appWidgetUpdater.updateAllAppWidgetsByProvider(TimetableWidgetProvider::class)
}
}, },
filterResult = { (timetable, additional, headers) -> filterResult = { (timetable, additional, headers) ->
TimetableFull( TimetableFull(

View File

@ -145,7 +145,11 @@ class LuckyNumberWidgetProvider : AppWidgetProvider() {
} }
if (currentStudent != null) { if (currentStudent != null) {
luckyNumberRepository.getLuckyNumber(currentStudent, forceRefresh = false) luckyNumberRepository.getLuckyNumber(
student = currentStudent,
forceRefresh = false,
isFromAppWidget = true
)
.toFirstResult() .toFirstResult()
.dataOrThrow .dataOrThrow
} else null } else null

View File

@ -104,7 +104,14 @@ class TimetableWidgetFactory(
private suspend fun getLessons( private suspend fun getLessons(
student: Student, semester: Semester, date: LocalDate student: Student, semester: Semester, date: LocalDate
): List<Timetable> { ): List<Timetable> {
val timetable = timetableRepository.getTimetable(student, semester, date, date, false) val timetable = timetableRepository.getTimetable(
student = student,
semester = semester,
start = date,
end = date,
forceRefresh = false,
isFromAppWidget = true
)
val lessons = timetable.toFirstResult().dataOrThrow.lessons val lessons = timetable.toFirstResult().dataOrThrow.lessons
return lessons.sortedBy { it.number } return lessons.sortedBy { it.number }
} }

View File

@ -0,0 +1,34 @@
package io.github.wulkanowy.utils
import android.appwidget.AppWidgetManager
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import dagger.hilt.android.qualifiers.ApplicationContext
import timber.log.Timber
import javax.inject.Inject
import kotlin.reflect.KClass
class AppWidgetUpdater @Inject constructor(
@ApplicationContext private val context: Context,
private val appWidgetManager: AppWidgetManager
) {
fun updateAllAppWidgetsByProvider(providerClass: KClass<out BroadcastReceiver>) {
try {
val ids = appWidgetManager.getAppWidgetIds(ComponentName(context, providerClass.java))
if (ids.isEmpty()) return
val intent = Intent(context, providerClass.java)
.apply {
action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
}
context.sendBroadcast(intent)
} catch (e: Exception) {
Timber.e(e, "Failed to update all widgets for provider $providerClass")
}
}
}

View File

@ -8,6 +8,7 @@ import io.github.wulkanowy.data.mappers.mapToEntity
import io.github.wulkanowy.data.toFirstResult import io.github.wulkanowy.data.toFirstResult
import io.github.wulkanowy.getStudentEntity import io.github.wulkanowy.getStudentEntity
import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.utils.AppWidgetUpdater
import io.mockk.MockKAnnotations import io.mockk.MockKAnnotations
import io.mockk.Runs import io.mockk.Runs
import io.mockk.coEvery import io.mockk.coEvery
@ -32,6 +33,9 @@ class LuckyNumberRemoteTest {
@MockK @MockK
private lateinit var luckyNumberDb: LuckyNumberDao private lateinit var luckyNumberDb: LuckyNumberDao
@MockK(relaxed = true)
private lateinit var appWidgetUpdater: AppWidgetUpdater
private val student = getStudentEntity() private val student = getStudentEntity()
private lateinit var luckyNumberRepository: LuckyNumberRepository private lateinit var luckyNumberRepository: LuckyNumberRepository
@ -44,7 +48,8 @@ class LuckyNumberRemoteTest {
fun setUp() { fun setUp() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
luckyNumberRepository = LuckyNumberRepository(luckyNumberDb, wulkanowySdkFactory) luckyNumberRepository =
LuckyNumberRepository(luckyNumberDb, wulkanowySdkFactory, appWidgetUpdater)
} }
@Test @Test

View File

@ -12,6 +12,7 @@ import io.github.wulkanowy.getSemesterEntity
import io.github.wulkanowy.getStudentEntity import io.github.wulkanowy.getStudentEntity
import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
import io.github.wulkanowy.utils.AppWidgetUpdater
import io.github.wulkanowy.utils.AutoRefreshHelper import io.github.wulkanowy.utils.AutoRefreshHelper
import io.mockk.MockKAnnotations import io.mockk.MockKAnnotations
import io.mockk.Runs import io.mockk.Runs
@ -53,6 +54,9 @@ class TimetableRepositoryTest {
@MockK(relaxUnitFun = true) @MockK(relaxUnitFun = true)
private lateinit var refreshHelper: AutoRefreshHelper private lateinit var refreshHelper: AutoRefreshHelper
@MockK(relaxed = true)
private lateinit var appWidgetUpdater: AppWidgetUpdater
private val student = getStudentEntity() private val student = getStudentEntity()
private val semester = getSemesterEntity() private val semester = getSemesterEntity()
@ -74,7 +78,8 @@ class TimetableRepositoryTest {
timetableHeaderDao, timetableHeaderDao,
wulkanowySdkFactory, wulkanowySdkFactory,
timetableNotificationSchedulerHelper, timetableNotificationSchedulerHelper,
refreshHelper refreshHelper,
appWidgetUpdater
) )
} }