Filter by author / series from the detail feature.
This commit is contained in:
parent
8c264042d0
commit
100f8d32bd
8 changed files with 85 additions and 17 deletions
|
|
@ -20,6 +20,8 @@ val LocalDetailBottomSheetState = staticCompositionLocalOf<DetailBottomSheetStat
|
||||||
@Composable
|
@Composable
|
||||||
fun DetailBottomSheet(
|
fun DetailBottomSheet(
|
||||||
bottomDetailState: DetailBottomSheetState = rememberDetailBottomSheetState(),
|
bottomDetailState: DetailBottomSheetState = rememberDetailBottomSheetState(),
|
||||||
|
onAuthor: (String?, Int?) -> Unit,
|
||||||
|
onSeries: (String?, Int?) -> Unit,
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
@ -31,7 +33,11 @@ fun DetailBottomSheet(
|
||||||
scrimColor = ShadowPalette.scrim,
|
scrimColor = ShadowPalette.scrim,
|
||||||
sheetState = bottomDetailState.bottomSheetState,
|
sheetState = bottomDetailState.bottomSheetState,
|
||||||
sheetContent = {
|
sheetContent = {
|
||||||
DetailScreen(bookId = bottomDetailState.bookId)
|
DetailScreen(
|
||||||
|
bookId = bottomDetailState.bookId,
|
||||||
|
onAuthor = onAuthor,
|
||||||
|
onSeries = onSeries,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
content = content,
|
content = content,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,36 @@ class BookSearchViewModel @Inject constructor(
|
||||||
searchSource?.invalidate()
|
searchSource?.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun cleanFilterThen(block: BookSearchViewModel.() -> Unit) {
|
||||||
|
// filter the search
|
||||||
|
_search.value = null
|
||||||
|
// clean the new filter
|
||||||
|
filterByNew = null
|
||||||
|
newFilter.value = newFilter.value.copy(selected = false)
|
||||||
|
// clean the author filter
|
||||||
|
filterByAuthorId = null
|
||||||
|
authorFilter.value = authorFilter.value.copy(
|
||||||
|
selected = false, label = null, closable = false, openable = true
|
||||||
|
)
|
||||||
|
// clean the author filter
|
||||||
|
filterBySeriesId = null
|
||||||
|
seriesFilter.value = seriesFilter.value.copy(
|
||||||
|
selected = false, label = null, closable = false, openable = true
|
||||||
|
)
|
||||||
|
// clean the author filter
|
||||||
|
filterByGenreId = null
|
||||||
|
genreFilter.value = genreFilter.value.copy(
|
||||||
|
selected = false, label = null, closable = false, openable = true
|
||||||
|
)
|
||||||
|
// clean the author filter
|
||||||
|
filterByLanguageId = null
|
||||||
|
languageFilter.value = languageFilter.value.copy(
|
||||||
|
selected = false, label = null, closable = false, openable = true
|
||||||
|
)
|
||||||
|
// call the filter
|
||||||
|
this.block()
|
||||||
|
}
|
||||||
|
|
||||||
fun filterSearch(criteria: String?) {
|
fun filterSearch(criteria: String?) {
|
||||||
_search.value = criteria
|
_search.value = criteria
|
||||||
searchSource?.invalidate()
|
searchSource?.invalidate()
|
||||||
|
|
|
||||||
|
|
@ -103,9 +103,23 @@ fun HomeScreen(
|
||||||
) {
|
) {
|
||||||
DetailBottomSheet(
|
DetailBottomSheet(
|
||||||
bottomDetailState = detailState,
|
bottomDetailState = detailState,
|
||||||
|
onAuthor = { label: String?, id: Int? ->
|
||||||
|
bookViewModel.cleanFilterThen {
|
||||||
|
filterByAuthor(label = label, criteria = id)
|
||||||
|
}
|
||||||
|
scope.launch { detailState.collapse() }
|
||||||
|
},
|
||||||
|
onSeries = { label: String?, id: Int? ->
|
||||||
|
bookViewModel.cleanFilterThen {
|
||||||
|
filterBySeries(label = label, criteria = id)
|
||||||
|
}
|
||||||
|
scope.launch { detailState.collapse() }
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
HomeScreenContent(
|
HomeScreenContent(
|
||||||
modifier = Modifier.systemBarsPadding(),
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.statusBarsPadding(),
|
||||||
avatar = profileViewModel.avatar,
|
avatar = profileViewModel.avatar,
|
||||||
search = bookViewModel.search,
|
search = bookViewModel.search,
|
||||||
onSearch = {
|
onSearch = {
|
||||||
|
|
@ -514,9 +528,9 @@ private fun HomeToolbar(
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
placeholder = {
|
label = {
|
||||||
Text(
|
Text(
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.bibLib.colors.typography.medium,
|
||||||
text = stringResource(id = R.string.search_title),
|
text = stringResource(id = R.string.search_title),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import com.pixelized.biblib.ui.composable.scaffold.LocalDetailBottomSheetState
|
||||||
import com.pixelized.biblib.ui.screen.home.profile.ProfileViewModel
|
import com.pixelized.biblib.ui.screen.home.profile.ProfileViewModel
|
||||||
import com.pixelized.biblib.ui.screen.home.profile.UserUio
|
import com.pixelized.biblib.ui.screen.home.profile.UserUio
|
||||||
import com.pixelized.biblib.ui.theme.color.ShadowPalette
|
import com.pixelized.biblib.ui.theme.color.ShadowPalette
|
||||||
import com.pixelized.biblib.utils.extention.bibLib
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
|
|
@ -52,6 +51,8 @@ sealed class BookDetailUioErrorUio(
|
||||||
fun DetailScreen(
|
fun DetailScreen(
|
||||||
detailViewModel: BookDetailViewModel = hiltViewModel(),
|
detailViewModel: BookDetailViewModel = hiltViewModel(),
|
||||||
profileViewModel: ProfileViewModel = hiltViewModel(),
|
profileViewModel: ProfileViewModel = hiltViewModel(),
|
||||||
|
onAuthor: (String?, Int?) -> Unit,
|
||||||
|
onSeries: (String?, Int?) -> Unit,
|
||||||
bookId: Int? = null,
|
bookId: Int? = null,
|
||||||
) {
|
) {
|
||||||
val detailState = LocalDetailBottomSheetState.current
|
val detailState = LocalDetailBottomSheetState.current
|
||||||
|
|
@ -96,6 +97,10 @@ fun DetailScreen(
|
||||||
.padding(all = 16.dp)
|
.padding(all = 16.dp)
|
||||||
.systemBarsPadding(),
|
.systemBarsPadding(),
|
||||||
book = detail,
|
book = detail,
|
||||||
|
onAuthor = { onAuthor(detail.author, detail.authorId) },
|
||||||
|
onSeries = { onSeries(detail.series, detail.seriesId) },
|
||||||
|
onMobi = { },
|
||||||
|
onEpub = { },
|
||||||
onSend = {
|
onSend = {
|
||||||
send(
|
send(
|
||||||
context = context,
|
context = context,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.pixelized.biblib.ui.screen.home.detail
|
||||||
|
|
||||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
|
@ -26,16 +27,12 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.core.text.toSpannable
|
import androidx.core.text.toSpannable
|
||||||
import com.google.accompanist.placeholder.PlaceholderHighlight
|
|
||||||
import com.google.accompanist.placeholder.material.placeholder
|
|
||||||
import com.google.accompanist.placeholder.shimmer
|
|
||||||
import com.pixelized.biblib.R
|
import com.pixelized.biblib.R
|
||||||
import com.pixelized.biblib.ui.composable.SpannedText
|
import com.pixelized.biblib.ui.composable.SpannedText
|
||||||
import com.pixelized.biblib.ui.composable.animation.AnimatedDelayer
|
import com.pixelized.biblib.ui.composable.animation.AnimatedDelayer
|
||||||
import com.pixelized.biblib.ui.composable.animation.AnimatedOffset
|
import com.pixelized.biblib.ui.composable.animation.AnimatedOffset
|
||||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||||
import com.pixelized.biblib.utils.extention.bibLib
|
import com.pixelized.biblib.utils.extention.bibLib
|
||||||
import com.pixelized.biblib.utils.extention.default
|
|
||||||
import com.pixelized.biblib.utils.extention.placeholder
|
import com.pixelized.biblib.utils.extention.placeholder
|
||||||
import com.skydoves.landscapist.CircularReveal
|
import com.skydoves.landscapist.CircularReveal
|
||||||
import com.skydoves.landscapist.glide.GlideImage
|
import com.skydoves.landscapist.glide.GlideImage
|
||||||
|
|
@ -47,10 +44,12 @@ import java.io.Serializable
|
||||||
data class BookDetailUio(
|
data class BookDetailUio(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val title: String,
|
val title: String,
|
||||||
|
val authorId: Int?,
|
||||||
val author: String,
|
val author: String,
|
||||||
val rating: Float,
|
val rating: Float,
|
||||||
val language: String,
|
val language: String,
|
||||||
val date: String?,
|
val date: String?,
|
||||||
|
val seriesId: Int?,
|
||||||
val series: String?,
|
val series: String?,
|
||||||
val description: String,
|
val description: String,
|
||||||
val cover: String,
|
val cover: String,
|
||||||
|
|
@ -60,8 +59,10 @@ data class BookDetailUio(
|
||||||
fun preview() = BookDetailUio(
|
fun preview() = BookDetailUio(
|
||||||
id = 90,
|
id = 90,
|
||||||
title = "Foundation",
|
title = "Foundation",
|
||||||
|
authorId = null,
|
||||||
author = "Asimov",
|
author = "Asimov",
|
||||||
date = "1951",
|
date = "1951",
|
||||||
|
seriesId = null,
|
||||||
series = "Foundation - 1",
|
series = "Foundation - 1",
|
||||||
description = "En ce début de treizième millénaire, l'Empire n'a jamais été aussi puissant, aussi étendu à travers toute la galaxie. C'est dans sa capitale, Trantor, que l'éminent savant Hari Seldon invente la psychohistoire, une science nouvelle permettant de prédire l'avenir. Grâce à elle, Seldon prévoit l'effondrement de l'Empire d'ici cinq siècles, suivi d'une ère de ténèbres de trente mille ans. Réduire cette période à mille ans est peut-être possible, à condition de mener à terme son projet : la Fondation, chargée de rassembler toutes les connaissances humaines. Une entreprise visionnaire qui rencontre de nombreux et puissants détracteurs...",
|
description = "En ce début de treizième millénaire, l'Empire n'a jamais été aussi puissant, aussi étendu à travers toute la galaxie. C'est dans sa capitale, Trantor, que l'éminent savant Hari Seldon invente la psychohistoire, une science nouvelle permettant de prédire l'avenir. Grâce à elle, Seldon prévoit l'effondrement de l'Empire d'ici cinq siècles, suivi d'une ère de ténèbres de trente mille ans. Réduire cette période à mille ans est peut-être possible, à condition de mener à terme son projet : la Fondation, chargée de rassembler toutes les connaissances humaines. Une entreprise visionnaire qui rencontre de nombreux et puissants détracteurs...",
|
||||||
rating = 4.5f,
|
rating = 4.5f,
|
||||||
|
|
@ -76,9 +77,11 @@ data class BookDetailUio(
|
||||||
fun DetailScreenContent(
|
fun DetailScreenContent(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
book: BookDetailUio,
|
book: BookDetailUio,
|
||||||
onMobi: () -> Unit = default(),
|
onAuthor: () -> Unit,
|
||||||
onEpub: () -> Unit = default(),
|
onSeries: () -> Unit,
|
||||||
onSend: suspend () -> Unit = { },
|
onMobi: () -> Unit,
|
||||||
|
onEpub: () -> Unit,
|
||||||
|
onSend: suspend () -> Unit,
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
|
@ -162,6 +165,7 @@ fun DetailScreenContent(
|
||||||
.padding(bottom = 16.dp),
|
.padding(bottom = 16.dp),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
|
modifier = Modifier.clickable(onClick = onAuthor),
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
style = MaterialTheme.typography.h6,
|
style = MaterialTheme.typography.h6,
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.colors.onSurface,
|
||||||
|
|
@ -201,7 +205,9 @@ fun DetailScreenContent(
|
||||||
modifier = Modifier.padding(bottom = 16.dp),
|
modifier = Modifier.padding(bottom = 16.dp),
|
||||||
) {
|
) {
|
||||||
TitleLabel(
|
TitleLabel(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable(onClick = onSeries),
|
||||||
title = stringResource(id = R.string.detail_series),
|
title = stringResource(id = R.string.detail_series),
|
||||||
label = book.series ?: "-",
|
label = book.series ?: "-",
|
||||||
)
|
)
|
||||||
|
|
@ -262,6 +268,11 @@ private fun DetailScreenContentPreview() {
|
||||||
.verticalScroll(state = rememberScrollState())
|
.verticalScroll(state = rememberScrollState())
|
||||||
.padding(all = 16.dp),
|
.padding(all = 16.dp),
|
||||||
book = BookDetailUio.preview(),
|
book = BookDetailUio.preview(),
|
||||||
|
onAuthor = { },
|
||||||
|
onSeries = { },
|
||||||
|
onMobi = { },
|
||||||
|
onEpub = { },
|
||||||
|
onSend = { },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +110,7 @@ fun DetailScreenSendOption(
|
||||||
.padding(vertical = 8.dp),
|
.padding(vertical = 8.dp),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
style = MaterialTheme.typography.caption,
|
style = MaterialTheme.typography.caption,
|
||||||
color = MaterialTheme.bibLib.colors.typography.dark,
|
color = MaterialTheme.bibLib.colors.typography.emphasis,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
text = stringResource(R.string.detail_send_confirm_help),
|
text = stringResource(R.string.detail_send_confirm_help),
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ data class BibLibColor(
|
||||||
data class Typography(
|
data class Typography(
|
||||||
val light: Color,
|
val light: Color,
|
||||||
val medium: Color,
|
val medium: Color,
|
||||||
val dark: Color,
|
val emphasis: Color,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
|
|
@ -43,7 +43,7 @@ fun bibLibDarkColors(
|
||||||
typography: BibLibColor.Typography = BibLibColor.Typography(
|
typography: BibLibColor.Typography = BibLibColor.Typography(
|
||||||
light = base.onSurface.copy(alpha = 0.67f),
|
light = base.onSurface.copy(alpha = 0.67f),
|
||||||
medium = base.onSurface,
|
medium = base.onSurface,
|
||||||
dark = base.primary,
|
emphasis = base.primary,
|
||||||
),
|
),
|
||||||
placeHolder: BibLibColor.PlaceHolder = BibLibColor.PlaceHolder(
|
placeHolder: BibLibColor.PlaceHolder = BibLibColor.PlaceHolder(
|
||||||
color = BibLibColorPalette.DarkGrey,
|
color = BibLibColorPalette.DarkGrey,
|
||||||
|
|
@ -71,7 +71,7 @@ fun bibLibLightColors(
|
||||||
typography: BibLibColor.Typography = BibLibColor.Typography(
|
typography: BibLibColor.Typography = BibLibColor.Typography(
|
||||||
light = base.onSurface.copy(alpha = 0.67f),
|
light = base.onSurface.copy(alpha = 0.67f),
|
||||||
medium = base.onSurface,
|
medium = base.onSurface,
|
||||||
dark = base.primary,
|
emphasis = base.primary,
|
||||||
),
|
),
|
||||||
placeHolder: BibLibColor.PlaceHolder = BibLibColor.PlaceHolder(
|
placeHolder: BibLibColor.PlaceHolder = BibLibColor.PlaceHolder(
|
||||||
color = BibLibColorPalette.LightGrey,
|
color = BibLibColorPalette.LightGrey,
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,12 @@ fun Book.toDetailUio(
|
||||||
) = BookDetailUio(
|
) = BookDetailUio(
|
||||||
id = id,
|
id = id,
|
||||||
title = title,
|
title = title,
|
||||||
|
authorId = author.firstOrNull()?.id,
|
||||||
author = author.joinToString { it.name },
|
author = author.joinToString { it.name },
|
||||||
rating = rating?.toFloat() ?: 0.0f,
|
rating = rating?.toFloat() ?: 0.0f,
|
||||||
language = language?.displayLanguage?.capitalize() ?: "",
|
language = language?.displayLanguage?.capitalize() ?: "",
|
||||||
date = releaseDate.shortDate(),
|
date = releaseDate.shortDate(),
|
||||||
|
seriesId = series?.id,
|
||||||
series = toLabel(series),
|
series = toLabel(series),
|
||||||
description = synopsis ?: "",
|
description = synopsis ?: "",
|
||||||
cover = "${coverBaseUrl}/$id.jpg",
|
cover = "${coverBaseUrl}/$id.jpg",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue