Skip to content

Commit

Permalink
Implement paging in compose and fix SQL query bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
Drumber committed Dec 20, 2024
1 parent aaca2c6 commit ab4f03a
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 52 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ dependencies {

// Paging
implementation(libs.androidx.paging.runtime.ktx)
implementation(libs.androidx.paging.compose)

// Room
implementation(libs.androidx.room.runtime)
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/graphql/GetLibraryEntriesWithNextUnit.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ query GetLibraryEntriesWithNextUnit(
) {
nodes {
id
createdAt
updatedAt
progressedAt
startedAt
finishedAt
notes
reconsumeCount
reconsuming
private
volumesOwned
status
progress
rating
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,18 @@ fun GetLibraryEntriesWithNextUnitQuery.Node.toLibraryEntriesWithModificationAndN

fun GetLibraryEntriesWithNextUnitQuery.Node.toLibraryEntry() = LibraryEntry(
id = id,
updatedAt = null,
startedAt = null,
finishedAt = null,
progressedAt = null,
updatedAt = updatedAt,
startedAt = startedAt,
finishedAt = finishedAt,
progressedAt = progressedAt,
status = status.toLibraryStatus(),
progress = progress,
reconsuming = null,
reconsumeCount = null,
volumesOwned = null,
reconsuming = reconsuming,
reconsumeCount = reconsumeCount,
volumesOwned = volumesOwned,
ratingTwenty = rating,
notes = null,
privateEntry = null,
notes = notes,
privateEntry = private,
reactionSkipped = null,
media = media.toMedia()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import io.github.drumber.kitsune.data.common.library.LibraryEntryKind
import io.github.drumber.kitsune.data.common.library.LibraryFilterOptions
import io.github.drumber.kitsune.data.common.library.LibraryFilterOptions.SortBy
import io.github.drumber.kitsune.data.common.library.LibraryFilterOptions.SortDirection
import io.github.drumber.kitsune.data.mapper.LibraryMapper.toLocalLibraryStatus
import io.github.drumber.kitsune.data.source.local.LocalDatabase
import io.github.drumber.kitsune.data.source.local.library.model.LocalLibraryEntry
import io.github.drumber.kitsune.data.source.local.library.model.LocalLibraryEntryModification
Expand Down Expand Up @@ -66,12 +67,8 @@ class LibraryLocalDataSource(

suspend fun insertLibraryEntryIfUpdatedAtIsNewer(libraryEntry: LocalLibraryEntry): Boolean {
libraryEntry.verifyIsValidLibraryEntry()
if (libraryEntry.updatedAt.isNullOrBlank()) {
insertLibraryEntry(libraryEntry)
return true
}
return database.withTransaction {
val hasNewerEntry = libraryEntryDao.hasLibraryEntryWhereUpdatedAtIsAfter(
val hasNewerEntry = !libraryEntry.updatedAt.isNullOrBlank() && libraryEntryDao.hasLibraryEntryWhereUpdatedAtIsAfter(
libraryEntry.id,
libraryEntry.updatedAt
)
Expand Down Expand Up @@ -157,7 +154,7 @@ class LibraryLocalDataSource(
filter: LibraryFilterOptions
): PagingSource<Int, LocalLibraryEntryWithModificationAndNextMediaUnit> {
return libraryEntryWithModificationAndNextMediaUnitDao.getByFilterAsPagingSource(
filter.status,
filter.status?.map { it.toLocalLibraryStatus() } ?: LocalLibraryStatus.entries,
filter.mediaType,
filter.sortBy ?: SortBy.UPDATED_AT,
filter.sortDirection ?: SortDirection.DESC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import androidx.room.Transaction
import io.github.drumber.kitsune.data.common.library.LibraryFilterOptions
import io.github.drumber.kitsune.data.common.library.LibraryFilterOptions.SortDirection
import io.github.drumber.kitsune.data.common.media.MediaType
import io.github.drumber.kitsune.data.presentation.model.library.LibraryStatus
import io.github.drumber.kitsune.data.source.local.library.dao.LibraryEntryDao.Companion.ORDER_BY_STATUS
import io.github.drumber.kitsune.data.source.local.library.model.LocalLibraryEntryWithModificationAndNextMediaUnit
import io.github.drumber.kitsune.data.source.local.library.model.LocalLibraryStatus
Expand All @@ -19,8 +18,8 @@ interface LibraryEntryWithModificationAndNextMediaUnitDao {
companion object {
private const val BASE_SELECT_WITH_FILTER = """
SELECT * FROM library_entries WHERE
(:status IS NULL OR status IN (:status) AND
(:mediaType IS NULL OR UPPER(media_type) = UPPER(:mediaType)))
status IN (:status) AND
(:mediaType IS NULL OR UPPER(media_type) = UPPER(:mediaType))
ORDER BY
CASE :sortBy
WHEN 'STATUS' THEN status
Expand All @@ -46,21 +45,21 @@ interface LibraryEntryWithModificationAndNextMediaUnitDao {
@Transaction
@Query(SELECT_WITH_FILTER_ASC)
fun getByFilterAsPagingSourceOrderAsc(
status: List<LibraryStatus>?,
status: List<LocalLibraryStatus>,
mediaType: String?,
sortBy: String
): PagingSource<Int, LocalLibraryEntryWithModificationAndNextMediaUnit>

@Transaction
@Query(SELECT_WITH_FILTER_DESC)
fun getByFilterAsPagingSourceOrderDesc(
status: List<LibraryStatus>?,
status: List<LocalLibraryStatus>,
mediaType: String?,
sortBy: String
): PagingSource<Int, LocalLibraryEntryWithModificationAndNextMediaUnit>

fun getByFilterAsPagingSource(
status: List<LibraryStatus>?,
status: List<LocalLibraryStatus>,
mediaType: MediaType?,
sortBy: LibraryFilterOptions.SortBy,
sortDirection: SortDirection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,27 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.paging.PagingData
import androidx.paging.compose.collectAsLazyPagingItems
import io.github.drumber.kitsune.data.presentation.model.library.LibraryEntryWithModification
import io.github.drumber.kitsune.data.presentation.model.library.LibraryEntryWithModificationAndNextUnit
import io.github.drumber.kitsune.ui.library_new.composables.LibraryEntryWithNextUnitItem
import io.github.drumber.kitsune.ui.library_new.composables.toLibraryEntryWithNextUnitData
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow

@Composable
fun LibraryContent(
modifier: Modifier = Modifier,
currentLibraryEntries: List<LibraryEntryWithModificationAndNextUnit> = emptyList(),
currentLibraryEntries: Flow<PagingData<LibraryEntryWithModificationAndNextUnit>> = emptyFlow(),
onItemClick: (LibraryEntryWithModification) -> Unit = {},
) {
Column(
Expand All @@ -47,24 +51,33 @@ fun LibraryContent(
@Composable
private fun CurrentLibraryEntriesShelf(
modifier: Modifier = Modifier,
libraryEntries: List<LibraryEntryWithModificationAndNextUnit> = emptyList(),
libraryEntries: Flow<PagingData<LibraryEntryWithModificationAndNextUnit>> = emptyFlow(),
onItemClick: (LibraryEntryWithModification) -> Unit = {},
onDecrementProgress: (LibraryEntryWithModification) -> Unit = {},
onIncrementProgress: (LibraryEntryWithModification) -> Unit = {},
onRatingClick: (LibraryEntryWithModification) -> Unit = {}
) {
val lazyPagingItems = libraryEntries.collectAsLazyPagingItems()

LazyRow(modifier) {
items(libraryEntries) {
LibraryEntryWithNextUnitItem(
data = it.toLibraryEntryWithNextUnitData(LocalContext.current),
onCardClick = { onItemClick(it.libraryEntryWithModification) },
onDecrementProgress = { onDecrementProgress(it.libraryEntryWithModification) },
onIncrementProgress = { onIncrementProgress(it.libraryEntryWithModification) },
onRatingClick = { onRatingClick(it.libraryEntryWithModification) },
modifier = Modifier
.size(width = 380.dp, height = 220.dp)
.padding(8.dp)
)
items(count = lazyPagingItems.itemCount) { index ->
val item = lazyPagingItems[index]

if (item == null) {
// TODO: show placeholder
Text("Placeholder", Modifier.padding(16.dp))
} else {
LibraryEntryWithNextUnitItem(
data = item.toLibraryEntryWithNextUnitData(LocalContext.current),
onCardClick = { onItemClick(item.libraryEntryWithModification) },
onDecrementProgress = { onDecrementProgress(item.libraryEntryWithModification) },
onIncrementProgress = { onIncrementProgress(item.libraryEntryWithModification) },
onRatingClick = { onRatingClick(item.libraryEntryWithModification) },
modifier = Modifier
.size(width = 380.dp, height = 220.dp)
.padding(8.dp)
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ class NewLibraryFragment : Fragment() {
else -> isSystemInDarkTheme()
}

val currentLibraryEntries by viewModel.currentLibraryEntries.collectAsState()

KitsuneTheme(dynamicColor = useDynamicColorTheme, darkTheme = isDarkModeEnabled) {
Scaffold(
modifier = Modifier.fillMaxSize(),
Expand All @@ -61,7 +59,7 @@ class NewLibraryFragment : Fragment() {
) { innerPadding ->
LibraryContent(
modifier = Modifier.padding(innerPadding),
currentLibraryEntries = currentLibraryEntries,
currentLibraryEntries = viewModel.currentLibraryEntriesPager,
onItemClick = { libraryEntry ->
val mediaDto = libraryEntry.media?.toMediaDto() ?: return@LibraryContent
val action = NewLibraryFragmentDirections.actionNewLibraryFragmentToDetailsFragment(mediaDto)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package io.github.drumber.kitsune.ui.library_new

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.github.drumber.kitsune.data.common.exception.NoDataException
import androidx.paging.cachedIn
import io.github.drumber.kitsune.data.common.library.LibraryFilterOptions
import io.github.drumber.kitsune.data.presentation.model.library.LibraryEntryWithModificationAndNextUnit
import io.github.drumber.kitsune.data.presentation.model.library.LibraryStatus
import io.github.drumber.kitsune.data.repository.library.LibraryRepository
import io.github.drumber.kitsune.domain.auth.IsUserLoggedInUseCase
import io.github.drumber.kitsune.util.logE
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

class NewLibraryViewModel(
isUserLoggedIn: IsUserLoggedInUseCase,
Expand All @@ -20,17 +20,25 @@ class NewLibraryViewModel(
MutableStateFlow(emptyList<LibraryEntryWithModificationAndNextUnit>())
val currentLibraryEntries = _currentLibraryEntries.asStateFlow()

val currentLibraryEntriesPager = libraryRepository.libraryEntriesWithNextMediaUnitPager(
pageSize = 20,
filter = LibraryFilterOptions(
status = listOf(LibraryStatus.Current),
sortBy = LibraryFilterOptions.SortBy.UPDATED_AT,
)
).cachedIn(viewModelScope)

init {
if (isUserLoggedIn()) {
viewModelScope.launch {
try {
val libraryEntries = libraryRepository.getCurrentLibraryEntriesWithNextUnit()
?: throw NoDataException()
_currentLibraryEntries.value = libraryEntries
} catch (e: Exception) {
logE("Failed to get library entries", e)
}
}
}
// if (isUserLoggedIn()) {
// viewModelScope.launch {
// try {
// val libraryEntries = libraryRepository.getCurrentLibraryEntriesWithNextUnit()
// ?: throw NoDataException()
// _currentLibraryEntries.value = libraryEntries
// } catch (e: Exception) {
// logE("Failed to get library entries", e)
// }
// }
// }
}
}
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-view
androidx-navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "androidxNavigation" }
androidx-navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "androidxNavigation" }
androidx-paging-runtime-ktx = { module = "androidx.paging:paging-runtime-ktx", version.ref = "androidxPaging" }
androidx-paging-compose = { module = "androidx.paging:paging-compose", version.ref = "androidxPaging" }
androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "preferenceKtx" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "androidxRoom" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "androidxRoom" }
Expand Down

0 comments on commit ab4f03a

Please sign in to comment.