Simplify the detail page. & small code clean up

This commit is contained in:
Thomas Andres Gomez 2023-03-31 15:37:32 +02:00
parent 100f8d32bd
commit 9c8d05e578
9 changed files with 428 additions and 356 deletions

View file

@ -86,9 +86,6 @@ android {
}
dependencies {
// Kotlin core
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.8.10"
// Android core
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.7.0-alpha02'

View file

@ -4,6 +4,7 @@ import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetState
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
@Composable
fun HandleBottomSheetData(
@ -34,12 +35,22 @@ fun HandleBottomSheetDismiss(
val currentOnDismiss by rememberUpdatedState(
newValue = onDismiss,
)
val haveBeenDismissed by remember(bottomSheetState) {
derivedStateOf {
bottomSheetState.currentValue != ModalBottomSheetValue.Hidden && bottomSheetState.targetValue == ModalBottomSheetValue.Hidden
// Showing a bottom sheet produce a :
// - currentValue == Hidden targetValue == Hidden
// before a :
// - currentValue == Hidden targetValue == Expanded
// We need to keep track of this behavior to avoid closing the bottom sheet immediately.
var skipLaunchEffect by rememberSaveable {
mutableStateOf(true)
}
}
if (haveBeenDismissed) {
LaunchedEffect(bottomSheetState.currentValue) {
if (skipLaunchEffect.not()) {
if (bottomSheetState.currentValue == ModalBottomSheetValue.Hidden && bottomSheetState.targetValue == ModalBottomSheetValue.Hidden) {
currentOnDismiss()
skipLaunchEffect = true
}
} else {
skipLaunchEffect = false
}
}
}

View file

@ -11,7 +11,6 @@ import com.pixelized.biblib.model.book.Book
import com.pixelized.biblib.model.search.FilterType
import com.pixelized.biblib.model.search.SortType
import com.pixelized.biblib.model.search.SortValue
import com.pixelized.biblib.repository.book.BookRepository
import com.pixelized.biblib.repository.book.IBookRepository
import com.pixelized.biblib.repository.search.ISearchRepository
import com.pixelized.biblib.ui.screen.home.common.item.LargeBookThumbnailUio
@ -105,142 +104,102 @@ class BookSearchViewModel @Inject constructor(
}
}
fun sort(sortBy: Map<SortType, SortValue?>) {
this.sortBy = sortBy
fun source(clean: Boolean = false, block: SortAndFilterScope.() -> Unit) {
val scope = if (clean) {
SortAndFilterScope(
sortBy = mapOf(),
isNew = null,
title = null,
author = null,
authorId = null,
series = null,
seriesId = null,
genre = null,
genreId = null,
language = null,
languageId = null,
)
} else {
SortAndFilterScope(
sortBy = sortBy,
isNew = filterByNew,
title = search.value,
author = authorFilter.value.label,
authorId = filterByAuthorId,
series = seriesFilter.value.label,
seriesId = filterBySeriesId,
genre = genreFilter.value.label,
genreId = filterByGenreId,
language = languageFilter.value.label,
languageId = filterByLanguageId,
)
}
scope.block()
// filter the search
if (_search.value != scope.title) {
_search.value = scope.title
}
// clean the new filter
if (filterByNew != scope.isNew) {
filterByNew = scope.isNew
newFilter.value = newFilter.value.copy(
selected = scope.isNew == true,
closable = scope.isNew == true,
)
}
// clean the author filter
if (filterByAuthorId != scope.authorId) {
filterByAuthorId = scope.authorId
authorFilter.value = authorFilter.value.copy(
selected = scope.authorId != null,
label = scope.author,
closable = scope.authorId != null,
openable = scope.authorId == null,
)
}
// clean the author filter
if (filterBySeriesId != scope.seriesId) {
filterBySeriesId = scope.seriesId
seriesFilter.value = seriesFilter.value.copy(
selected = scope.seriesId != null,
label = scope.series,
closable = scope.seriesId != null,
openable = scope.seriesId == null,
)
}
// clean the author filter
if (filterByGenreId != scope.genreId) {
filterByGenreId = scope.genreId
genreFilter.value = genreFilter.value.copy(
selected = scope.genreId != null,
label = scope.genre,
closable = scope.genreId != null,
openable = scope.genreId == null,
)
}
// clean the author filter
if (filterByLanguageId != scope.languageId) {
filterByLanguageId = scope.languageId
languageFilter.value = languageFilter.value.copy(
selected = scope.languageId != null,
label = scope.language,
closable = scope.languageId != null,
openable = scope.languageId == null,
)
}
// apply the sorting
if (sortBy != scope.sortBy) {
sortBy = scope.sortBy
}
// invalidate the source
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 filterByTitle(criteria: String?) {
_search.value = criteria
searchSource?.invalidate()
}
fun filterByNew(criteria: Boolean) {
if (filterByNew != criteria) {
filterByNew = if (criteria) true else null
newFilter.value = newFilter.value.copy(selected = criteria)
searchSource?.invalidate()
}
}
fun filterByAuthor(label: String?, criteria: Int?) {
if (filterByAuthorId != criteria) {
filterByAuthorId = criteria
authorFilter.value = if (criteria != null) {
authorFilter.value.copy(
selected = true,
label = label,
closable = true,
openable = false
)
} else {
authorFilter.value.copy(
selected = false,
label = null,
closable = false,
openable = true
)
}
searchSource?.invalidate()
}
}
fun filterBySeries(label: String?, criteria: Int?) {
if (filterBySeriesId != criteria) {
filterBySeriesId = criteria
seriesFilter.value = if (criteria != null) {
seriesFilter.value.copy(
selected = true,
label = label,
closable = true,
openable = false
)
} else {
seriesFilter.value.copy(
selected = false,
label = null,
closable = false,
openable = true
)
}
searchSource?.invalidate()
}
}
fun filterByGenre(label: String?, criteria: Int?) {
if (filterByGenreId != criteria) {
filterByGenreId = criteria
genreFilter.value = if (criteria != null) {
genreFilter.value.copy(
selected = true,
label = label,
closable = true,
openable = false
)
} else {
genreFilter.value.copy(
selected = false,
label = null,
closable = false,
openable = true
)
}
searchSource?.invalidate()
}
}
fun filterByLanguage(label: String?, criteria: Int?) {
if (filterByLanguageId != criteria) {
filterByLanguageId = criteria
languageFilter.value = if (criteria != null) {
languageFilter.value.copy(
selected = true,
label = label,
closable = true,
openable = false
)
} else {
languageFilter.value.copy(
selected = false,
label = null,
closable = false,
openable = true
)
}
searchSource?.invalidate()
}
}
private fun buildBookSource(): PagingSource<Int, Book> {
return BookSearchSource(
searchRepository = searchRepository,
@ -312,6 +271,79 @@ class BookSearchViewModel @Inject constructor(
)
)
class SortAndFilterScope(
sortBy: Map<SortType, SortValue?>,
isNew: Boolean?,
title: String?,
author: String?,
authorId: Int?,
series: String?,
seriesId: Int?,
genre: String?,
genreId: Int?,
language: String?,
languageId: Int?,
) {
var sortBy: Map<SortType, SortValue?> = sortBy
private set
var isNew: Boolean? = isNew
private set
var title: String? = title
private set
var author: String? = author
private set
var authorId: Int? = authorId
private set
var series: String? = series
private set
var seriesId: Int? = seriesId
private set
var genre: String? = genre
private set
var genreId: Int? = genreId
private set
var language: String? = language
private set
var languageId: Int? = languageId
private set
fun sortBy(type: SortType, value: SortValue?) {
this.sortBy = mapOf(type to value)
}
fun sortBy(sortBy: Map<SortType, SortValue?>) {
this.sortBy = sortBy
}
fun filterByNew(isNew: Boolean) {
this.isNew = if (isNew) true else null
}
fun filterByTitle(title: String?) {
this.title = title
}
fun filterByAuthor(author: String?, authorId: Int?) {
this.author = author
this.authorId = authorId
}
fun filterBySeries(series: String?, seriesId: Int?) {
this.series = series
this.seriesId = seriesId
}
fun filterByGenre(genre: String?, genreId: Int?) {
this.genre = genre
this.genreId = genreId
}
fun filterByLanguage(language: String?, languageId: Int?) {
this.language = language
this.languageId = languageId
}
}
companion object {
private const val SEARCH_PAGE_SIZE = 20
}

View file

@ -41,6 +41,8 @@ import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import com.pixelized.biblib.R
import com.pixelized.biblib.model.search.FilterType
import com.pixelized.biblib.model.search.SortType
import com.pixelized.biblib.model.search.SortValue
import com.pixelized.biblib.ui.LocalSnackHostState
import com.pixelized.biblib.ui.composable.scaffold.*
import com.pixelized.biblib.ui.navigation.LocalScreenNavHostController
@ -104,14 +106,16 @@ fun HomeScreen(
DetailBottomSheet(
bottomDetailState = detailState,
onAuthor = { label: String?, id: Int? ->
bookViewModel.cleanFilterThen {
filterByAuthor(label = label, criteria = id)
bookViewModel.source(clean = true) {
filterByAuthor(author = label, authorId = id)
sortBy(type = SortType.Title, value = SortValue.ASC)
}
scope.launch { detailState.collapse() }
},
onSeries = { label: String?, id: Int? ->
bookViewModel.cleanFilterThen {
filterBySeries(label = label, criteria = id)
bookViewModel.source(clean = true) {
filterBySeries(series = label, seriesId = id)
sortBy(type = SortType.Series, value = SortValue.ASC)
}
scope.launch { detailState.collapse() }
},
@ -123,7 +127,7 @@ fun HomeScreen(
avatar = profileViewModel.avatar,
search = bookViewModel.search,
onSearch = {
bookViewModel.filterSearch(criteria = it)
bookViewModel.filterByTitle(criteria = it)
},
onAvatarTap = {
navigation.navigateToProfile()
@ -149,7 +153,9 @@ fun HomeScreen(
scope.launch {
val result = sortingState.show(sortBy = bookViewModel.sortBy)
if (result is SortBottomSheetResult.ActionPerformed) {
bookViewModel.sort(sortBy = result.sortBy)
bookViewModel.source {
sortBy(sortBy = result.sortBy)
}
}
}
},
@ -182,6 +188,12 @@ fun HomeScreen(
}
}
CollapseKeyboardOnScrollHandler(
largeGridState = largeGridState,
smallListState = smallListState,
microListState = microListState
)
LaunchedEffect(key1 = "HomeScreenLaunchedEffect") {
// update
launch {
@ -212,51 +224,55 @@ private fun rememberOnFilter(
return remember {
{
if (it.id == FilterType.New) {
filterViewModel.filterByNew(criteria = it.selected.not())
filterViewModel.source {
filterByNew(isNew = it.selected.not())
}
} else {
if (it.selected.not()) {
scope.launch {
val result = filterState.show(type = it.id)
if (result is FilterBottomSheetResult.ActionPerformed) {
filterViewModel.source {
when (it.id) {
FilterType.Author -> filterViewModel.filterByAuthor(
label = result.filter.filterLabel,
criteria = result.filter.filterId,
FilterType.Author -> filterByAuthor(
author = result.filter.filterLabel,
authorId = result.filter.filterId,
)
FilterType.Series -> filterViewModel.filterBySeries(
label = result.filter.filterLabel,
criteria = result.filter.filterId,
FilterType.Series -> filterBySeries(
series = result.filter.filterLabel,
seriesId = result.filter.filterId,
)
FilterType.Genre -> filterViewModel.filterByGenre(
label = result.filter.filterLabel,
criteria = result.filter.filterId,
FilterType.Genre -> filterByGenre(
genre = result.filter.filterLabel,
genreId = result.filter.filterId,
)
FilterType.Language -> filterViewModel.filterByLanguage(
label = result.filter.filterLabel,
criteria = result.filter.filterId,
FilterType.Language -> filterByLanguage(
language = result.filter.filterLabel,
languageId = result.filter.filterId,
)
else -> Unit
}
}
}
}
} else {
filterViewModel.source {
when (it.id) {
FilterType.Author -> filterViewModel.filterByAuthor(
label = null,
criteria = null,
FilterType.Author -> filterByAuthor(
author = null,
authorId = null,
)
FilterType.Series -> filterViewModel.filterBySeries(
label = null,
criteria = null,
FilterType.Series -> filterBySeries(
series = null,
seriesId = null,
)
FilterType.Genre -> filterViewModel.filterByGenre(
label = null,
criteria = null,
FilterType.Genre -> filterByGenre(
genre = null,
genreId = null,
)
FilterType.Language -> filterViewModel.filterByLanguage(
label = null,
criteria = null,
FilterType.Language -> filterByLanguage(
language = null,
languageId = null,
)
else -> Unit
}
@ -264,6 +280,7 @@ private fun rememberOnFilter(
}
}
}
}
}
@Composable
@ -569,6 +586,26 @@ private fun HomeToolbar(
}
}
@OptIn(ExperimentalComposeUiApi::class)
@Composable
private fun CollapseKeyboardOnScrollHandler(
largeGridState: LazyGridState,
smallListState: LazyListState,
microListState: LazyListState,
) {
val keyboard = LocalSoftwareKeyboardController.current
val focus = LocalFocusManager.current
if (
largeGridState.isScrollInProgress
|| smallListState.isScrollInProgress
|| microListState.isScrollInProgress
) {
focus.clearFocus()
keyboard?.hide()
}
}
@Composable
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)

View file

@ -91,17 +91,13 @@ fun DetailScreen(
content = {
if (detailState.bottomSheetState.isVisible) {
DetailScreenContent(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.padding(all = 16.dp)
.systemBarsPadding(),
book = detail,
onAuthor = { onAuthor(detail.author, detail.authorId) },
onSeries = { onSeries(detail.series, detail.seriesId) },
onAuthor = { onAuthor(it.name, it.id) },
onSeries = { onSeries(it.name, it.id) },
onMobi = { },
onEpub = { },
onSend = {
scope.launch {
send(
context = context,
profileViewModel = profileViewModel,
@ -110,6 +106,7 @@ fun DetailScreen(
user = profileViewModel.user
)
}
}
)
DetailScreenSendLoader(
loadingVisibility = detailViewModel.sendStatus,

View file

@ -11,19 +11,17 @@ import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Send
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
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.toSpannable
@ -36,7 +34,6 @@ import com.pixelized.biblib.utils.extention.bibLib
import com.pixelized.biblib.utils.extention.placeholder
import com.skydoves.landscapist.CircularReveal
import com.skydoves.landscapist.glide.GlideImage
import kotlinx.coroutines.launch
import java.io.Serializable
@Stable
@ -45,25 +42,40 @@ data class BookDetailUio(
val id: Int,
val title: String,
val authorId: Int?,
val author: String,
val authors: List<AuthorUio>,
val rating: Float,
val language: String,
val date: String?,
val seriesId: Int?,
val series: String?,
val series: SeriesUio?,
val description: String,
val cover: String,
val placeHolder: Boolean,
) : Serializable {
@Stable
@Immutable
data class AuthorUio(
val id: Int,
val name: String,
)
@Stable
@Immutable
data class SeriesUio(
val id: Int,
val name: String,
val label: String,
)
companion object {
fun preview() = BookDetailUio(
id = 90,
title = "Foundation",
authorId = null,
author = "Asimov",
authors = listOf(AuthorUio(id = 0, name = "Asimov")),
date = "1951",
seriesId = null,
series = "Foundation - 1",
series = SeriesUio(id = 0, "Foundation", label = "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...",
rating = 4.5f,
language = "Français",
@ -77,19 +89,26 @@ data class BookDetailUio(
fun DetailScreenContent(
modifier: Modifier = Modifier,
book: BookDetailUio,
onAuthor: () -> Unit,
onSeries: () -> Unit,
onAuthor: (BookDetailUio.AuthorUio) -> Unit,
onSeries: (BookDetailUio.SeriesUio) -> Unit,
onMobi: () -> Unit,
onEpub: () -> Unit,
onSend: suspend () -> Unit,
onSend: () -> Unit,
) {
val scope = rememberCoroutineScope()
val density = LocalDensity.current
val fabHeight = remember { mutableStateOf(0.dp) }
AnimatedDelayer(
targetState = book.id,
) {
Box {
Column(
modifier = modifier,
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
.padding(all = 16.dp)
.systemBarsPadding(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
GlideImage(
modifier = Modifier
@ -102,80 +121,45 @@ fun DetailScreenContent(
imageModel = book.cover,
)
Row(modifier = Modifier.padding(vertical = 16.dp)) {
AnimatedOffset(
modifier = Modifier.weight(1f),
) {
Button(
AnimatedOffset {
Column(
modifier = Modifier.fillMaxWidth(),
onClick = onMobi,
) {
Icon(imageVector = Icons.Default.Download, contentDescription = null)
Spacer(modifier = Modifier.width(4.dp))
Text(text = stringResource(id = R.string.action_mobi))
}
}
Spacer(modifier = Modifier.padding(all = 4.dp))
AnimatedOffset(
modifier = Modifier.weight(1f),
) {
Button(
modifier = Modifier.fillMaxWidth(),
onClick = onEpub,
) {
Icon(imageVector = Icons.Default.Download, contentDescription = null)
Spacer(modifier = Modifier.width(4.dp))
Text(text = stringResource(id = R.string.action_epub))
}
}
Spacer(modifier = Modifier.padding(all = 4.dp))
AnimatedOffset(
modifier = Modifier.weight(1f),
) {
Button(
modifier = Modifier.fillMaxWidth(),
onClick = { scope.launch { onSend() } },
) {
Icon(imageVector = Icons.Default.Send, contentDescription = "")
Spacer(modifier = Modifier.width(4.dp))
Text(text = stringResource(id = R.string.action_send))
}
}
}
AnimatedOffset(
modifier = Modifier
.align(alignment = Alignment.CenterHorizontally)
.padding(bottom = 4.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
style = MaterialTheme.typography.h5,
color = MaterialTheme.colors.onSurface,
text = book.title,
)
book.series?.let { series ->
Text(
modifier = Modifier.clickable(onClick = { onSeries(series) }),
style = MaterialTheme.typography.body1,
color = MaterialTheme.colors.onSurface,
text = series.label,
)
}
}
}
AnimatedOffset(
modifier = Modifier
.align(alignment = Alignment.CenterHorizontally)
.padding(bottom = 16.dp),
AnimatedOffset {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
book.authors.forEach { author ->
Text(
modifier = Modifier.clickable(onClick = onAuthor),
modifier = Modifier.clickable(onClick = { onAuthor(author) }),
fontWeight = FontWeight.Bold,
style = MaterialTheme.typography.h6,
color = MaterialTheme.colors.onSurface,
text = book.author,
text = author.name,
)
}
}
}
Row(
modifier = Modifier.padding(bottom = 8.dp),
) {
Row {
AnimatedOffset(modifier = Modifier.weight(1f)) {
TitleLabel(
modifier = Modifier.fillMaxWidth(),
@ -201,18 +185,6 @@ fun DetailScreenContent(
}
}
AnimatedOffset(
modifier = Modifier.padding(bottom = 16.dp),
) {
TitleLabel(
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = onSeries),
title = stringResource(id = R.string.detail_series),
label = book.series ?: "-",
)
}
AnimatedOffset {
SpannedText(
modifier = Modifier
@ -229,8 +201,32 @@ fun DetailScreenContent(
).toSpannable(),
)
}
Spacer(height = fabHeight)
}
AnimatedOffset(
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(all = 16.dp)
.systemBarsPadding()
.onSizeChanged { fabHeight.value = with(density) { it.height.toDp() } },
) {
Button(
onClick = onSend,
) {
Icon(imageVector = Icons.Default.Send, contentDescription = "")
Spacer(modifier = Modifier.width(4.dp))
Text(text = stringResource(id = R.string.action_send))
}
}
}
}
}
@Composable
private fun Spacer(height: State<Dp>) {
Spacer(modifier = Modifier.height(height = height.value))
}
@Composable
@ -245,13 +241,12 @@ private fun TitleLabel(
) {
Text(
style = MaterialTheme.typography.body2,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colors.onSurface,
text = title,
)
Text(
style = MaterialTheme.typography.body1,
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colors.onSurface,
text = label,
)

View file

@ -24,7 +24,7 @@ fun Book.toMicroThumbnailUio(
cover = "${coverBaseUrl}/$id.jpg",
title = title,
author = author.joinToString { it.name },
series = toLabel(series) ?: "",
series = series?.let { toLabel(it) } ?: "",
isNew = isNew,
)
@ -55,21 +55,26 @@ fun Book.toDetailUio(
id = id,
title = title,
authorId = author.firstOrNull()?.id,
author = author.joinToString { it.name },
authors = author.map { BookDetailUio.AuthorUio(id = it.id, it.name) },
rating = rating?.toFloat() ?: 0.0f,
language = language?.displayLanguage?.capitalize() ?: "",
date = releaseDate.shortDate(),
seriesId = series?.id,
series = toLabel(series),
series = series?.let {
BookDetailUio.SeriesUio(
id = it.id,
name = it.name,
label = toLabel(series)
)
},
description = synopsis ?: "",
cover = "${coverBaseUrl}/$id.jpg",
placeHolder = placeHolder,
)
fun Book.toLabel(series: Series?): String? {
fun Book.toLabel(series: Series): String {
return when {
series?.name != null && seriesIndex != null -> "${series.name} - $seriesIndex"
series?.name != null -> series.name
else -> null
seriesIndex != null -> "${series.name} - $seriesIndex"
else -> series.name
}
}

View file

@ -46,7 +46,6 @@
<string name="detail_language">Langue</string>
<string name="detail_release">Publication</string>
<string name="detail_genre">Genre</string>
<string name="detail_series">Séries</string>
<string name="detail_option_mail">Envoyer cet eBook à :</string>
<string name="detail_option_format">Format de l\'eBook :</string>

View file

@ -61,7 +61,6 @@
<string name="detail_language">Language</string>
<string name="detail_release">Release</string>
<string name="detail_genre">Genre</string>
<string name="detail_series">Series</string>
<string name="detail_option_mail">Send this eBook to:</string>
<string name="detail_option_format">eBook format:</string>