Skip to content

Commit

Permalink
Refactor: Migrate data operations to FavoritesRepository
Browse files Browse the repository at this point in the history
This commit refactors data operations related to favorites and watched chapters by migrating them to a new `FavoritesRepository` class.

- Created a new `FavoritesRepository` to centralize data operations for favorites and watched chapters.
- Moved favorite and watched chapter-related functions from ViewModels and Fragments to the `FavoritesRepository`.
- Updated ViewModels and Fragments to use the `FavoritesRepository` for data operations.
- Updated the Koin module to include the `FavoritesRepository`.
- Removed direct database and FirebaseDb calls from ViewModels and Fragments.
- Updated related dependencies and imports.
- Improved code organization and maintainability by centralizing data operations.
  • Loading branch information
jacobrein committed Jan 23, 2025
1 parent f84d5da commit 3b4a1b1
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.programmersbox.uiviews.di
import com.programmersbox.extensionloader.SourceRepository
import com.programmersbox.uiviews.repository.ChangingSettingsRepository
import com.programmersbox.uiviews.repository.CurrentSourceRepository
import com.programmersbox.uiviews.repository.FavoritesRepository
import com.programmersbox.uiviews.repository.NotificationRepository
import org.koin.core.module.Module
import org.koin.core.module.dsl.singleOf
Expand All @@ -12,4 +13,5 @@ fun Module.repository() {
single { CurrentSourceRepository() }
single { ChangingSettingsRepository() }
singleOf(::NotificationRepository)
singleOf(::FavoritesRepository)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@ import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.toMutableStateList
import androidx.compose.ui.util.fastMaxBy
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.programmersbox.favoritesdatabase.DbModel
import com.programmersbox.favoritesdatabase.ItemDao
import com.programmersbox.models.ApiService
import com.programmersbox.models.ItemModel
import com.programmersbox.uiviews.repository.CurrentSourceRepository
import com.programmersbox.uiviews.repository.FavoritesRepository
import com.programmersbox.uiviews.utils.DefaultToastItems
import com.programmersbox.uiviews.utils.ToastItems
import com.programmersbox.uiviews.utils.dispatchIoAndCatchList
import com.programmersbox.uiviews.utils.fireListener
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flowOn
Expand All @@ -31,6 +30,7 @@ import ru.beryukhov.reactivenetwork.ReactiveNetwork
class AllViewModel(
dao: ItemDao,
private val currentSourceRepository: CurrentSourceRepository,
favoritesRepository: FavoritesRepository,
) : ViewModel(), ToastItems by DefaultToastItems() {

val observeNetwork = ReactiveNetwork()
Expand All @@ -51,10 +51,8 @@ class AllViewModel(
private val itemListener = fireListener()

init {
combine(
itemListener.getAllShowsFlow(),
dao.getAllFavorites()
) { f, d -> (f + d).groupBy(DbModel::url).map { it.value.fastMaxBy(DbModel::numChapters)!! } }
favoritesRepository
.getAllFavorites(itemListener)
.onEach { favoriteList = it.toMutableStateList() }
.launchIn(viewModelScope)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,16 @@ import com.kmpalette.palette.graphics.Palette
import com.programmersbox.extensionloader.SourceRepository
import com.programmersbox.favoritesdatabase.ChapterWatched
import com.programmersbox.favoritesdatabase.DbModel
import com.programmersbox.favoritesdatabase.ItemDao
import com.programmersbox.favoritesdatabase.toDbModel
import com.programmersbox.gsonutils.fromJson
import com.programmersbox.models.ApiService
import com.programmersbox.models.ChapterModel
import com.programmersbox.models.InfoModel
import com.programmersbox.models.ItemModel
import com.programmersbox.sharedutils.FirebaseDb
import com.programmersbox.sharedutils.TranslateItems
import com.programmersbox.uiviews.GenericInfo
import com.programmersbox.uiviews.presentation.Screen
import com.programmersbox.uiviews.repository.FavoritesRepository
import com.programmersbox.uiviews.utils.ApiServiceDeserializer
import com.programmersbox.uiviews.utils.Cached
import com.programmersbox.uiviews.utils.ComposableUtils
Expand All @@ -37,9 +36,9 @@ import com.programmersbox.uiviews.utils.dispatchIo
import com.programmersbox.uiviews.utils.fireListener
import com.programmersbox.uiviews.utils.recordFirebaseException
import com.vanniktech.blurhash.BlurHash
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
Expand All @@ -53,9 +52,9 @@ import kotlinx.coroutines.launch
class DetailsViewModel(
handle: SavedStateHandle,
genericInfo: GenericInfo,
private val dao: ItemDao,
private val blurHashDao: BlurHashDao,
sourceRepository: SourceRepository,
private val favoritesRepository: FavoritesRepository,
) : ViewModel() {

private val details: Screen.DetailsScreen.Details? = handle.toRoute()
Expand Down Expand Up @@ -169,10 +168,7 @@ class DetailsViewModel(
suspend fun toggleNotify() {
dbModel
?.let { it.copy(shouldCheckForUpdate = !it.shouldCheckForUpdate) }
?.let {
dao.updateFavoriteItem(it)
FirebaseDb.toggleUpdateCheckShowFlow(it).collect()
}
?.let { favoritesRepository.toggleNotify(it) }
}

private val englishTranslator = TranslateItems()
Expand All @@ -186,25 +182,28 @@ class DetailsViewModel(
}

private fun setup(info: InfoModel) {
combine(
itemListener.findItemByUrlFlow(info.url),
dao.containsItem(info.url)
) { f, d -> f || d }
favoritesRepository
.isFavorite(
url = info.url,
fireListenerClosable = itemListener,
)
.dispatchIo()
.onEach { favoriteListener = it }
.launchIn(viewModelScope)

combine(
chapterListener.getAllEpisodesByShowFlow(info.url),
dao.getAllChapters(info.url)
) { f, d -> (f + d).distinctBy { it.url } }
favoritesRepository
.getChapters(
url = info.url,
fireListenerClosable = chapterListener,
)
.onEach { chapters = it }
.launchIn(viewModelScope)

combine(
dao.getDbModel(info.url),
dbModelListener.getShowFlow(info.url)
) { d, f -> f ?: d }
favoritesRepository
.getModel(
url = info.url,
fireListenerClosable = dbModelListener,
)
.onEach { dbModel = it }
.launchIn(viewModelScope)
}
Expand All @@ -217,8 +216,11 @@ class DetailsViewModel(
)

viewModelScope.launch {
if (b) dao.insertChapter(chapter) else dao.deleteChapter(chapter)
(if (b) FirebaseDb.insertEpisodeWatchedFlow(chapter) else FirebaseDb.removeEpisodeWatchedFlow(chapter)).collect()
if (b) {
favoritesRepository.addWatched(chapter)
} else {
favoritesRepository.removeWatched(chapter)
}
}
}

Expand All @@ -227,13 +229,12 @@ class DetailsViewModel(
is DetailFavoriteAction.Add -> {
val db = action.info.toDbModel(action.info.chapters.size)
addRemoveFavoriteJob?.cancel()
addRemoveFavoriteJob = viewModelScope.launch {
dao.insertFavorite(db)
FirebaseDb.insertShowFlow(db).collect()
addRemoveFavoriteJob = viewModelScope.launch(Dispatchers.IO) {
favoritesRepository.addFavorite(db)
}

imageBitmap?.let {
viewModelScope.launch {
viewModelScope.launch(Dispatchers.IO) {
blurHashDao.insertHash(
BlurHashItem(
action.info.imageUrl,
Expand All @@ -247,12 +248,11 @@ class DetailsViewModel(
is DetailFavoriteAction.Remove -> {
val db = action.info.toDbModel(action.info.chapters.size)
addRemoveFavoriteJob?.cancel()
addRemoveFavoriteJob = viewModelScope.launch {
dao.deleteFavorite(db)
FirebaseDb.removeShowFlow(db).collect()
addRemoveFavoriteJob = viewModelScope.launch(Dispatchers.IO) {
favoritesRepository.removeFavorite(db)
}

viewModelScope.launch {
viewModelScope.launch(Dispatchers.IO) {
blurHashItem?.let { blurHashDao.deleteHash(it) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,18 @@ import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.util.fastMap
import androidx.compose.ui.util.fastMaxBy
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.programmersbox.extensionloader.SourceRepository
import com.programmersbox.favoritesdatabase.DbModel
import com.programmersbox.favoritesdatabase.ItemDao
import com.programmersbox.uiviews.repository.FavoritesRepository
import com.programmersbox.uiviews.utils.fireListener
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

class FavoriteViewModel(
dao: ItemDao,
private val sourceRepository: SourceRepository,
favoritesRepository: FavoritesRepository,
) : ViewModel() {

private val fireListener = fireListener("favorite")
Expand All @@ -31,10 +29,8 @@ class FavoriteViewModel(
private val fullSourceList get() = (sourceList + favoriteList.map { it.source }).distinct()

init {
combine(
fireListener.getAllShowsFlow(),
dao.getAllFavorites()
) { f, d -> (f + d).groupBy(DbModel::url).map { it.value.fastMaxBy(DbModel::numChapters)!! } }
favoritesRepository
.getAllFavorites(fireListener)
.onEach {
favoriteList.clear()
favoriteList.addAll(it)
Expand Down Expand Up @@ -107,11 +103,6 @@ class FavoriteViewModel(
resetSources()
}
}

override fun onCleared() {
super.onCleared()
fireListener.unregister()
}
}

sealed class SortFavoritesBy<K>(val sort: (Map.Entry<String, List<DbModel>>) -> K) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.util.fastMaxBy
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.programmersbox.extensionloader.SourceRepository
Expand All @@ -18,13 +17,13 @@ import com.programmersbox.models.ApiService
import com.programmersbox.models.ItemModel
import com.programmersbox.models.SourceInformation
import com.programmersbox.uiviews.repository.CurrentSourceRepository
import com.programmersbox.uiviews.repository.FavoritesRepository
import com.programmersbox.uiviews.utils.combineSources
import com.programmersbox.uiviews.utils.dispatchIo
import com.programmersbox.uiviews.utils.fireListener
import com.programmersbox.uiviews.utils.recordFirebaseException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flowOn
Expand All @@ -39,6 +38,7 @@ class RecentViewModel(
dao: ItemDao,
sourceRepository: SourceRepository,
currentSourceRepository: CurrentSourceRepository,
favoritesRepository: FavoritesRepository,
) : ViewModel() {

var isRefreshing by mutableStateOf(false)
Expand Down Expand Up @@ -71,10 +71,8 @@ class RecentViewModel(
}
.launchIn(viewModelScope)

combine(
itemListener.getAllShowsFlow(),
dao.getAllFavorites()
) { f, d -> (f + d).groupBy(DbModel::url).map { it.value.fastMaxBy(DbModel::numChapters)!! } }
favoritesRepository
.getAllFavorites(itemListener)
.onEach {
favoriteList.clear()
favoriteList.addAll(it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.programmersbox.favoritesdatabase.ItemDao
import com.programmersbox.gsonutils.fromJson
import com.programmersbox.gsonutils.toJson
import com.programmersbox.sharedutils.FirebaseDb
import com.programmersbox.uiviews.repository.FavoritesRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
Expand All @@ -24,6 +25,7 @@ import java.io.InputStreamReader

class MoreSettingsViewModel(
private val dao: ItemDao,
private val favoritesRepository: FavoritesRepository,
) : ViewModel() {

var importExportListStatus: ImportExportListStatus by mutableStateOf(ImportExportListStatus.Idle)
Expand All @@ -46,8 +48,7 @@ class MoreSettingsViewModel(
}
.onSuccess { list ->
list?.forEach {
dao.insertFavorite(it)
FirebaseDb.insertShowFlow(it)
favoritesRepository.addFavorite(it)
}
importExportListStatus = ImportExportListStatus.Success
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.programmersbox.uiviews.repository

import androidx.compose.ui.util.fastMaxBy
import com.programmersbox.favoritesdatabase.ChapterWatched
import com.programmersbox.favoritesdatabase.DbModel
import com.programmersbox.favoritesdatabase.ItemDao
import com.programmersbox.sharedutils.FirebaseDb
import com.programmersbox.uiviews.utils.FireListenerClosable
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine

class FavoritesRepository(
private val dao: ItemDao,
) {

suspend fun addFavorite(db: DbModel) {
dao.insertFavorite(db)
FirebaseDb.insertShowFlow(db).collect()
}

suspend fun removeFavorite(db: DbModel) {
dao.deleteFavorite(db)
FirebaseDb.removeShowFlow(db).collect()
}

suspend fun addWatched(chapterWatched: ChapterWatched) {
dao.insertChapter(chapterWatched)
FirebaseDb.insertEpisodeWatchedFlow(chapterWatched).collect()
}

suspend fun removeWatched(chapterWatched: ChapterWatched) {
dao.deleteChapter(chapterWatched)
FirebaseDb.removeEpisodeWatchedFlow(chapterWatched).collect()
}

suspend fun toggleNotify(db: DbModel) {
dao.updateFavoriteItem(db)
FirebaseDb.toggleUpdateCheckShowFlow(db).collect()
}

fun isFavorite(
url: String,
fireListenerClosable: FireListenerClosable,
) = combine(
fireListenerClosable.findItemByUrlFlow(url),
dao.containsItem(url)
) { f, d -> f || d }

fun getChapters(
url: String,
fireListenerClosable: FireListenerClosable,
) = combine(
fireListenerClosable.getAllEpisodesByShowFlow(url),
dao.getAllChapters(url)
) { f, d -> (f + d).distinctBy { it.url } }

fun getModel(
url: String,
fireListenerClosable: FireListenerClosable,
) = combine(
fireListenerClosable.getShowFlow(url),
dao.getDbModel(url),
) { d, f -> d ?: f }

fun getAllFavorites(fireListenerClosable: FireListenerClosable) = combine(
fireListenerClosable.getAllShowsFlow(),
dao.getAllFavorites()
) { f, d -> (f + d).groupBy(DbModel::url).map { it.value.fastMaxBy(DbModel::numChapters)!! } }

}
Loading

0 comments on commit 3b4a1b1

Please sign in to comment.