Skip to content

Commit

Permalink
refactor: Improve logic for filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbukachi committed Nov 7, 2023
1 parent d340e67 commit eaf7039
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(
Expand All @@ -46,12 +48,13 @@ class SessionsViewModel @Inject constructor(
MutableStateFlow(emptyList())
val selectedFilterOptions = _selectedFilterOptions.asStateFlow()

private val _filterState: MutableStateFlow<SessionsFilterState?> =
MutableStateFlow(SessionsFilterState())
private var filterState = SessionsFilterState()

private val _sessionsUiState = MutableStateFlow(SessionsUiState())
val sessionsUiState = _sessionsUiState.asStateFlow()

private val sessionsCache = mutableListOf<Session>()

val isRefreshing = syncDataWorkManager.isSyncing
.stateIn(
scope = viewModelScope,
Expand Down Expand Up @@ -84,57 +87,57 @@ 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)
} else {
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)
} else {
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)
} else {
removeAt(index)
}
}.toList()
_filterState.value = _filterState.value!!.copy(
filterState = filterState.copy(
sessionTypes = newValue
)
}
Expand All @@ -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<Session>) {
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() {
Expand All @@ -205,9 +234,9 @@ class SessionsViewModel @Inject constructor(

fun clearSelectedFilterList() {
_selectedFilterOptions.value = listOf()
_filterState.value = SessionsFilterState()
filterState = SessionsFilterState()
viewModelScope.launch {
fetchAllSessions()
fetchFilteredSessions()
}
}

Expand All @@ -222,30 +251,29 @@ class SessionsViewModel @Inject constructor(

fun refreshSessionList() {
_selectedFilterOptions.value = listOf()
_filterState.value = SessionsFilterState()
filterState = SessionsFilterState(isBookmarked = filterState.isBookmarked)
sessionsCache.clear()
viewModelScope.launch {
syncDataWorkManager.startSync()
}
}

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()
}
}
}

0 comments on commit eaf7039

Please sign in to comment.