refactor: NavHostViewModel stage 4 - extract favorites state holder
This commit is contained in:
parent
d942fbf3a0
commit
72054ad442
3 changed files with 78 additions and 46 deletions
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.garfiec.librechat.shared.navigation
|
||||||
|
|
||||||
|
import co.touchlab.kermit.Logger
|
||||||
|
import com.garfiec.librechat.core.data.datastore.SettingsDataStore
|
||||||
|
import com.garfiec.librechat.core.model.Conversation
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class FavoritesStateHolder(
|
||||||
|
private val settingsDataStore: SettingsDataStore,
|
||||||
|
private val recentConversations: StateFlow<List<Conversation>>,
|
||||||
|
private val scope: CoroutineScope,
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val _favorites = MutableStateFlow<Set<String>>(emptySet())
|
||||||
|
val favorites: StateFlow<Set<String>> = _favorites.asStateFlow()
|
||||||
|
|
||||||
|
private val _favoriteConversations = MutableStateFlow<List<Conversation>>(emptyList())
|
||||||
|
val favoriteConversations: StateFlow<List<Conversation>> = _favoriteConversations.asStateFlow()
|
||||||
|
|
||||||
|
init {
|
||||||
|
observeBookmarks()
|
||||||
|
observeRecentConversations()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeBookmarks() {
|
||||||
|
scope.launch {
|
||||||
|
try {
|
||||||
|
settingsDataStore.bookmarkedConversationIds.collect { bookmarkedIds ->
|
||||||
|
_favorites.value = bookmarkedIds
|
||||||
|
updateFavoriteConversations()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Logger.w(e) { "Failed to observe bookmarks" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeRecentConversations() {
|
||||||
|
scope.launch {
|
||||||
|
recentConversations.collect {
|
||||||
|
updateFavoriteConversations()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toggleFavorite(conversationId: String) {
|
||||||
|
scope.launch {
|
||||||
|
settingsDataStore.toggleBookmark(conversationId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateFavoriteConversations() {
|
||||||
|
val bookmarkedIds = _favorites.value
|
||||||
|
val allConversations = recentConversations.value
|
||||||
|
_favoriteConversations.value = allConversations.filter { conversation ->
|
||||||
|
conversation.conversationId in bookmarkedIds ||
|
||||||
|
conversation.tags.any {
|
||||||
|
it.equals("favorite", ignoreCase = true) ||
|
||||||
|
it.equals("bookmark", ignoreCase = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reset() {
|
||||||
|
_favorites.value = emptySet()
|
||||||
|
_favoriteConversations.value = emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -68,15 +68,13 @@ class NavHostViewModel(
|
||||||
private val bannerStateHolder = BannerStateHolder(bannerRepository, viewModelScope)
|
private val bannerStateHolder = BannerStateHolder(bannerRepository, viewModelScope)
|
||||||
private val versionCheckStateHolder = VersionCheckStateHolder(configRepository, settingsDataStore, viewModelScope)
|
private val versionCheckStateHolder = VersionCheckStateHolder(configRepository, settingsDataStore, viewModelScope)
|
||||||
private val conversationListStateHolder = ConversationListStateHolder(conversationRepository, viewModelScope)
|
private val conversationListStateHolder = ConversationListStateHolder(conversationRepository, viewModelScope)
|
||||||
|
private val favoritesStateHolder = FavoritesStateHolder(settingsDataStore, conversationListStateHolder.recentConversations, viewModelScope)
|
||||||
|
|
||||||
private val _isLoggedIn = MutableStateFlow(tokenManager.isAuthenticated)
|
private val _isLoggedIn = MutableStateFlow(tokenManager.isAuthenticated)
|
||||||
val isLoggedIn: StateFlow<Boolean> = _isLoggedIn.asStateFlow()
|
val isLoggedIn: StateFlow<Boolean> = _isLoggedIn.asStateFlow()
|
||||||
|
|
||||||
val versionMismatch: StateFlow<VersionMismatchState?> = versionCheckStateHolder.versionMismatch
|
val versionMismatch: StateFlow<VersionMismatchState?> = versionCheckStateHolder.versionMismatch
|
||||||
|
|
||||||
private val _favorites = MutableStateFlow<Set<String>>(emptySet())
|
|
||||||
private val _favoriteConversations = MutableStateFlow<List<Conversation>>(emptyList())
|
|
||||||
|
|
||||||
val banners: StateFlow<List<Banner>> = bannerStateHolder.banners
|
val banners: StateFlow<List<Banner>> = bannerStateHolder.banners
|
||||||
val dismissedBannerIds: StateFlow<Set<String>> = bannerStateHolder.dismissedBannerIds
|
val dismissedBannerIds: StateFlow<Set<String>> = bannerStateHolder.dismissedBannerIds
|
||||||
|
|
||||||
|
|
@ -110,8 +108,8 @@ class NavHostViewModel(
|
||||||
combine(
|
combine(
|
||||||
conversationListStateHolder.groupedConversations,
|
conversationListStateHolder.groupedConversations,
|
||||||
conversationListStateHolder.activeConversationId,
|
conversationListStateHolder.activeConversationId,
|
||||||
_favorites,
|
favoritesStateHolder.favorites,
|
||||||
_favoriteConversations,
|
favoritesStateHolder.favoriteConversations,
|
||||||
conversationListStateHolder.searchQuery,
|
conversationListStateHolder.searchQuery,
|
||||||
) { grouped, activeId, favIds, favConvos, query ->
|
) { grouped, activeId, favIds, favConvos, query ->
|
||||||
DrawerDataSnapshot(grouped, activeId, favIds, favConvos, query)
|
DrawerDataSnapshot(grouped, activeId, favIds, favConvos, query)
|
||||||
|
|
@ -148,19 +146,9 @@ class NavHostViewModel(
|
||||||
Logger.w(e) { "Failed to check auth state on init" }
|
Logger.w(e) { "Failed to check auth state on init" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
observeBookmarks()
|
|
||||||
observeRecentConversationsForFavorites()
|
|
||||||
bannerStateHolder.fetchBanners()
|
bannerStateHolder.fetchBanners()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeRecentConversationsForFavorites() {
|
|
||||||
viewModelScope.launch {
|
|
||||||
conversationListStateHolder.recentConversations.collect {
|
|
||||||
updateFavoriteConversations()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadMoreConversations() {
|
fun loadMoreConversations() {
|
||||||
conversationListStateHolder.loadMoreConversations()
|
conversationListStateHolder.loadMoreConversations()
|
||||||
}
|
}
|
||||||
|
|
@ -184,35 +172,8 @@ class NavHostViewModel(
|
||||||
conversationListStateHolder.onSearchQueryChanged(query)
|
conversationListStateHolder.onSearchQueryChanged(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeBookmarks() {
|
|
||||||
viewModelScope.launch {
|
|
||||||
try {
|
|
||||||
settingsDataStore.bookmarkedConversationIds.collect { bookmarkedIds ->
|
|
||||||
_favorites.value = bookmarkedIds
|
|
||||||
updateFavoriteConversations()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Logger.w(e) { "Failed to observe bookmarks" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toggleFavorite(conversationId: String) {
|
fun toggleFavorite(conversationId: String) {
|
||||||
viewModelScope.launch {
|
favoritesStateHolder.toggleFavorite(conversationId)
|
||||||
settingsDataStore.toggleBookmark(conversationId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateFavoriteConversations() {
|
|
||||||
val bookmarkedIds = _favorites.value
|
|
||||||
val allConversations = conversationListStateHolder.recentConversations.value
|
|
||||||
_favoriteConversations.value = allConversations.filter { conversation ->
|
|
||||||
conversation.conversationId in bookmarkedIds ||
|
|
||||||
conversation.tags.any {
|
|
||||||
it.equals("favorite", ignoreCase = true) ||
|
|
||||||
it.equals("bookmark", ignoreCase = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTabletSidebarOpen(open: Boolean) {
|
fun setTabletSidebarOpen(open: Boolean) {
|
||||||
|
|
@ -238,8 +199,7 @@ class NavHostViewModel(
|
||||||
authRepository.logout()
|
authRepository.logout()
|
||||||
_isLoggedIn.value = false
|
_isLoggedIn.value = false
|
||||||
conversationListStateHolder.reset()
|
conversationListStateHolder.reset()
|
||||||
_favorites.value = emptySet()
|
favoritesStateHolder.reset()
|
||||||
_favoriteConversations.value = emptyList()
|
|
||||||
_sidebarMode.value = SidebarMode.Conversations
|
_sidebarMode.value = SidebarMode.Conversations
|
||||||
_selectedSettingsCategory.value = null
|
_selectedSettingsCategory.value = null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ class VersionCheckStateHolder(
|
||||||
is Result.Error -> {
|
is Result.Error -> {
|
||||||
Logger.w(result.exception) { "Failed to check backend version: ${result.message}" }
|
Logger.w(result.exception) { "Failed to check backend version: ${result.message}" }
|
||||||
}
|
}
|
||||||
else -> {}
|
is Result.Loading -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue