Clean search filtering.
This commit is contained in:
parent
e176b6827a
commit
e69af172af
20 changed files with 177 additions and 219 deletions
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.pixelized.biblib.repository.search
|
package com.pixelized.biblib.repository.search
|
||||||
|
|
||||||
import com.pixelized.biblib.model.book.*
|
import com.pixelized.biblib.model.book.*
|
||||||
|
import com.pixelized.biblib.model.search.SortType
|
||||||
|
|
||||||
interface ISearchRepository {
|
interface ISearchRepository {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import com.pixelized.biblib.database.crossref.BookGenreCrossRef
|
||||||
import com.pixelized.biblib.database.data.*
|
import com.pixelized.biblib.database.data.*
|
||||||
import com.pixelized.biblib.database.relation.BookRelation
|
import com.pixelized.biblib.database.relation.BookRelation
|
||||||
import com.pixelized.biblib.model.book.*
|
import com.pixelized.biblib.model.book.*
|
||||||
|
import com.pixelized.biblib.model.search.SortType
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SearchRepository @Inject constructor(
|
class SearchRepository @Inject constructor(
|
||||||
|
|
@ -42,6 +43,7 @@ class SearchRepository @Inject constructor(
|
||||||
query += args.where(argument = languageId) {
|
query += args.where(argument = languageId) {
|
||||||
BookDbo.run { "$TABLE.$LANGUAGE_ID LIKE ?" }
|
BookDbo.run { "$TABLE.$LANGUAGE_ID LIKE ?" }
|
||||||
}
|
}
|
||||||
|
query += BookDbo.run { " ORDER BY $TABLE.$SORT" }
|
||||||
// Limit and Offset the query.
|
// Limit and Offset the query.
|
||||||
query += " LIMIT $limit OFFSET $offset;"
|
query += " LIMIT $limit OFFSET $offset;"
|
||||||
// compute the query
|
// compute the query
|
||||||
|
|
@ -57,6 +59,7 @@ class SearchRepository @Inject constructor(
|
||||||
val query = AuthorDbo.run {
|
val query = AuthorDbo.run {
|
||||||
"SELECT $TABLE.* FROM $TABLE" +
|
"SELECT $TABLE.* FROM $TABLE" +
|
||||||
args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } +
|
args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } +
|
||||||
|
" ORDER BY $TABLE.$SORT" +
|
||||||
" LIMIT $limit OFFSET $offset;"
|
" LIMIT $limit OFFSET $offset;"
|
||||||
}
|
}
|
||||||
// compute the query
|
// compute the query
|
||||||
|
|
@ -72,6 +75,7 @@ class SearchRepository @Inject constructor(
|
||||||
val query = GenreDbo.run {
|
val query = GenreDbo.run {
|
||||||
"SELECT $TABLE.* FROM $TABLE" +
|
"SELECT $TABLE.* FROM $TABLE" +
|
||||||
args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } +
|
args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } +
|
||||||
|
" ORDER BY $TABLE.$NAME" +
|
||||||
" LIMIT $limit OFFSET $offset;"
|
" LIMIT $limit OFFSET $offset;"
|
||||||
}
|
}
|
||||||
// compute the query
|
// compute the query
|
||||||
|
|
@ -87,6 +91,7 @@ class SearchRepository @Inject constructor(
|
||||||
val query = SeriesDbo.run {
|
val query = SeriesDbo.run {
|
||||||
"SELECT $TABLE.* FROM $TABLE" +
|
"SELECT $TABLE.* FROM $TABLE" +
|
||||||
args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } +
|
args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } +
|
||||||
|
" ORDER BY $TABLE.$SORT" +
|
||||||
" LIMIT $limit OFFSET $offset;"
|
" LIMIT $limit OFFSET $offset;"
|
||||||
}
|
}
|
||||||
// compute the query
|
// compute the query
|
||||||
|
|
@ -102,6 +107,7 @@ class SearchRepository @Inject constructor(
|
||||||
val query = LanguageDbo.run {
|
val query = LanguageDbo.run {
|
||||||
"SELECT $TABLE.* FROM $TABLE" +
|
"SELECT $TABLE.* FROM $TABLE" +
|
||||||
args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } +
|
args.where(argument = search) { "$TABLE.$NAME LIKE '%'||?||'%'" } +
|
||||||
|
" ORDER BY $TABLE.$NAME" +
|
||||||
" LIMIT $limit OFFSET $offset;"
|
" LIMIT $limit OFFSET $offset;"
|
||||||
}
|
}
|
||||||
// compute the query
|
// compute the query
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
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.screen.home.page.search.viewModel.BookSearchViewModel
|
||||||
import com.pixelized.biblib.ui.theme.color.ShadowPalette
|
import com.pixelized.biblib.ui.theme.color.ShadowPalette
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -20,14 +21,14 @@ import kotlinx.coroutines.launch
|
||||||
val LocalBookSearchViewModel = staticCompositionLocalOf<BookSearchViewModel> {
|
val LocalBookSearchViewModel = staticCompositionLocalOf<BookSearchViewModel> {
|
||||||
error("SearchViewModel is not ready yet")
|
error("SearchViewModel is not ready yet")
|
||||||
}
|
}
|
||||||
val LocalCategorySearchBottomSheetState = staticCompositionLocalOf<SearchBottomSheetState> {
|
val LocalFilterSearchBottomSheetState = staticCompositionLocalOf<FilterSearchBottomSheetState> {
|
||||||
error("BottomSearchState is not ready yet")
|
error("FilterSearchBottomSheetState is not ready yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun CategorySearchBottomSheet(
|
fun SearchOptionBottomSheet(
|
||||||
state: SearchBottomSheetState = rememberSearchBottomSheetState(),
|
filterState: FilterSearchBottomSheetState = rememberSearchBottomSheetState(),
|
||||||
bookSearchViewModel: BookSearchViewModel = hiltViewModel(),
|
bookSearchViewModel: BookSearchViewModel = hiltViewModel(),
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
|
@ -35,23 +36,23 @@ fun CategorySearchBottomSheet(
|
||||||
|
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalBookSearchViewModel provides bookSearchViewModel,
|
LocalBookSearchViewModel provides bookSearchViewModel,
|
||||||
LocalCategorySearchBottomSheetState provides state,
|
LocalFilterSearchBottomSheetState provides filterState,
|
||||||
) {
|
) {
|
||||||
ModalBottomSheetLayout(
|
ModalBottomSheetLayout(
|
||||||
modifier = Modifier.statusBarsPadding(),
|
modifier = Modifier.statusBarsPadding(),
|
||||||
scrimColor = ShadowPalette.scrim,
|
scrimColor = ShadowPalette.scrim,
|
||||||
sheetState = state.bottomSheetState,
|
sheetState = filterState.bottomSheetState,
|
||||||
sheetContent = {
|
sheetContent = {
|
||||||
FilterSearchPage(
|
FilterSearchPage(
|
||||||
focusRequester = state.focusRequester,
|
focusRequester = filterState.focusRequester,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
content = content,
|
content = content,
|
||||||
)
|
)
|
||||||
|
|
||||||
BackHandler(state.bottomSheetState.isVisible) {
|
BackHandler(filterState.bottomSheetState.isVisible) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
state.collapse()
|
filterState.collapse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,12 +66,12 @@ fun rememberSearchBottomSheetState(
|
||||||
initialValue = Hidden,
|
initialValue = Hidden,
|
||||||
skipHalfExpanded = true,
|
skipHalfExpanded = true,
|
||||||
),
|
),
|
||||||
): SearchBottomSheetState {
|
): FilterSearchBottomSheetState {
|
||||||
val filter = rememberSaveable(bottomSheetState) {
|
val filter = rememberSaveable(bottomSheetState) {
|
||||||
mutableStateOf<SearchFilter?>(null)
|
mutableStateOf<SearchType?>(null)
|
||||||
}
|
}
|
||||||
return remember(bottomSheetState) {
|
return remember(bottomSheetState) {
|
||||||
SearchBottomSheetState(
|
FilterSearchBottomSheetState(
|
||||||
bottomSheetState = bottomSheetState,
|
bottomSheetState = bottomSheetState,
|
||||||
focusRequester = focusRequester,
|
focusRequester = focusRequester,
|
||||||
filter = filter,
|
filter = filter,
|
||||||
|
|
@ -80,15 +81,15 @@ fun rememberSearchBottomSheetState(
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Stable
|
@Stable
|
||||||
class SearchBottomSheetState constructor(
|
class FilterSearchBottomSheetState constructor(
|
||||||
val bottomSheetState: ModalBottomSheetState,
|
val bottomSheetState: ModalBottomSheetState,
|
||||||
val focusRequester: FocusRequester,
|
val focusRequester: FocusRequester,
|
||||||
filter: MutableState<SearchFilter?>,
|
filter: MutableState<SearchType?>,
|
||||||
) {
|
) {
|
||||||
var filter: SearchFilter? by filter
|
var filter: SearchType? by filter
|
||||||
private set
|
private set
|
||||||
|
|
||||||
suspend fun expandSearch(filter: SearchFilter?) {
|
suspend fun expandSearch(filter: SearchType?) {
|
||||||
this.filter = filter
|
this.filter = filter
|
||||||
bottomSheetState.show()
|
bottomSheetState.show()
|
||||||
focusRequester.requestFocus()
|
focusRequester.requestFocus()
|
||||||
|
|
@ -97,13 +98,4 @@ class SearchBottomSheetState constructor(
|
||||||
suspend fun collapse() {
|
suspend fun collapse() {
|
||||||
bottomSheetState.hide()
|
bottomSheetState.hide()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Stable
|
|
||||||
@Immutable
|
|
||||||
enum class SearchFilter {
|
|
||||||
Author,
|
|
||||||
Series,
|
|
||||||
Genre,
|
|
||||||
Language;
|
|
||||||
}
|
}
|
||||||
|
|
@ -57,7 +57,7 @@ fun HomeScreen(
|
||||||
val focusRequester: FocusRequester = remember { FocusRequester() }
|
val focusRequester: FocusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
DetailBottomSheet {
|
DetailBottomSheet {
|
||||||
CategorySearchBottomSheet {
|
SearchOptionBottomSheet {
|
||||||
SearchScaffold(
|
SearchScaffold(
|
||||||
modifier = Modifier.statusBarsPadding(),
|
modifier = Modifier.statusBarsPadding(),
|
||||||
state = searchScaffoldState,
|
state = searchScaffoldState,
|
||||||
|
|
@ -138,7 +138,7 @@ fun HomeScreen(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
val bottomSearchState = LocalCategorySearchBottomSheetState.current
|
val bottomSearchState = LocalFilterSearchBottomSheetState.current
|
||||||
val bottomDetailState = LocalDetailBottomSheetState.current
|
val bottomDetailState = LocalDetailBottomSheetState.current
|
||||||
BackHandler(
|
BackHandler(
|
||||||
enabled = searchScaffoldState.isExpended || bottomSearchState.bottomSheetState.isVisible || bottomDetailState.bottomSheetState.isVisible
|
enabled = searchScaffoldState.isExpended || bottomSearchState.bottomSheetState.isVisible || bottomDetailState.bottomSheetState.isVisible
|
||||||
|
|
|
||||||
|
|
@ -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_NO
|
||||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||||
import androidx.compose.animation.core.Spring
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.animation.core.spring
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
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.Composable
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
import androidx.compose.ui.Modifier
|
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.LocalFocusManager
|
||||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
|
@ -23,33 +21,31 @@ import androidx.paging.PagingData
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import androidx.paging.compose.items
|
import androidx.paging.compose.items
|
||||||
import com.pixelized.biblib.R
|
import com.pixelized.biblib.R
|
||||||
import com.pixelized.biblib.ui.scaffold.LocalCategorySearchBottomSheetState
|
import com.pixelized.biblib.model.search.SearchType
|
||||||
import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState
|
|
||||||
import com.pixelized.biblib.ui.scaffold.LocalBookSearchViewModel
|
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.MicroBookThumbnail
|
||||||
import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnailUio
|
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.SearchFilterList
|
||||||
import com.pixelized.biblib.ui.screen.home.page.search.item.SearchFilterUio
|
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.screen.home.page.search.viewModel.BookSearchViewModel
|
||||||
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.default
|
||||||
import com.pixelized.biblib.utils.extention.isLoading
|
|
||||||
import com.pixelized.biblib.utils.extention.navigationBarsHeight
|
import com.pixelized.biblib.utils.extention.navigationBarsHeight
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalComposeUiApi::class)
|
@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun SearchPage(
|
fun SearchPage(
|
||||||
bookSearchViewModel: BookSearchViewModel = LocalBookSearchViewModel.current,
|
bookSearchViewModel: BookSearchViewModel = LocalBookSearchViewModel.current,
|
||||||
) {
|
) {
|
||||||
val keyboard = LocalSoftwareKeyboardController.current
|
val keyboard = LocalSoftwareKeyboardController.current
|
||||||
val detail = LocalDetailBottomSheetState.current
|
val detail = LocalDetailBottomSheetState.current
|
||||||
val search = LocalCategorySearchBottomSheetState.current
|
val filter = LocalFilterSearchBottomSheetState.current
|
||||||
val focus = LocalFocusManager.current
|
val focus = LocalFocusManager.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
|
@ -58,8 +54,17 @@ fun SearchPage(
|
||||||
search = bookSearchViewModel.paging,
|
search = bookSearchViewModel.paging,
|
||||||
filters = filters(bookSearchViewModel),
|
filters = filters(bookSearchViewModel),
|
||||||
onFilter = {
|
onFilter = {
|
||||||
scope.launch {
|
if (it.value == null) {
|
||||||
search.expandSearch(it.id)
|
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 = {
|
onDetail = {
|
||||||
|
|
@ -75,10 +80,10 @@ fun SearchPage(
|
||||||
@Composable
|
@Composable
|
||||||
private fun SearchPageContent(
|
private fun SearchPageContent(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
search: Flow<PagingData<MicroBookThumbnailUio>>,
|
search: Flow<PagingData<MicroBookThumbnailUio>> = emptyFlow(),
|
||||||
filters: List<SearchFilterUio> = emptyList(),
|
filters: List<SearchFilterUio> = emptyList(),
|
||||||
onFilter: (filter: SearchFilterUio) -> Unit,
|
onFilter: (filter: SearchFilterUio) -> Unit = default<SearchFilterUio>(),
|
||||||
onDetail: (item: MicroBookThumbnailUio) -> Unit,
|
onDetail: (item: MicroBookThumbnailUio) -> Unit = default<MicroBookThumbnailUio>(),
|
||||||
) {
|
) {
|
||||||
val items = search.collectAsLazyPagingItems()
|
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
|
@Composable
|
||||||
|
|
@ -135,22 +117,22 @@ private fun filters(
|
||||||
bookSearchViewModel: BookSearchViewModel,
|
bookSearchViewModel: BookSearchViewModel,
|
||||||
) = listOf(
|
) = listOf(
|
||||||
SearchFilterUio(
|
SearchFilterUio(
|
||||||
id = SearchFilter.Author,
|
id = SearchType.Author,
|
||||||
label = stringResource(id = R.string.search_filter_author),
|
label = stringResource(id = R.string.search_filter_author),
|
||||||
value = bookSearchViewModel.author?.filter,
|
value = bookSearchViewModel.author?.filter,
|
||||||
),
|
),
|
||||||
SearchFilterUio(
|
SearchFilterUio(
|
||||||
id = SearchFilter.Genre,
|
id = SearchType.Genre,
|
||||||
label = stringResource(id = R.string.search_filter_genre),
|
label = stringResource(id = R.string.search_filter_genre),
|
||||||
value = bookSearchViewModel.genre?.filter,
|
value = bookSearchViewModel.genre?.filter,
|
||||||
),
|
),
|
||||||
SearchFilterUio(
|
SearchFilterUio(
|
||||||
id = SearchFilter.Series,
|
id = SearchType.Series,
|
||||||
label = stringResource(id = R.string.search_filter_serie),
|
label = stringResource(id = R.string.search_filter_series),
|
||||||
value = bookSearchViewModel.series?.filter,
|
value = bookSearchViewModel.series?.filter,
|
||||||
),
|
),
|
||||||
SearchFilterUio(
|
SearchFilterUio(
|
||||||
id = SearchFilter.Language,
|
id = SearchType.Language,
|
||||||
label = stringResource(id = R.string.search_filter_language),
|
label = stringResource(id = R.string.search_filter_language),
|
||||||
value = bookSearchViewModel.language?.filter,
|
value = bookSearchViewModel.language?.filter,
|
||||||
),
|
),
|
||||||
|
|
@ -163,10 +145,6 @@ private fun SearchPageContentPreview() {
|
||||||
BibLibTheme {
|
BibLibTheme {
|
||||||
SearchPageContent(
|
SearchPageContent(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
search = emptyFlow(),
|
|
||||||
filters = searchFilterPreviewItems(),
|
|
||||||
onFilter = default<SearchFilterUio>(),
|
|
||||||
onDetail = default<MicroBookThumbnailUio>(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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_NO
|
||||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
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.collectAsLazyPagingItems
|
||||||
import androidx.paging.compose.items
|
import androidx.paging.compose.items
|
||||||
import com.pixelized.biblib.R
|
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.LocalBookSearchViewModel
|
||||||
import com.pixelized.biblib.ui.scaffold.LocalCategorySearchBottomSheetState
|
import com.pixelized.biblib.ui.scaffold.LocalFilterSearchBottomSheetState
|
||||||
import com.pixelized.biblib.ui.scaffold.SearchFilter
|
|
||||||
import com.pixelized.biblib.ui.screen.home.page.search.viewModel.*
|
import com.pixelized.biblib.ui.screen.home.page.search.viewModel.*
|
||||||
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
|
||||||
|
|
@ -48,16 +48,16 @@ fun FilterSearchPage(
|
||||||
focusRequester: FocusRequester = FocusRequester(),
|
focusRequester: FocusRequester = FocusRequester(),
|
||||||
) {
|
) {
|
||||||
val bookSearchViewModel = LocalBookSearchViewModel.current
|
val bookSearchViewModel = LocalBookSearchViewModel.current
|
||||||
val bottomSearchState = LocalCategorySearchBottomSheetState.current
|
val bottomSearchState = LocalFilterSearchBottomSheetState.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val filter = bottomSearchState.filter
|
val filter = bottomSearchState.filter
|
||||||
|
|
||||||
val viewModel: IFilterViewModel? = remember(filter) {
|
val viewModel: IFilterViewModel? = remember(filter) {
|
||||||
when (filter) {
|
when (filter) {
|
||||||
SearchFilter.Author -> authorFilterViewModel
|
SearchType.Author -> authorFilterViewModel
|
||||||
SearchFilter.Series -> seriesFilterViewModel
|
SearchType.Series -> seriesFilterViewModel
|
||||||
SearchFilter.Genre -> genreViewModel
|
SearchType.Genre -> genreViewModel
|
||||||
SearchFilter.Language -> languageViewModel
|
SearchType.Language -> languageViewModel
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,10 +72,10 @@ fun FilterSearchPage(
|
||||||
},
|
},
|
||||||
onClose = {
|
onClose = {
|
||||||
when (filter) {
|
when (filter) {
|
||||||
SearchFilter.Author -> bookSearchViewModel.filterAuthor(null)
|
SearchType.Author -> bookSearchViewModel.filterAuthor(null)
|
||||||
SearchFilter.Series -> bookSearchViewModel.filterSeries(null)
|
SearchType.Series -> bookSearchViewModel.filterSeries(null)
|
||||||
SearchFilter.Genre -> bookSearchViewModel.filterGenre(null)
|
SearchType.Genre -> bookSearchViewModel.filterGenre(null)
|
||||||
SearchFilter.Language -> bookSearchViewModel.filterLanguage(null)
|
SearchType.Language -> bookSearchViewModel.filterLanguage(null)
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
|
@ -84,10 +84,10 @@ fun FilterSearchPage(
|
||||||
},
|
},
|
||||||
onFilter = {
|
onFilter = {
|
||||||
when (filter) {
|
when (filter) {
|
||||||
SearchFilter.Author -> bookSearchViewModel.filterAuthor(it)
|
SearchType.Author -> bookSearchViewModel.filterAuthor(it)
|
||||||
SearchFilter.Series -> bookSearchViewModel.filterSeries(it)
|
SearchType.Series -> bookSearchViewModel.filterSeries(it)
|
||||||
SearchFilter.Genre -> bookSearchViewModel.filterGenre(it)
|
SearchType.Genre -> bookSearchViewModel.filterGenre(it)
|
||||||
SearchFilter.Language -> bookSearchViewModel.filterLanguage(it)
|
SearchType.Language -> bookSearchViewModel.filterLanguage(it)
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
|
@ -100,7 +100,7 @@ fun FilterSearchPage(
|
||||||
@Composable
|
@Composable
|
||||||
fun CategorySearchPageContent(
|
fun CategorySearchPageContent(
|
||||||
focusRequester: FocusRequester = FocusRequester(),
|
focusRequester: FocusRequester = FocusRequester(),
|
||||||
filter: SearchFilter?,
|
filter: SearchType?,
|
||||||
search: () -> String?,
|
search: () -> String?,
|
||||||
paging: () -> Flow<PagingData<FilterUio>> = { emptyFlow() },
|
paging: () -> Flow<PagingData<FilterUio>> = { emptyFlow() },
|
||||||
onSearchUpdate: (String) -> Unit = default<String>(),
|
onSearchUpdate: (String) -> Unit = default<String>(),
|
||||||
|
|
@ -121,10 +121,10 @@ fun CategorySearchPageContent(
|
||||||
style = MaterialTheme.typography.h6,
|
style = MaterialTheme.typography.h6,
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.colors.onSurface,
|
||||||
text = when (filter) {
|
text = when (filter) {
|
||||||
SearchFilter.Author -> stringResource(id = R.string.search_filter_author)
|
SearchType.Author -> stringResource(id = R.string.search_filter_author)
|
||||||
SearchFilter.Genre -> stringResource(id = R.string.search_filter_genre)
|
SearchType.Genre -> stringResource(id = R.string.search_filter_genre)
|
||||||
SearchFilter.Series -> stringResource(id = R.string.search_filter_serie)
|
SearchType.Series -> stringResource(id = R.string.search_filter_series)
|
||||||
SearchFilter.Language -> stringResource(id = R.string.search_filter_language)
|
SearchType.Language -> stringResource(id = R.string.search_filter_language)
|
||||||
else -> ""
|
else -> ""
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -181,7 +181,7 @@ fun CategorySearchPageContent(
|
||||||
private fun CategorySearchPageContentPreview() {
|
private fun CategorySearchPageContentPreview() {
|
||||||
BibLibTheme {
|
BibLibTheme {
|
||||||
CategorySearchPageContent(
|
CategorySearchPageContent(
|
||||||
filter = SearchFilter.Author,
|
filter = SearchType.Author,
|
||||||
search = { "Asimov" },
|
search = { "Asimov" },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -1,22 +1,23 @@
|
||||||
package com.pixelized.biblib.ui.screen.home.page.search.item
|
package com.pixelized.biblib.ui.screen.home.page.search.item
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import androidx.compose.animation.*
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
import androidx.compose.material.icons.filled.Close
|
||||||
import androidx.compose.runtime.*
|
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.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import com.pixelized.biblib.R
|
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.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.default
|
||||||
|
|
@ -24,7 +25,7 @@ import com.pixelized.biblib.utils.extention.default
|
||||||
@Stable
|
@Stable
|
||||||
@Immutable
|
@Immutable
|
||||||
data class SearchFilterUio(
|
data class SearchFilterUio(
|
||||||
val id: SearchFilter,
|
val id: SearchType,
|
||||||
val label: String,
|
val label: String,
|
||||||
val value: String? = null,
|
val value: String? = null,
|
||||||
)
|
)
|
||||||
|
|
@ -51,7 +52,7 @@ fun SearchFilterList(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class, ExperimentalAnimationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun SearchFilter(
|
private fun SearchFilter(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
|
@ -59,34 +60,34 @@ private fun SearchFilter(
|
||||||
onClick: () -> Unit = default(),
|
onClick: () -> Unit = default(),
|
||||||
) {
|
) {
|
||||||
FilterChip(
|
FilterChip(
|
||||||
modifier = modifier,
|
modifier = modifier.animateContentSize(),
|
||||||
selected = uio.value != null,
|
selected = uio.value != null,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
) {
|
trailingIcon = {
|
||||||
Text(
|
Icon(
|
||||||
color = MaterialTheme.bibLib.colors.typography.medium,
|
modifier = Modifier.size(MaterialTheme.bibLib.dimen.dp12),
|
||||||
style = MaterialTheme.typography.caption,
|
imageVector = when (uio.value) {
|
||||||
text = uio.label,
|
null -> Icons.Default.KeyboardArrowDown
|
||||||
)
|
else -> Icons.Default.Close
|
||||||
|
},
|
||||||
uio.value?.let {
|
tint = MaterialTheme.bibLib.colors.typography.medium,
|
||||||
Text(
|
contentDescription = null
|
||||||
color = MaterialTheme.bibLib.colors.typography.medium,
|
|
||||||
style = MaterialTheme.typography.caption,
|
|
||||||
text = ": "
|
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
AnimatedContent(
|
||||||
|
targetState = uio.value,
|
||||||
|
transitionSpec = { fadeIn() with fadeOut() },
|
||||||
|
) {
|
||||||
Text(
|
Text(
|
||||||
color = MaterialTheme.bibLib.colors.typography.medium,
|
color = MaterialTheme.bibLib.colors.typography.medium,
|
||||||
style = MaterialTheme.typography.caption,
|
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
|
@Composable
|
||||||
fun searchFilterPreviewItems() = listOf(
|
fun searchFilterPreviewItems() = listOf(
|
||||||
SearchFilterUio(
|
SearchFilterUio(
|
||||||
id = SearchFilter.Author,
|
id = SearchType.Author,
|
||||||
label = stringResource(id = R.string.search_filter_author),
|
label = stringResource(id = R.string.search_filter_author),
|
||||||
value = "Asimov",
|
value = "Asimov",
|
||||||
),
|
),
|
||||||
SearchFilterUio(
|
SearchFilterUio(
|
||||||
id = SearchFilter.Genre,
|
id = SearchType.Genre,
|
||||||
label = stringResource(id = R.string.search_filter_genre),
|
label = stringResource(id = R.string.search_filter_genre),
|
||||||
),
|
),
|
||||||
SearchFilterUio(
|
SearchFilterUio(
|
||||||
id = SearchFilter.Series,
|
id = SearchType.Series,
|
||||||
label = stringResource(id = R.string.search_filter_serie),
|
label = stringResource(id = R.string.search_filter_series),
|
||||||
),
|
),
|
||||||
SearchFilterUio(
|
SearchFilterUio(
|
||||||
id = SearchFilter.Language,
|
id = SearchType.Language,
|
||||||
label = stringResource(id = R.string.search_filter_language),
|
label = stringResource(id = R.string.search_filter_language),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -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")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -8,7 +8,8 @@ import androidx.lifecycle.viewModelScope
|
||||||
import androidx.paging.*
|
import androidx.paging.*
|
||||||
import com.pixelized.biblib.model.book.Author
|
import com.pixelized.biblib.model.book.Author
|
||||||
import com.pixelized.biblib.repository.search.ISearchRepository
|
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 com.pixelized.biblib.ui.screen.home.page.search.source.AuthorSearchSource
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import androidx.paging.*
|
||||||
import com.pixelized.biblib.model.book.Book
|
import com.pixelized.biblib.model.book.Book
|
||||||
import com.pixelized.biblib.repository.search.ISearchRepository
|
import com.pixelized.biblib.repository.search.ISearchRepository
|
||||||
import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnailUio
|
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.ui.screen.home.page.search.source.BookSearchSource
|
||||||
import com.pixelized.biblib.utils.extention.toMicroThumbnailUio
|
import com.pixelized.biblib.utils.extention.toMicroThumbnailUio
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
|
@ -65,10 +65,12 @@ class BookSearchViewModel @Inject constructor(
|
||||||
series = criteria
|
series = criteria
|
||||||
searchSource?.invalidate()
|
searchSource?.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun filterGenre(criteria: FilterUio?) {
|
fun filterGenre(criteria: FilterUio?) {
|
||||||
genre = criteria
|
genre = criteria
|
||||||
searchSource?.invalidate()
|
searchSource?.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun filterLanguage(criteria: FilterUio?) {
|
fun filterLanguage(criteria: FilterUio?) {
|
||||||
language = criteria
|
language = criteria
|
||||||
searchSource?.invalidate()
|
searchSource?.invalidate()
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope
|
||||||
import androidx.paging.*
|
import androidx.paging.*
|
||||||
import com.pixelized.biblib.model.book.Genre
|
import com.pixelized.biblib.model.book.Genre
|
||||||
import com.pixelized.biblib.repository.search.ISearchRepository
|
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 com.pixelized.biblib.ui.screen.home.page.search.source.GenreSearchSource
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package com.pixelized.biblib.ui.screen.home.page.search.viewModel
|
package com.pixelized.biblib.ui.screen.home.page.search.viewModel
|
||||||
|
|
||||||
import androidx.paging.PagingData
|
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
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface IFilterViewModel {
|
interface IFilterViewModel {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope
|
||||||
import androidx.paging.*
|
import androidx.paging.*
|
||||||
import com.pixelized.biblib.model.book.Language
|
import com.pixelized.biblib.model.book.Language
|
||||||
import com.pixelized.biblib.repository.search.ISearchRepository
|
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 com.pixelized.biblib.ui.screen.home.page.search.source.LanguageSearchSource
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope
|
||||||
import androidx.paging.*
|
import androidx.paging.*
|
||||||
import com.pixelized.biblib.model.book.Series
|
import com.pixelized.biblib.model.book.Series
|
||||||
import com.pixelized.biblib.repository.search.ISearchRepository
|
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 com.pixelized.biblib.ui.screen.home.page.search.source.SeriesSearchSource
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ data class BibLibDimen(
|
||||||
val dp2: Dp = 2.dp,
|
val dp2: Dp = 2.dp,
|
||||||
val dp4: Dp = 4.dp,
|
val dp4: Dp = 4.dp,
|
||||||
val dp8: Dp = 8.dp,
|
val dp8: Dp = 8.dp,
|
||||||
|
val dp12: Dp = 12.dp,
|
||||||
val dp16: Dp = 16.dp,
|
val dp16: Dp = 16.dp,
|
||||||
val dp32: Dp = 32.dp,
|
val dp32: Dp = 32.dp,
|
||||||
val dp48: Dp = 48.dp,
|
val dp48: Dp = 48.dp,
|
||||||
|
|
@ -33,10 +34,11 @@ data class BibLibDimen(
|
||||||
@Stable
|
@Stable
|
||||||
@Immutable
|
@Immutable
|
||||||
data class BookThumbnail(
|
data class BookThumbnail(
|
||||||
|
val ratio: Float = 1.6f,
|
||||||
val padding: Dp = 16.dp,
|
val padding: Dp = 16.dp,
|
||||||
val arrangement: Dp = 16.dp,
|
val arrangement: Dp = 16.dp,
|
||||||
val cover: DpSize = DpSize(width = 72.dp, height = 115.dp), // ratio 1.6
|
val cover: DpSize = 72.dp.let { DpSize(width = it, height = it * ratio) },
|
||||||
val micro: DpSize = DpSize(width = 40.dp, height = 64.dp), // ratio 1.6
|
val micro: DpSize = 48.dp.let { DpSize(width = it, height = it * ratio) },
|
||||||
)
|
)
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.pixelized.biblib.utils.extention
|
||||||
|
|
||||||
import androidx.annotation.StringDef
|
import androidx.annotation.StringDef
|
||||||
import com.pixelized.biblib.model.book.Book
|
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.network.client.IBibLibClient
|
||||||
import com.pixelized.biblib.ui.screen.home.common.item.LargeBookThumbnailUio
|
import com.pixelized.biblib.ui.screen.home.common.item.LargeBookThumbnailUio
|
||||||
import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnailUio
|
import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnailUio
|
||||||
|
|
@ -20,10 +21,10 @@ fun Book.toMicroThumbnailUio(
|
||||||
@CoverUrl coverBaseUrl: String = IBibLibClient.THUMBNAIL_URL
|
@CoverUrl coverBaseUrl: String = IBibLibClient.THUMBNAIL_URL
|
||||||
) = MicroBookThumbnailUio(
|
) = MicroBookThumbnailUio(
|
||||||
id = id,
|
id = id,
|
||||||
|
cover = "${coverBaseUrl}/$id.jpg",
|
||||||
title = title,
|
title = title,
|
||||||
author = author.joinToString { it.name },
|
author = author.joinToString { it.name },
|
||||||
isNew = isNew,
|
isNew = isNew,
|
||||||
cover = "${coverBaseUrl}/$id.jpg",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
fun Book.toSmallThumbnailUio(
|
fun Book.toSmallThumbnailUio(
|
||||||
|
|
@ -58,7 +59,15 @@ fun Book.toDetailUio(
|
||||||
rating = rating?.toFloat() ?: 0.0f,
|
rating = rating?.toFloat() ?: 0.0f,
|
||||||
language = language?.displayLanguage?.capitalize() ?: "",
|
language = language?.displayLanguage?.capitalize() ?: "",
|
||||||
date = releaseDate.shortDate(),
|
date = releaseDate.shortDate(),
|
||||||
series = series?.name,
|
series = series.toLabel(),
|
||||||
description = synopsis ?: "",
|
description = synopsis ?: "",
|
||||||
cover = "${coverBaseUrl}/$id.jpg",
|
cover = "${coverBaseUrl}/$id.jpg",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun Series?.toLabel(): String? {
|
||||||
|
return when {
|
||||||
|
this != null && index != null -> "$name - $index"
|
||||||
|
this != null -> name
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -44,11 +44,14 @@
|
||||||
|
|
||||||
<string name="search_title">Rechercher sur Biblib</string>
|
<string name="search_title">Rechercher sur Biblib</string>
|
||||||
<string name="search_filter_title">Rechercher</string>
|
<string name="search_filter_title">Rechercher</string>
|
||||||
|
<string name="search_filter_param">%1$s : %2$s</string>
|
||||||
<string name="search_filter_author">Auteur</string>
|
<string name="search_filter_author">Auteur</string>
|
||||||
<string name="search_filter_serie">Série</string>
|
<string name="search_filter_series">Série</string>
|
||||||
<string name="search_filter_genre">Genre</string>
|
<string name="search_filter_genre">Genre</string>
|
||||||
<string name="search_filter_language">Langue</string>
|
<string name="search_filter_language">Langue</string>
|
||||||
|
|
||||||
|
<string name="search_sort_by">Trié par : %1$s</string>
|
||||||
|
|
||||||
<string name="profile_title">Profile</string>
|
<string name="profile_title">Profile</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -50,10 +50,13 @@
|
||||||
|
|
||||||
<string name="search_title">Search on Biblib</string>
|
<string name="search_title">Search on Biblib</string>
|
||||||
<string name="search_filter_title">Search</string>
|
<string name="search_filter_title">Search</string>
|
||||||
<string name="search_filter_author">Author</string>
|
<string name="search_filter_param">%1$s: %2$s</string>
|
||||||
<string name="search_filter_serie">Serie</string>
|
<string name="search_filter_author">Authors</string>
|
||||||
<string name="search_filter_genre">Genre</string>
|
<string name="search_filter_series">Series</string>
|
||||||
<string name="search_filter_language">Language</string>
|
<string name="search_filter_genre">Genres</string>
|
||||||
|
<string name="search_filter_language">Languages</string>
|
||||||
|
|
||||||
|
<string name="search_sort_by">Sort by: %1$s</string>
|
||||||
|
|
||||||
<string name="profile_title">Profil</string>
|
<string name="profile_title">Profil</string>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue