diff --git a/data/src/main/java/com/android254/data/repos/SessionsManager.kt b/data/src/main/java/com/android254/data/repos/SessionsManager.kt index 88ede170..22b7259a 100644 --- a/data/src/main/java/com/android254/data/repos/SessionsManager.kt +++ b/data/src/main/java/com/android254/data/repos/SessionsManager.kt @@ -69,7 +69,7 @@ class SessionsManager @Inject constructor( sessions = sessions.map { session -> session.toDomainModel().copy( isBookmarked = bookmarks.map { it.sessionId } - .contains(session.id.toString()) + .contains(session.remote_id) ) }, eventDays = eventDays diff --git a/presentation/src/main/java/com/android254/presentation/common/components/SessionsCard.kt b/presentation/src/main/java/com/android254/presentation/common/components/SessionsCard.kt index 9aa2dfc0..b17230f9 100644 --- a/presentation/src/main/java/com/android254/presentation/common/components/SessionsCard.kt +++ b/presentation/src/main/java/com/android254/presentation/common/components/SessionsCard.kt @@ -155,9 +155,9 @@ fun SessionTitleComponent( onClick = { scope.launch { if (session.isStarred) { - viewModel.unBookmarkSession(session.id) + viewModel.unBookmarkSession(session.remoteId) } else { - viewModel.bookmarkSession(session.id) + viewModel.bookmarkSession(session.remoteId) } } } diff --git a/presentation/src/main/java/com/android254/presentation/home/screen/HomeScreen.kt b/presentation/src/main/java/com/android254/presentation/home/screen/HomeScreen.kt index 47f99829..2bdf61d4 100644 --- a/presentation/src/main/java/com/android254/presentation/home/screen/HomeScreen.kt +++ b/presentation/src/main/java/com/android254/presentation/home/screen/HomeScreen.kt @@ -30,7 +30,6 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android254.presentation.common.components.SponsorsCard -import com.android254.presentation.home.components.HomeBannerSection import com.android254.presentation.home.components.HomeHeaderSectionComponent import com.android254.presentation.home.components.HomeSessionLoadingComponent import com.android254.presentation.home.components.HomeSessionSection @@ -108,7 +107,7 @@ private fun HomeScreen( horizontalAlignment = Alignment.CenterHorizontally ) { HomeHeaderSectionComponent() - HomeBannerSection(viewState) +// HomeBannerSection(viewState) HomeSpacer() when { isSyncing -> { diff --git a/presentation/src/main/java/com/android254/presentation/sessions/view/SessionsViewModel.kt b/presentation/src/main/java/com/android254/presentation/sessions/view/SessionsViewModel.kt index 4d50501f..a5fbe354 100644 --- a/presentation/src/main/java/com/android254/presentation/sessions/view/SessionsViewModel.kt +++ b/presentation/src/main/java/com/android254/presentation/sessions/view/SessionsViewModel.kt @@ -18,7 +18,6 @@ package com.android254.presentation.sessions.view import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.android254.domain.models.Session -import com.android254.domain.models.SessionFilter import com.android254.domain.models.SessionsInformationDomainModel import com.android254.domain.repos.SessionsRepo import com.android254.domain.work.SyncDataWorkManager @@ -28,13 +27,16 @@ import com.android254.presentation.sessions.mappers.toPresentationModel import com.android254.presentation.sessions.models.SessionsUiState import com.android254.presentation.sessions.utils.SessionsFilterCategory import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext @HiltViewModel class SessionsViewModel @Inject constructor( @@ -46,12 +48,13 @@ class SessionsViewModel @Inject constructor( MutableStateFlow(emptyList()) val selectedFilterOptions = _selectedFilterOptions.asStateFlow() - private val _filterState: MutableStateFlow = - MutableStateFlow(SessionsFilterState()) + private var filterState = SessionsFilterState() private val _sessionsUiState = MutableStateFlow(SessionsUiState()) val sessionsUiState = _sessionsUiState.asStateFlow() + private val sessionsCache = mutableListOf() + val isRefreshing = syncDataWorkManager.isSyncing .stateIn( scope = viewModelScope, @@ -84,21 +87,21 @@ class SessionsViewModel @Inject constructor( private fun updateFilterState(option: SessionsFilterOption) { when (option.type) { SessionsFilterCategory.Level -> { - val newValue = _filterState.value?.levels?.toMutableList()?.apply { + val newValue = filterState.levels.toMutableList().apply { val index = this.indexOf(option.value) if (index < 0) { add(option.value) } else { removeAt(index) } - }?.toList() - _filterState.value = _filterState.value?.copy( - levels = newValue!! + }.toList() + filterState = filterState.copy( + levels = newValue ) } SessionsFilterCategory.Topic -> { - val newValue = _filterState.value!!.topics.toMutableList().apply { + val newValue = filterState.topics.toMutableList().apply { val index = this.indexOf(option.value) if (index < 0) { add(option.value) @@ -106,13 +109,13 @@ class SessionsViewModel @Inject constructor( removeAt(index) } }.toList() - _filterState.value = _filterState.value?.copy( + filterState = filterState.copy( topics = newValue ) } SessionsFilterCategory.Room -> { - val newValue = _filterState.value!!.rooms.toMutableList().apply { + val newValue = filterState.rooms.toMutableList().apply { val index = this.indexOf(option.value) if (index < 0) { add(option.value) @@ -120,13 +123,13 @@ class SessionsViewModel @Inject constructor( removeAt(index) } }.toList() - _filterState.value = _filterState.value?.copy( + filterState = filterState.copy( rooms = newValue ) } SessionsFilterCategory.SessionType -> { - val newValue = _filterState.value!!.sessionTypes.toMutableList().apply { + val newValue = filterState.sessionTypes.toMutableList().apply { val index = this.indexOf(option.value) if (index < 0) { add(option.value) @@ -134,7 +137,7 @@ class SessionsViewModel @Inject constructor( removeAt(index) } }.toList() - _filterState.value = _filterState.value!!.copy( + filterState = filterState.copy( sessionTypes = newValue ) } @@ -143,58 +146,84 @@ class SessionsViewModel @Inject constructor( private suspend fun fetchAllSessions() { updateIsLoadingState() - sessionsRepo.fetchSessionsInformation().collectLatest { sessionsInformation -> - updateSessionDays(sessionsInformation) - updateSessions(sessionsInformation.sessions) + if (sessionsCache.isEmpty()) { + sessionsRepo.fetchSessionsInformation().collectLatest { sessionsInformation -> + sessionsCache.addAll(sessionsInformation.sessions) + + updateSessionDays(sessionsInformation) + fetchFilteredSessions() + } } } private fun updateSessionDays(sessionsInformation: SessionsInformationDomainModel) { if (sessionsInformation.eventDays.isNotEmpty()) { val sessionDays = sessionsInformation.eventDays.mapIndexed { index, day -> EventDate(value = day, day = index + 1) } - _sessionsUiState.value = _sessionsUiState.value.copy( - eventDays = sessionDays, - selectedEventDay = sessionDays.first() - ) + _sessionsUiState.update { + it.copy( + eventDays = sessionDays, + selectedEventDay = sessionDays.first() + ) + } } } - private suspend fun fetchFilteredSessions() { + private suspend fun fetchFilteredSessions() = withContext(Dispatchers.Default) { updateIsLoadingState() - sessionsRepo.fetchFilteredSessions( - filter = SessionFilter( - levels = _filterState.value?.levels ?: emptyList(), - rooms = _filterState.value?.rooms ?: emptyList(), - sessionFormats = _filterState.value?.sessionTypes ?: emptyList(), - bookmarked = _filterState.value?.isBookmarked ?: false - ) - ).collectLatest { sessions -> - updateSessions(sessions) - } + updateSessions( + sessionsCache.asSequence().filter { + if (filterState.levels.isNotEmpty()) { + filterState.levels.contains(it.sessionLevel) + } else { + true + } + }.filter { + if (filterState.rooms.isNotEmpty()) { + filterState.rooms.contains(it.rooms) + } else { + true + } + }.filter { + if (filterState.sessionTypes.isNotEmpty()) { + filterState.sessionTypes.contains(it.sessionFormat) + } else { + true + } + }.filter { + if (filterState.isBookmarked) { + it.isBookmarked + } else { + true + } + }.distinctBy { it.remoteId }.toList() + ) } private fun updateSessions(sessions: List) { - val state = _sessionsUiState.value - val newState = if (sessions.isEmpty()) { - state.copy( - isEmpty = true, - sessions = emptyList(), - isEmptyMessage = "No sessions found", - isLoading = false - ) - } else { - state.copy( - isEmpty = false, - sessions = sessions.map { session -> session.toPresentationModel() }.filter { session -> session.eventDay == state.selectedEventDay.value }, - isEmptyMessage = "", - isLoading = false - ) + val selectedDay = _sessionsUiState.value.selectedEventDay.value + _sessionsUiState.update { + if (sessions.isEmpty()) { + it.copy( + isEmpty = true, + sessions = emptyList(), + isEmptyMessage = "No sessions found", + isLoading = false + ) + } else { + it.copy( + isEmpty = false, + sessions = sessions.map { session -> session.toPresentationModel() }.filter { session -> session.eventDay == selectedDay }, + isEmptyMessage = "", + isLoading = false + ) + } } - _sessionsUiState.value = newState } private fun updateIsLoadingState() { - _sessionsUiState.value = _sessionsUiState.value.copy(isLoading = true) + _sessionsUiState.update { + it.copy(isLoading = true) + } } fun fetchSessionWithFilter() { @@ -205,9 +234,9 @@ class SessionsViewModel @Inject constructor( fun clearSelectedFilterList() { _selectedFilterOptions.value = listOf() - _filterState.value = SessionsFilterState() + filterState = SessionsFilterState() viewModelScope.launch { - fetchAllSessions() + fetchFilteredSessions() } } @@ -222,7 +251,8 @@ class SessionsViewModel @Inject constructor( fun refreshSessionList() { _selectedFilterOptions.value = listOf() - _filterState.value = SessionsFilterState() + filterState = SessionsFilterState(isBookmarked = filterState.isBookmarked) + sessionsCache.clear() viewModelScope.launch { syncDataWorkManager.startSync() } @@ -230,22 +260,20 @@ class SessionsViewModel @Inject constructor( suspend fun bookmarkSession(id: String) { sessionsRepo.bookmarkSession(id = id) + sessionsCache.clear() + fetchAllSessions() } suspend fun unBookmarkSession(id: String) { sessionsRepo.unBookmarkSession(id = id) + sessionsCache.clear() + fetchAllSessions() } fun toggleBookmarkFilter() { + filterState = filterState.copy(isBookmarked = !filterState.isBookmarked) viewModelScope.launch { - _filterState.value = SessionsFilterState() - val previousState = _filterState.value?.isBookmarked ?: false - _filterState.value = _filterState.value?.copy(isBookmarked = !previousState) - if (_filterState.value?.isBookmarked == true) { - fetchFilteredSessions() - } else { - fetchAllSessions() - } + fetchFilteredSessions() } } } \ No newline at end of file