Skip to content

Commit

Permalink
Add paging in book list screen
Browse files Browse the repository at this point in the history
  • Loading branch information
Tibi19 committed Mar 22, 2023
1 parent cea3635 commit 080927b
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.hilt.navigation.compose.hiltViewModel
import com.tam.tesbooks.presentation.reusable.BookCardItem
import com.tam.tesbooks.presentation.reusable.LoadingMoreIndicator
import com.tam.tesbooks.presentation.reusable.OnErrorEffect
import com.tam.tesbooks.presentation.screen.bookmarks.BookmarksEvent

@OptIn(ExperimentalFoundationApi::class)
@Composable
Expand Down Expand Up @@ -53,7 +55,27 @@ fun BookListScreen(
},
onClick = { goToBookScreen(bookInfo.bookId) }
)

if (state.bookInfos.last() == bookInfo) {
decideLoadingMoreBookInfos(state, bookListViewModel)
}
}

item {
if (!state.isLoading) return@item
LoadingMoreIndicator()
}

}
}
}

private fun decideLoadingMoreBookInfos(
state: BookListState,
bookListViewModel: BookListViewModel
) {
val shouldLoadMore = state.canLoadMore && !state.isLoading
if(shouldLoadMore) {
val loadMoreEvent = BookListEvent.OnLoadMoreBookInfos
bookListViewModel.onEvent(loadMoreEvent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ import com.tam.tesbooks.domain.model.book_list.BookList
import com.tam.tesbooks.domain.model.listing_modifier.BookListSort
import com.tam.tesbooks.domain.repository.Repository
import com.tam.tesbooks.presentation.navigation.ARG_BOOK_LIST_ID
import com.tam.tesbooks.util.FALLBACK_ERROR_LOAD_BOOK_INFOS
import com.tam.tesbooks.util.FALLBACK_ERROR_LOAD_BOOK_LISTS
import com.tam.tesbooks.util.FALLBACK_ERROR_UPDATE_BOOK_INFO
import com.tam.tesbooks.util.refreshDataObserver
import com.tam.tesbooks.util.*
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
Expand Down Expand Up @@ -65,15 +63,29 @@ class BookListViewModel @Inject constructor(
onError = { error -> errorChannel.send(error ?: FALLBACK_ERROR_LOAD_BOOK_LISTS) }
)

private suspend fun loadBookInfos() {
private suspend fun loadBookInfos(
alreadyLoadedInfos: List<BookInfo> = emptyList(),
shouldReset: Boolean = false
) {
val bookList = state.bookList ?: return
repository
.getBookInfosFromList(bookList, state.listSort)
.getBookInfosFromList(
bookList = bookList,
bookListSort = state.listSort,
alreadyLoadedInfos = alreadyLoadedInfos
)
.collect { result ->
result.onResource(
onSuccess = { bookInfos ->
bookInfos ?: return@onResource
state = state.copy(bookInfos = bookInfos)
val isBookInfosCountAtMax = bookInfos.size >= LIMIT_ROOM_QUERY_DEFAULT
val newBookInfos = if (shouldReset) bookInfos else state.bookInfos + bookInfos
val newPagesLoaded = state.pagesLoaded + 1
state = state.copy(
bookInfos = newBookInfos,
canLoadMore = isBookInfosCountAtMax,
pagesLoaded = newPagesLoaded
)
},
onError = { error -> errorChannel.send(error ?: FALLBACK_ERROR_LOAD_BOOK_INFOS) },
onLoading = { isLoading -> state = state.copy(isLoading = isLoading) }
Expand All @@ -89,7 +101,7 @@ class BookListViewModel @Inject constructor(
updatedBookInfo ?: return@onResource

if(didBookInfoChangeScreenList(updatedBookInfo)) {
loadBookInfos()
reloadBookInfos()
return@onResource
}

Expand All @@ -103,6 +115,34 @@ class BookListViewModel @Inject constructor(
)
}

private fun reloadBookInfos() =
viewModelScope.launch {
val bookList = state.bookList ?: return@launch
val reloadedBookInfos = mutableListOf<BookInfo>()
repeat(state.pagesLoaded) {
repository
.getBookInfosFromList(
bookList = bookList,
bookListSort = state.listSort,
alreadyLoadedInfos = reloadedBookInfos
)
.collect { bookInfosResource ->
bookInfosResource.onResource(
onSuccess = { bookInfos ->
bookInfos ?: return@collect
reloadedBookInfos.addAll(bookInfos)
},
onError = { error -> errorChannel.send(error ?: FALLBACK_ERROR_LOAD_BOOK_INFOS) }
)
}
}
val areAllPagesAtMaxBookInfos = reloadedBookInfos.size >= state.pagesLoaded * LIMIT_ROOM_QUERY_DEFAULT
state = state.copy(
bookInfos = reloadedBookInfos,
canLoadMore = areAllPagesAtMaxBookInfos
)
}

private fun didBookInfoChangeScreenList(newBookInfo: BookInfo): Boolean {
val screenList = state.bookList ?: return false
val newBookInfoList = newBookInfo.savedInBookLists.find { it.id == screenList.id }
Expand All @@ -111,12 +151,19 @@ class BookListViewModel @Inject constructor(

fun onEvent(event: BookListEvent) {
when(event) {
is BookListEvent.OnLoadMoreBookInfos -> {}
is BookListEvent.OnLoadMoreBookInfos -> loadMoreBookInfos()
is BookListEvent.OnChangeBookList -> changeBookList(event.bookInfo, event.bookList)
is BookListEvent.OnSortChange -> changeSort(event.bookListSort)
}
}

private fun loadMoreBookInfos() =
viewModelScope.launch {
state = state.copy(isLoading = true)
delay(TIME_MINIMUM_FOR_LOADING_MORE_ELEMENTS)
loadBookInfos(alreadyLoadedInfos = state.bookInfos)
}

private fun changeBookList(bookInfo: BookInfo, bookList: BookList) =
viewModelScope.launch {
val isBookInList = bookInfo.savedInBookLists.any { it.id == bookList.id }
Expand All @@ -130,7 +177,7 @@ class BookListViewModel @Inject constructor(

private fun changeSort(bookListSort: BookListSort) {
state = state.copy(listSort = bookListSort)
viewModelScope.launch { loadBookInfos() }
viewModelScope.launch { loadBookInfos(shouldReset = true) }
}

}

0 comments on commit 080927b

Please sign in to comment.