diff --git a/app/src/main/java/com/pixelized/biblib/model/search/SearchType.kt b/app/src/main/java/com/pixelized/biblib/model/search/SearchType.kt new file mode 100644 index 0000000..1dee9d9 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/model/search/SearchType.kt @@ -0,0 +1,13 @@ +package com.pixelized.biblib.model.search + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable + +@Stable +@Immutable +enum class SearchType { + Author, + Series, + Genre, + Language; +} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/model/search/SortType.kt b/app/src/main/java/com/pixelized/biblib/model/search/SortType.kt new file mode 100644 index 0000000..153fb90 --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/model/search/SortType.kt @@ -0,0 +1,14 @@ +package com.pixelized.biblib.model.search + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable + +@Stable +@Immutable +enum class SortType { + Book, + Author, + Series, + Genre, + Language; +} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/repository/search/ISearchRepository.kt b/app/src/main/java/com/pixelized/biblib/repository/search/ISearchRepository.kt index 2ddc6f6..d044638 100644 --- a/app/src/main/java/com/pixelized/biblib/repository/search/ISearchRepository.kt +++ b/app/src/main/java/com/pixelized/biblib/repository/search/ISearchRepository.kt @@ -1,6 +1,7 @@ package com.pixelized.biblib.repository.search import com.pixelized.biblib.model.book.* +import com.pixelized.biblib.model.search.SortType interface ISearchRepository { diff --git a/app/src/main/java/com/pixelized/biblib/repository/search/SearchRepository.kt b/app/src/main/java/com/pixelized/biblib/repository/search/SearchRepository.kt index 9da9726..8be1c55 100644 --- a/app/src/main/java/com/pixelized/biblib/repository/search/SearchRepository.kt +++ b/app/src/main/java/com/pixelized/biblib/repository/search/SearchRepository.kt @@ -7,6 +7,7 @@ import com.pixelized.biblib.database.crossref.BookGenreCrossRef import com.pixelized.biblib.database.data.* import com.pixelized.biblib.database.relation.BookRelation import com.pixelized.biblib.model.book.* +import com.pixelized.biblib.model.search.SortType import javax.inject.Inject class SearchRepository @Inject constructor( @@ -42,6 +43,7 @@ class SearchRepository @Inject constructor( query += args.where(argument = languageId) { BookDbo.run { "$TABLE.$LANGUAGE_ID LIKE ?" } } + query += BookDbo.run { " ORDER BY $TABLE.$SORT" } // Limit and Offset the query. query += " LIMIT $limit OFFSET $offset;" // compute the query @@ -57,6 +59,7 @@ class SearchRepository @Inject constructor( val query = AuthorDbo.run { "SELECT $TABLE.* FROM $TABLE" + args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } + + " ORDER BY $TABLE.$SORT" + " LIMIT $limit OFFSET $offset;" } // compute the query @@ -72,6 +75,7 @@ class SearchRepository @Inject constructor( val query = GenreDbo.run { "SELECT $TABLE.* FROM $TABLE" + args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } + + " ORDER BY $TABLE.$NAME" + " LIMIT $limit OFFSET $offset;" } // compute the query @@ -87,6 +91,7 @@ class SearchRepository @Inject constructor( val query = SeriesDbo.run { "SELECT $TABLE.* FROM $TABLE" + args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } + + " ORDER BY $TABLE.$SORT" + " LIMIT $limit OFFSET $offset;" } // compute the query @@ -102,6 +107,7 @@ class SearchRepository @Inject constructor( val query = LanguageDbo.run { "SELECT $TABLE.* FROM $TABLE" + args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } + + " ORDER BY $TABLE.$NAME" + " LIMIT $limit OFFSET $offset;" } // compute the query diff --git a/app/src/main/java/com/pixelized/biblib/ui/scaffold/CategorySearchBottomSheet.kt b/app/src/main/java/com/pixelized/biblib/ui/scaffold/SearchOptionBottomSheet.kt similarity index 71% rename from app/src/main/java/com/pixelized/biblib/ui/scaffold/CategorySearchBottomSheet.kt rename to app/src/main/java/com/pixelized/biblib/ui/scaffold/SearchOptionBottomSheet.kt index a808fc7..c960725 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/scaffold/CategorySearchBottomSheet.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/scaffold/SearchOptionBottomSheet.kt @@ -12,7 +12,8 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.hilt.navigation.compose.hiltViewModel -import com.pixelized.biblib.ui.screen.home.page.search.FilterSearchPage +import com.pixelized.biblib.model.search.SearchType +import com.pixelized.biblib.ui.screen.home.page.search.bottom.FilterSearchPage import com.pixelized.biblib.ui.screen.home.page.search.viewModel.BookSearchViewModel import com.pixelized.biblib.ui.theme.color.ShadowPalette import kotlinx.coroutines.launch @@ -20,14 +21,14 @@ import kotlinx.coroutines.launch val LocalBookSearchViewModel = staticCompositionLocalOf { error("SearchViewModel is not ready yet") } -val LocalCategorySearchBottomSheetState = staticCompositionLocalOf { - error("BottomSearchState is not ready yet") +val LocalFilterSearchBottomSheetState = staticCompositionLocalOf { + error("FilterSearchBottomSheetState is not ready yet") } @OptIn(ExperimentalMaterialApi::class) @Composable -fun CategorySearchBottomSheet( - state: SearchBottomSheetState = rememberSearchBottomSheetState(), +fun SearchOptionBottomSheet( + filterState: FilterSearchBottomSheetState = rememberSearchBottomSheetState(), bookSearchViewModel: BookSearchViewModel = hiltViewModel(), content: @Composable () -> Unit, ) { @@ -35,23 +36,23 @@ fun CategorySearchBottomSheet( CompositionLocalProvider( LocalBookSearchViewModel provides bookSearchViewModel, - LocalCategorySearchBottomSheetState provides state, + LocalFilterSearchBottomSheetState provides filterState, ) { ModalBottomSheetLayout( modifier = Modifier.statusBarsPadding(), scrimColor = ShadowPalette.scrim, - sheetState = state.bottomSheetState, + sheetState = filterState.bottomSheetState, sheetContent = { FilterSearchPage( - focusRequester = state.focusRequester, + focusRequester = filterState.focusRequester, ) }, content = content, ) - BackHandler(state.bottomSheetState.isVisible) { + BackHandler(filterState.bottomSheetState.isVisible) { scope.launch { - state.collapse() + filterState.collapse() } } } @@ -65,12 +66,12 @@ fun rememberSearchBottomSheetState( initialValue = Hidden, skipHalfExpanded = true, ), -): SearchBottomSheetState { +): FilterSearchBottomSheetState { val filter = rememberSaveable(bottomSheetState) { - mutableStateOf(null) + mutableStateOf(null) } return remember(bottomSheetState) { - SearchBottomSheetState( + FilterSearchBottomSheetState( bottomSheetState = bottomSheetState, focusRequester = focusRequester, filter = filter, @@ -80,15 +81,15 @@ fun rememberSearchBottomSheetState( @OptIn(ExperimentalMaterialApi::class) @Stable -class SearchBottomSheetState constructor( +class FilterSearchBottomSheetState constructor( val bottomSheetState: ModalBottomSheetState, val focusRequester: FocusRequester, - filter: MutableState, + filter: MutableState, ) { - var filter: SearchFilter? by filter + var filter: SearchType? by filter private set - suspend fun expandSearch(filter: SearchFilter?) { + suspend fun expandSearch(filter: SearchType?) { this.filter = filter bottomSheetState.show() focusRequester.requestFocus() @@ -97,13 +98,4 @@ class SearchBottomSheetState constructor( suspend fun collapse() { bottomSheetState.hide() } -} - -@Stable -@Immutable -enum class SearchFilter { - Author, - Series, - Genre, - Language; } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/HomeScreen.kt index f77e593..1460584 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/HomeScreen.kt @@ -57,7 +57,7 @@ fun HomeScreen( val focusRequester: FocusRequester = remember { FocusRequester() } DetailBottomSheet { - CategorySearchBottomSheet { + SearchOptionBottomSheet { SearchScaffold( modifier = Modifier.statusBarsPadding(), state = searchScaffoldState, @@ -138,7 +138,7 @@ fun HomeScreen( }, ) - val bottomSearchState = LocalCategorySearchBottomSheetState.current + val bottomSearchState = LocalFilterSearchBottomSheetState.current val bottomDetailState = LocalDetailBottomSheetState.current BackHandler( enabled = searchScaffoldState.isExpended || bottomSearchState.bottomSheetState.isVisible || bottomDetailState.bottomSheetState.isVisible diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchPage.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchPage.kt index de6d2ad..ae1b5ab 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchPage.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchPage.kt @@ -2,19 +2,17 @@ package com.pixelized.biblib.ui.screen.home.page.search import android.content.res.Configuration.UI_MODE_NIGHT_NO import android.content.res.Configuration.UI_MODE_NIGHT_YES -import androidx.compose.animation.core.Spring -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.spring -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material.* +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.stringResource @@ -23,33 +21,31 @@ import androidx.paging.PagingData import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.items import com.pixelized.biblib.R -import com.pixelized.biblib.ui.scaffold.LocalCategorySearchBottomSheetState -import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState +import com.pixelized.biblib.model.search.SearchType import com.pixelized.biblib.ui.scaffold.LocalBookSearchViewModel -import com.pixelized.biblib.ui.scaffold.SearchFilter +import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState +import com.pixelized.biblib.ui.scaffold.LocalFilterSearchBottomSheetState import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnail import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnailUio import com.pixelized.biblib.ui.screen.home.page.search.item.SearchFilterList import com.pixelized.biblib.ui.screen.home.page.search.item.SearchFilterUio -import com.pixelized.biblib.ui.screen.home.page.search.item.searchFilterPreviewItems import com.pixelized.biblib.ui.screen.home.page.search.viewModel.BookSearchViewModel import com.pixelized.biblib.ui.theme.BibLibTheme import com.pixelized.biblib.utils.extention.bibLib import com.pixelized.biblib.utils.extention.default -import com.pixelized.biblib.utils.extention.isLoading import com.pixelized.biblib.utils.extention.navigationBarsHeight import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.launch -@OptIn(ExperimentalComposeUiApi::class) +@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterialApi::class) @Composable fun SearchPage( bookSearchViewModel: BookSearchViewModel = LocalBookSearchViewModel.current, ) { val keyboard = LocalSoftwareKeyboardController.current val detail = LocalDetailBottomSheetState.current - val search = LocalCategorySearchBottomSheetState.current + val filter = LocalFilterSearchBottomSheetState.current val focus = LocalFocusManager.current val scope = rememberCoroutineScope() @@ -58,8 +54,17 @@ fun SearchPage( search = bookSearchViewModel.paging, filters = filters(bookSearchViewModel), onFilter = { - scope.launch { - search.expandSearch(it.id) + if (it.value == null) { + scope.launch { + filter.expandSearch(it.id) + } + } else { + when (it.id) { + SearchType.Author -> bookSearchViewModel.filterAuthor(null) + SearchType.Series -> bookSearchViewModel.filterSeries(null) + SearchType.Genre -> bookSearchViewModel.filterGenre(null) + SearchType.Language -> bookSearchViewModel.filterLanguage(null) + } } }, onDetail = { @@ -75,10 +80,10 @@ fun SearchPage( @Composable private fun SearchPageContent( modifier: Modifier = Modifier, - search: Flow>, + search: Flow> = emptyFlow(), filters: List = emptyList(), - onFilter: (filter: SearchFilterUio) -> Unit, - onDetail: (item: MicroBookThumbnailUio) -> Unit, + onFilter: (filter: SearchFilterUio) -> Unit = default(), + onDetail: (item: MicroBookThumbnailUio) -> Unit = default(), ) { val items = search.collectAsLazyPagingItems() @@ -105,29 +110,6 @@ private fun SearchPageContent( ) } } - - SearchLoader( - modifier = Modifier - .fillMaxWidth() - .height(MaterialTheme.bibLib.dimen.dp2), - isLoading = { items.isLoading }, - ) -} - -@Composable -private fun SearchLoader( - modifier: Modifier = Modifier, - isLoading: () -> Boolean, -) { - val alpha by animateFloatAsState( - animationSpec = spring(stiffness = Spring.StiffnessLow), - targetValue = if (isLoading()) 1f else 0f - ) - LinearProgressIndicator( - modifier = modifier.alpha(alpha), - color = MaterialTheme.colors.primary, - backgroundColor = Color.Transparent, - ) } @Composable @@ -135,22 +117,22 @@ private fun filters( bookSearchViewModel: BookSearchViewModel, ) = listOf( SearchFilterUio( - id = SearchFilter.Author, + id = SearchType.Author, label = stringResource(id = R.string.search_filter_author), value = bookSearchViewModel.author?.filter, ), SearchFilterUio( - id = SearchFilter.Genre, + id = SearchType.Genre, label = stringResource(id = R.string.search_filter_genre), value = bookSearchViewModel.genre?.filter, ), SearchFilterUio( - id = SearchFilter.Series, - label = stringResource(id = R.string.search_filter_serie), + id = SearchType.Series, + label = stringResource(id = R.string.search_filter_series), value = bookSearchViewModel.series?.filter, ), SearchFilterUio( - id = SearchFilter.Language, + id = SearchType.Language, label = stringResource(id = R.string.search_filter_language), value = bookSearchViewModel.language?.filter, ), @@ -163,10 +145,6 @@ private fun SearchPageContentPreview() { BibLibTheme { SearchPageContent( modifier = Modifier.fillMaxWidth(), - search = emptyFlow(), - filters = searchFilterPreviewItems(), - onFilter = default(), - onDetail = default(), ) } } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/FilterSearchPage.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/bottom/FilterSearchPage.kt similarity index 77% rename from app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/FilterSearchPage.kt rename to app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/bottom/FilterSearchPage.kt index 07e0052..0da5481 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/FilterSearchPage.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/bottom/FilterSearchPage.kt @@ -1,4 +1,4 @@ -package com.pixelized.biblib.ui.screen.home.page.search +package com.pixelized.biblib.ui.screen.home.page.search.bottom import android.content.res.Configuration.UI_MODE_NIGHT_NO import android.content.res.Configuration.UI_MODE_NIGHT_YES @@ -21,9 +21,9 @@ import androidx.paging.PagingData import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.items import com.pixelized.biblib.R +import com.pixelized.biblib.model.search.SearchType import com.pixelized.biblib.ui.scaffold.LocalBookSearchViewModel -import com.pixelized.biblib.ui.scaffold.LocalCategorySearchBottomSheetState -import com.pixelized.biblib.ui.scaffold.SearchFilter +import com.pixelized.biblib.ui.scaffold.LocalFilterSearchBottomSheetState import com.pixelized.biblib.ui.screen.home.page.search.viewModel.* import com.pixelized.biblib.ui.theme.BibLibTheme import com.pixelized.biblib.utils.extention.bibLib @@ -48,16 +48,16 @@ fun FilterSearchPage( focusRequester: FocusRequester = FocusRequester(), ) { val bookSearchViewModel = LocalBookSearchViewModel.current - val bottomSearchState = LocalCategorySearchBottomSheetState.current + val bottomSearchState = LocalFilterSearchBottomSheetState.current val scope = rememberCoroutineScope() val filter = bottomSearchState.filter val viewModel: IFilterViewModel? = remember(filter) { when (filter) { - SearchFilter.Author -> authorFilterViewModel - SearchFilter.Series -> seriesFilterViewModel - SearchFilter.Genre -> genreViewModel - SearchFilter.Language -> languageViewModel + SearchType.Author -> authorFilterViewModel + SearchType.Series -> seriesFilterViewModel + SearchType.Genre -> genreViewModel + SearchType.Language -> languageViewModel else -> null } } @@ -72,10 +72,10 @@ fun FilterSearchPage( }, onClose = { when (filter) { - SearchFilter.Author -> bookSearchViewModel.filterAuthor(null) - SearchFilter.Series -> bookSearchViewModel.filterSeries(null) - SearchFilter.Genre -> bookSearchViewModel.filterGenre(null) - SearchFilter.Language -> bookSearchViewModel.filterLanguage(null) + SearchType.Author -> bookSearchViewModel.filterAuthor(null) + SearchType.Series -> bookSearchViewModel.filterSeries(null) + SearchType.Genre -> bookSearchViewModel.filterGenre(null) + SearchType.Language -> bookSearchViewModel.filterLanguage(null) else -> Unit } scope.launch { @@ -84,10 +84,10 @@ fun FilterSearchPage( }, onFilter = { when (filter) { - SearchFilter.Author -> bookSearchViewModel.filterAuthor(it) - SearchFilter.Series -> bookSearchViewModel.filterSeries(it) - SearchFilter.Genre -> bookSearchViewModel.filterGenre(it) - SearchFilter.Language -> bookSearchViewModel.filterLanguage(it) + SearchType.Author -> bookSearchViewModel.filterAuthor(it) + SearchType.Series -> bookSearchViewModel.filterSeries(it) + SearchType.Genre -> bookSearchViewModel.filterGenre(it) + SearchType.Language -> bookSearchViewModel.filterLanguage(it) else -> Unit } scope.launch { @@ -100,7 +100,7 @@ fun FilterSearchPage( @Composable fun CategorySearchPageContent( focusRequester: FocusRequester = FocusRequester(), - filter: SearchFilter?, + filter: SearchType?, search: () -> String?, paging: () -> Flow> = { emptyFlow() }, onSearchUpdate: (String) -> Unit = default(), @@ -121,10 +121,10 @@ fun CategorySearchPageContent( style = MaterialTheme.typography.h6, color = MaterialTheme.colors.onSurface, text = when (filter) { - SearchFilter.Author -> stringResource(id = R.string.search_filter_author) - SearchFilter.Genre -> stringResource(id = R.string.search_filter_genre) - SearchFilter.Series -> stringResource(id = R.string.search_filter_serie) - SearchFilter.Language -> stringResource(id = R.string.search_filter_language) + SearchType.Author -> stringResource(id = R.string.search_filter_author) + SearchType.Genre -> stringResource(id = R.string.search_filter_genre) + SearchType.Series -> stringResource(id = R.string.search_filter_series) + SearchType.Language -> stringResource(id = R.string.search_filter_language) else -> "" }, ) @@ -181,7 +181,7 @@ fun CategorySearchPageContent( private fun CategorySearchPageContentPreview() { BibLibTheme { CategorySearchPageContent( - filter = SearchFilter.Author, + filter = SearchType.Author, search = { "Asimov" }, ) } diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/item/SearchFilter.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/item/SearchFilter.kt index 2f0588a..51d0eac 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/item/SearchFilter.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/item/SearchFilter.kt @@ -1,22 +1,23 @@ package com.pixelized.biblib.ui.screen.home.page.search.item import android.content.res.Configuration +import androidx.compose.animation.* import androidx.compose.foundation.horizontalScroll -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.material.* import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowDropDown -import androidx.compose.runtime.* +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.KeyboardArrowDown +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import com.pixelized.biblib.R -import com.pixelized.biblib.ui.scaffold.SearchFilter +import com.pixelized.biblib.model.search.SearchType import com.pixelized.biblib.ui.theme.BibLibTheme import com.pixelized.biblib.utils.extention.bibLib import com.pixelized.biblib.utils.extention.default @@ -24,7 +25,7 @@ import com.pixelized.biblib.utils.extention.default @Stable @Immutable data class SearchFilterUio( - val id: SearchFilter, + val id: SearchType, val label: String, val value: String? = null, ) @@ -51,7 +52,7 @@ fun SearchFilterList( } } -@OptIn(ExperimentalMaterialApi::class) +@OptIn(ExperimentalMaterialApi::class, ExperimentalAnimationApi::class) @Composable private fun SearchFilter( modifier: Modifier = Modifier, @@ -59,34 +60,34 @@ private fun SearchFilter( onClick: () -> Unit = default(), ) { FilterChip( - modifier = modifier, + modifier = modifier.animateContentSize(), selected = uio.value != null, onClick = onClick, - ) { - Text( - color = MaterialTheme.bibLib.colors.typography.medium, - style = MaterialTheme.typography.caption, - text = uio.label, - ) - - uio.value?.let { - Text( - color = MaterialTheme.bibLib.colors.typography.medium, - style = MaterialTheme.typography.caption, - text = ": " + trailingIcon = { + Icon( + modifier = Modifier.size(MaterialTheme.bibLib.dimen.dp12), + imageVector = when (uio.value) { + null -> Icons.Default.KeyboardArrowDown + else -> Icons.Default.Close + }, + tint = MaterialTheme.bibLib.colors.typography.medium, + contentDescription = null ) + }, + ) { + AnimatedContent( + targetState = uio.value, + transitionSpec = { fadeIn() with fadeOut() }, + ) { Text( color = MaterialTheme.bibLib.colors.typography.medium, style = MaterialTheme.typography.caption, - text = it + text = when { + it != null -> stringResource(id = R.string.search_filter_param, uio.label, it) + else -> uio.label + } ) } - - Icon( - imageVector = Icons.Default.ArrowDropDown, - tint = MaterialTheme.bibLib.colors.typography.medium, - contentDescription = null - ) } } @@ -104,20 +105,20 @@ private fun SearchFilterPreview() { @Composable fun searchFilterPreviewItems() = listOf( SearchFilterUio( - id = SearchFilter.Author, + id = SearchType.Author, label = stringResource(id = R.string.search_filter_author), value = "Asimov", ), SearchFilterUio( - id = SearchFilter.Genre, + id = SearchType.Genre, label = stringResource(id = R.string.search_filter_genre), ), SearchFilterUio( - id = SearchFilter.Series, - label = stringResource(id = R.string.search_filter_serie), + id = SearchType.Series, + label = stringResource(id = R.string.search_filter_series), ), SearchFilterUio( - id = SearchFilter.Language, + id = SearchType.Language, label = stringResource(id = R.string.search_filter_language), ), ) \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/item/SearchHistory.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/item/SearchHistory.kt deleted file mode 100644 index 9725c8b..0000000 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/item/SearchHistory.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.pixelized.biblib.ui.screen.home.page.search.item - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -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.History -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.Stable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import com.pixelized.biblib.ui.theme.BibLibTheme -import com.pixelized.biblib.utils.extention.bibLib - -@Stable -@Immutable -data class SearchHistoryUio( - val label: String, -) - -@Composable -fun SearchHistory( - uio: SearchHistoryUio, -) { - SearchHistoryContent( - modifier = Modifier.fillMaxWidth(), - label = uio.label - ) -} - -@Composable -private fun SearchHistoryContent( - modifier: Modifier = Modifier, - label: String, -) { - Row( - modifier = modifier.padding(all = MaterialTheme.bibLib.dimen.dp16) - ) { - Icon( - modifier = Modifier.padding(end = MaterialTheme.bibLib.dimen.dp8), - tint = MaterialTheme.colors.onSurface, - imageVector = Icons.Default.History, - contentDescription = null, - ) - Text( - color = MaterialTheme.bibLib.colors.typography.medium, - style = MaterialTheme.typography.body1, - text = label, - ) - } -} - -@Composable -@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO) -@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES) -private fun SearchHistoryContentPreview() { - BibLibTheme { - SearchHistory( - uio = SearchHistoryUio("Asimov") - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/AuthorFilterViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/AuthorFilterViewModel.kt index 339f23a..1124698 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/AuthorFilterViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/AuthorFilterViewModel.kt @@ -8,7 +8,8 @@ import androidx.lifecycle.viewModelScope import androidx.paging.* import com.pixelized.biblib.model.book.Author import com.pixelized.biblib.repository.search.ISearchRepository -import com.pixelized.biblib.ui.screen.home.page.search.FilterUio +import com.pixelized.biblib.ui.screen.home.page.search.bottom.FilterUio + import com.pixelized.biblib.ui.screen.home.page.search.source.AuthorSearchSource import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/BookSearchViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/BookSearchViewModel.kt index 4f7c7a4..2030bfb 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/BookSearchViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/BookSearchViewModel.kt @@ -9,7 +9,7 @@ import androidx.paging.* import com.pixelized.biblib.model.book.Book import com.pixelized.biblib.repository.search.ISearchRepository import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnailUio -import com.pixelized.biblib.ui.screen.home.page.search.FilterUio +import com.pixelized.biblib.ui.screen.home.page.search.bottom.FilterUio import com.pixelized.biblib.ui.screen.home.page.search.source.BookSearchSource import com.pixelized.biblib.utils.extention.toMicroThumbnailUio import dagger.hilt.android.lifecycle.HiltViewModel @@ -65,10 +65,12 @@ class BookSearchViewModel @Inject constructor( series = criteria searchSource?.invalidate() } + fun filterGenre(criteria: FilterUio?) { genre = criteria searchSource?.invalidate() } + fun filterLanguage(criteria: FilterUio?) { language = criteria searchSource?.invalidate() diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/GenreFilterViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/GenreFilterViewModel.kt index 8d6adeb..afa98b0 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/GenreFilterViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/GenreFilterViewModel.kt @@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope import androidx.paging.* import com.pixelized.biblib.model.book.Genre import com.pixelized.biblib.repository.search.ISearchRepository -import com.pixelized.biblib.ui.screen.home.page.search.FilterUio +import com.pixelized.biblib.ui.screen.home.page.search.bottom.FilterUio import com.pixelized.biblib.ui.screen.home.page.search.source.GenreSearchSource import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/IFilterViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/IFilterViewModel.kt index f9ef0d6..ba25441 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/IFilterViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/IFilterViewModel.kt @@ -1,7 +1,7 @@ package com.pixelized.biblib.ui.screen.home.page.search.viewModel import androidx.paging.PagingData -import com.pixelized.biblib.ui.screen.home.page.search.FilterUio +import com.pixelized.biblib.ui.screen.home.page.search.bottom.FilterUio import kotlinx.coroutines.flow.Flow interface IFilterViewModel { diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/LanguageFilterViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/LanguageFilterViewModel.kt index 930dd31..bbaace8 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/LanguageFilterViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/LanguageFilterViewModel.kt @@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope import androidx.paging.* import com.pixelized.biblib.model.book.Language import com.pixelized.biblib.repository.search.ISearchRepository -import com.pixelized.biblib.ui.screen.home.page.search.FilterUio +import com.pixelized.biblib.ui.screen.home.page.search.bottom.FilterUio import com.pixelized.biblib.ui.screen.home.page.search.source.LanguageSearchSource import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/SeriesFilterViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/SeriesFilterViewModel.kt index bdd6166..00a09a9 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/SeriesFilterViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/SeriesFilterViewModel.kt @@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope import androidx.paging.* import com.pixelized.biblib.model.book.Series import com.pixelized.biblib.repository.search.ISearchRepository -import com.pixelized.biblib.ui.screen.home.page.search.FilterUio +import com.pixelized.biblib.ui.screen.home.page.search.bottom.FilterUio import com.pixelized.biblib.ui.screen.home.page.search.source.SeriesSearchSource import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt b/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt index ecb2e63..606b614 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt @@ -13,6 +13,7 @@ data class BibLibDimen( val dp2: Dp = 2.dp, val dp4: Dp = 4.dp, val dp8: Dp = 8.dp, + val dp12: Dp = 12.dp, val dp16: Dp = 16.dp, val dp32: Dp = 32.dp, val dp48: Dp = 48.dp, @@ -33,10 +34,11 @@ data class BibLibDimen( @Stable @Immutable data class BookThumbnail( + val ratio: Float = 1.6f, val padding: Dp = 16.dp, val arrangement: Dp = 16.dp, - val cover: DpSize = DpSize(width = 72.dp, height = 115.dp), // ratio 1.6 - val micro: DpSize = DpSize(width = 40.dp, height = 64.dp), // ratio 1.6 + val cover: DpSize = 72.dp.let { DpSize(width = it, height = it * ratio) }, + val micro: DpSize = 48.dp.let { DpSize(width = it, height = it * ratio) }, ) @Stable diff --git a/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt b/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt index d7da39a..1cb3ef1 100644 --- a/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt +++ b/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt @@ -2,6 +2,7 @@ package com.pixelized.biblib.utils.extention import androidx.annotation.StringDef import com.pixelized.biblib.model.book.Book +import com.pixelized.biblib.model.book.Series import com.pixelized.biblib.network.client.IBibLibClient import com.pixelized.biblib.ui.screen.home.common.item.LargeBookThumbnailUio import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnailUio @@ -20,10 +21,10 @@ fun Book.toMicroThumbnailUio( @CoverUrl coverBaseUrl: String = IBibLibClient.THUMBNAIL_URL ) = MicroBookThumbnailUio( id = id, + cover = "${coverBaseUrl}/$id.jpg", title = title, author = author.joinToString { it.name }, isNew = isNew, - cover = "${coverBaseUrl}/$id.jpg", ) fun Book.toSmallThumbnailUio( @@ -58,7 +59,15 @@ fun Book.toDetailUio( rating = rating?.toFloat() ?: 0.0f, language = language?.displayLanguage?.capitalize() ?: "", date = releaseDate.shortDate(), - series = series?.name, + series = series.toLabel(), description = synopsis ?: "", cover = "${coverBaseUrl}/$id.jpg", -) \ No newline at end of file +) + +fun Series?.toLabel(): String? { + return when { + this != null && index != null -> "$name - $index" + this != null -> name + else -> null + } +} \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f87c2d6..9d056d8 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -44,11 +44,14 @@ Rechercher sur Biblib Rechercher + %1$s : %2$s Auteur - Série + Série Genre Langue + Trié par : %1$s + Profile \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d664c7e..4272479 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -50,10 +50,13 @@ Search on Biblib Search - Author - Serie - Genre - Language + %1$s: %2$s + Authors + Series + Genres + Languages + + Sort by: %1$s Profil