mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-24 03:36:51 +00:00
refactor(home): extract refresh side effects
Centralize home refresh orchestration so future refresh side effects can be added through Hilt multibindings instead of expanding AppViewModel.
This commit is contained in:
@@ -12,6 +12,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import hu.bbara.purefin.core.data.DownloadMediaSourceResolver
|
||||
import hu.bbara.purefin.core.data.OfflineCatalogStore
|
||||
import hu.bbara.purefin.core.data.SmartDownloadStore
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -230,6 +231,8 @@ class MediaDownloadManager @Inject constructor(
|
||||
for (seriesId in enabledSeriesIds) {
|
||||
try {
|
||||
syncSmartDownloadsForSeries(seriesId)
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
} catch (e: Exception) {
|
||||
Timber.tag(TAG).e(e, "Smart download sync failed for series $seriesId")
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import hu.bbara.purefin.core.data.HomeRepository
|
||||
import hu.bbara.purefin.core.data.LocalMediaRepository
|
||||
import hu.bbara.purefin.core.data.NetworkMonitor
|
||||
import hu.bbara.purefin.core.data.UserSessionRepository
|
||||
import hu.bbara.purefin.core.download.MediaDownloadController
|
||||
import hu.bbara.purefin.core.feature.browse.home.refresh.HomeRefreshCoordinator
|
||||
import hu.bbara.purefin.core.jellyfin.JellyfinMediaMetadataUpdater
|
||||
import hu.bbara.purefin.core.settings.SettingsRepository
|
||||
import hu.bbara.purefin.core.model.EpisodeUiModel
|
||||
@@ -41,7 +41,7 @@ class AppViewModel @Inject constructor(
|
||||
private val userSessionRepository: UserSessionRepository,
|
||||
private val jellyfinMediaMetadataUpdater: JellyfinMediaMetadataUpdater,
|
||||
private val navigationManager: NavigationManager,
|
||||
private val mediaDownloadManager: MediaDownloadController,
|
||||
private val homeRefreshCoordinator: HomeRefreshCoordinator,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
networkMonitor: NetworkMonitor,
|
||||
) : ViewModel() {
|
||||
@@ -253,35 +253,16 @@ class AppViewModel @Inject constructor(
|
||||
|
||||
fun onResumed() {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
homeRepository.refreshHomeData()
|
||||
} catch (e: Exception) {
|
||||
// Refresh is best-effort; don't crash on failure
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
mediaDownloadManager.syncSmartDownloads()
|
||||
} catch (_: Exception) { }
|
||||
homeRefreshCoordinator.onResumed()
|
||||
}
|
||||
}
|
||||
|
||||
fun onRefresh() {
|
||||
viewModelScope.launch {
|
||||
_isRefreshing.value = true
|
||||
try {
|
||||
homeRepository.refreshHomeData()
|
||||
} catch (e: Exception) {
|
||||
// Refresh is best-effort; don't crash on failure
|
||||
} finally {
|
||||
_isRefreshing.value = false
|
||||
homeRefreshCoordinator.onRefresh { isRefreshing ->
|
||||
_isRefreshing.value = isRefreshing
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
mediaDownloadManager.syncSmartDownloads()
|
||||
} catch (_: Exception) { }
|
||||
}
|
||||
}
|
||||
|
||||
fun openSearch() {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package hu.bbara.purefin.core.feature.browse.home.refresh
|
||||
|
||||
import hu.bbara.purefin.core.data.HomeRepository
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import javax.inject.Inject
|
||||
|
||||
class HomeRefreshCoordinator @Inject constructor(
|
||||
private val homeRepository: HomeRepository,
|
||||
private val sideEffects: Set<@JvmSuppressWildcards HomeRefreshSideEffect>,
|
||||
) {
|
||||
private val sideEffectsMutex = Mutex()
|
||||
|
||||
suspend fun onResumed() {
|
||||
refreshHomeData()
|
||||
runSideEffects()
|
||||
}
|
||||
|
||||
suspend fun onRefresh(setRefreshing: (Boolean) -> Unit) {
|
||||
refreshHomeData(setRefreshing)
|
||||
runSideEffects()
|
||||
}
|
||||
|
||||
private suspend fun refreshHomeData(
|
||||
setRefreshing: ((Boolean) -> Unit)? = null,
|
||||
) {
|
||||
setRefreshing?.invoke(true)
|
||||
try {
|
||||
homeRepository.refreshHomeData()
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
} catch (e: Exception) {
|
||||
// Refresh is best-effort; don't crash on failure
|
||||
} finally {
|
||||
setRefreshing?.invoke(false)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun runSideEffects() {
|
||||
sideEffectsMutex.withLock {
|
||||
coroutineScope {
|
||||
sideEffects.forEach { sideEffect ->
|
||||
launch {
|
||||
try {
|
||||
sideEffect.run()
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
} catch (_: Exception) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package hu.bbara.purefin.core.feature.browse.home.refresh
|
||||
|
||||
interface HomeRefreshSideEffect {
|
||||
suspend fun run()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package hu.bbara.purefin.core.feature.browse.home.refresh
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import dagger.multibindings.IntoSet
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
abstract class HomeRefreshSideEffectModule {
|
||||
|
||||
@Binds
|
||||
@IntoSet
|
||||
abstract fun bindSyncSmartDownloadsHomeRefreshSideEffect(
|
||||
impl: SyncSmartDownloadsHomeRefreshSideEffect
|
||||
): HomeRefreshSideEffect
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package hu.bbara.purefin.core.feature.browse.home.refresh
|
||||
|
||||
import hu.bbara.purefin.core.download.MediaDownloadController
|
||||
import javax.inject.Inject
|
||||
|
||||
class SyncSmartDownloadsHomeRefreshSideEffect @Inject constructor(
|
||||
private val mediaDownloadController: MediaDownloadController,
|
||||
) : HomeRefreshSideEffect {
|
||||
|
||||
override suspend fun run() {
|
||||
mediaDownloadController.syncSmartDownloads()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user