Small UI Clean.
This commit is contained in:
parent
d65d0bc3d5
commit
d82efe7f5d
14 changed files with 134 additions and 77 deletions
|
|
@ -70,11 +70,12 @@ fun Search(
|
||||||
contentDescription = null
|
contentDescription = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.focusRequester(focusRequester = focusRequester)
|
.focusRequester(focusRequester = focusRequester)
|
||||||
.weight(1f),
|
.weight(1f),
|
||||||
label = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.colors.onSurface,
|
||||||
text = if (state.content != ContentState.PROFILE) {
|
text = if (state.content != ContentState.PROFILE) {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
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.compose.ui.graphics.Color
|
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import com.pixelized.biblib.R
|
import com.pixelized.biblib.R
|
||||||
import com.pixelized.biblib.ui.screen.home.page.search.CategorySearchPage
|
import com.pixelized.biblib.ui.screen.home.page.search.CategorySearchPage
|
||||||
|
|
@ -25,20 +24,20 @@ import java.io.Serializable
|
||||||
val LocalSearchViewModel = staticCompositionLocalOf<SearchViewModel> {
|
val LocalSearchViewModel = staticCompositionLocalOf<SearchViewModel> {
|
||||||
error("SearchViewModel is not ready yet")
|
error("SearchViewModel is not ready yet")
|
||||||
}
|
}
|
||||||
val LocalSearchBottomSheetState = staticCompositionLocalOf<SearchBottomSheetState> {
|
val LocalCategorySearchBottomSheetState = staticCompositionLocalOf<SearchBottomSheetState> {
|
||||||
error("BottomSearchState is not ready yet")
|
error("BottomSearchState is not ready yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun SearchBottomSheet(
|
fun CategorySearchBottomSheet(
|
||||||
state: SearchBottomSheetState = rememberSearchBottomSheetState(),
|
state: SearchBottomSheetState = rememberSearchBottomSheetState(),
|
||||||
searchViewModel: SearchViewModel = hiltViewModel(),
|
searchViewModel: SearchViewModel = hiltViewModel(),
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalSearchViewModel provides searchViewModel,
|
LocalSearchViewModel provides searchViewModel,
|
||||||
LocalSearchBottomSheetState provides state,
|
LocalCategorySearchBottomSheetState provides state,
|
||||||
) {
|
) {
|
||||||
ModalBottomSheetLayout(
|
ModalBottomSheetLayout(
|
||||||
modifier = Modifier.statusBarsPadding(),
|
modifier = Modifier.statusBarsPadding(),
|
||||||
|
|
@ -9,7 +9,6 @@ import androidx.compose.material.ModalBottomSheetValue.Hidden
|
||||||
import androidx.compose.material.rememberModalBottomSheetState
|
import androidx.compose.material.rememberModalBottomSheetState
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import com.pixelized.biblib.R
|
import com.pixelized.biblib.R
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,8 @@ class SearchScaffoldState(
|
||||||
expended: Boolean,
|
expended: Boolean,
|
||||||
state: ContentState = ContentState.INITIAL,
|
state: ContentState = ContentState.INITIAL,
|
||||||
) {
|
) {
|
||||||
private var isExpended: Boolean by mutableStateOf(expended)
|
var isExpended: Boolean by mutableStateOf(expended)
|
||||||
|
private set
|
||||||
|
|
||||||
var content: ContentState by mutableStateOf(state)
|
var content: ContentState by mutableStateOf(state)
|
||||||
private set
|
private set
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ import com.pixelized.biblib.R
|
||||||
import com.pixelized.biblib.ui.composable.Search
|
import com.pixelized.biblib.ui.composable.Search
|
||||||
import com.pixelized.biblib.ui.scaffold.*
|
import com.pixelized.biblib.ui.scaffold.*
|
||||||
import com.pixelized.biblib.ui.scaffold.SearchScaffoldState.ContentState
|
import com.pixelized.biblib.ui.scaffold.SearchScaffoldState.ContentState
|
||||||
import com.pixelized.biblib.ui.screen.home.common.connectivity.ConnectivityViewModel
|
|
||||||
import com.pixelized.biblib.ui.screen.home.common.connectivity.ConnectivityHeader
|
import com.pixelized.biblib.ui.screen.home.common.connectivity.ConnectivityHeader
|
||||||
|
import com.pixelized.biblib.ui.screen.home.common.connectivity.ConnectivityViewModel
|
||||||
import com.pixelized.biblib.ui.screen.home.page.Page
|
import com.pixelized.biblib.ui.screen.home.page.Page
|
||||||
import com.pixelized.biblib.ui.screen.home.page.books.BooksPage
|
import com.pixelized.biblib.ui.screen.home.page.books.BooksPage
|
||||||
import com.pixelized.biblib.ui.screen.home.page.news.NewsPage
|
import com.pixelized.biblib.ui.screen.home.page.news.NewsPage
|
||||||
|
|
@ -50,36 +50,36 @@ fun HomeScreen(
|
||||||
accountViewModel: HomeViewModel = hiltViewModel(),
|
accountViewModel: HomeViewModel = hiltViewModel(),
|
||||||
connectivityViewModel: ConnectivityViewModel = hiltViewModel(),
|
connectivityViewModel: ConnectivityViewModel = hiltViewModel(),
|
||||||
keyboard: SoftwareKeyboardController? = LocalSoftwareKeyboardController.current,
|
keyboard: SoftwareKeyboardController? = LocalSoftwareKeyboardController.current,
|
||||||
state: SearchScaffoldState = rememberSearchScaffoldState(),
|
searchScaffoldState: SearchScaffoldState = rememberSearchScaffoldState(),
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val focusManager: FocusManager = LocalFocusManager.current
|
val focusManager: FocusManager = LocalFocusManager.current
|
||||||
val focusRequester: FocusRequester = remember { FocusRequester() }
|
val focusRequester: FocusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
DetailBottomSheet {
|
DetailBottomSheet {
|
||||||
SearchBottomSheet {
|
CategorySearchBottomSheet {
|
||||||
SearchScaffold(
|
SearchScaffold(
|
||||||
modifier = Modifier.statusBarsPadding(),
|
modifier = Modifier.statusBarsPadding(),
|
||||||
state = state,
|
state = searchScaffoldState,
|
||||||
topBar = {
|
topBar = {
|
||||||
val viewModel = LocalSearchViewModel.current
|
val viewModel = LocalSearchViewModel.current
|
||||||
val search by viewModel.filterFlow.collectAsState(initial = "")
|
val search by viewModel.filterFlow.collectAsState(initial = "")
|
||||||
Search(
|
Search(
|
||||||
state = state,
|
state = searchScaffoldState,
|
||||||
avatar = accountViewModel.avatar,
|
avatar = accountViewModel.avatar,
|
||||||
focusRequester = focusRequester,
|
focusRequester = focusRequester,
|
||||||
onCloseTap = {
|
onCloseTap = {
|
||||||
focusManager.clearFocus(force = true)
|
focusManager.clearFocus(force = true)
|
||||||
keyboard?.hide()
|
keyboard?.hide()
|
||||||
state.collapse()
|
searchScaffoldState.collapse()
|
||||||
},
|
},
|
||||||
searchValue = search,
|
searchValue = search,
|
||||||
onSearchValueChange = {
|
onSearchValueChange = {
|
||||||
viewModel.filter(criteria = it)
|
viewModel.filter(criteria = it)
|
||||||
},
|
},
|
||||||
onSearchTap = {
|
onSearchTap = {
|
||||||
if (state.content != ContentState.SEARCH || state.isCollapsed()) {
|
if (searchScaffoldState.content != ContentState.SEARCH || searchScaffoldState.isCollapsed()) {
|
||||||
state.expand(ContentState.SEARCH)
|
searchScaffoldState.expand(ContentState.SEARCH)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
delay(100) // let the animation play before requesting the focus
|
delay(100) // let the animation play before requesting the focus
|
||||||
focusRequester.requestFocus()
|
focusRequester.requestFocus()
|
||||||
|
|
@ -87,16 +87,16 @@ fun HomeScreen(
|
||||||
} else {
|
} else {
|
||||||
focusManager.clearFocus(force = true)
|
focusManager.clearFocus(force = true)
|
||||||
keyboard?.hide()
|
keyboard?.hide()
|
||||||
state.collapse()
|
searchScaffoldState.collapse()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onAvatarTap = {
|
onAvatarTap = {
|
||||||
if (state.content != ContentState.PROFILE || state.isCollapsed()) {
|
if (searchScaffoldState.content != ContentState.PROFILE || searchScaffoldState.isCollapsed()) {
|
||||||
focusManager.clearFocus(force = true)
|
focusManager.clearFocus(force = true)
|
||||||
keyboard?.hide()
|
keyboard?.hide()
|
||||||
state.expand(ContentState.PROFILE)
|
searchScaffoldState.expand(ContentState.PROFILE)
|
||||||
} else {
|
} else {
|
||||||
state.collapse()
|
searchScaffoldState.collapse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -104,7 +104,7 @@ fun HomeScreen(
|
||||||
search = {
|
search = {
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
AnimatedContent(
|
AnimatedContent(
|
||||||
targetState = state.content,
|
targetState = searchScaffoldState.content,
|
||||||
transitionSpec = {
|
transitionSpec = {
|
||||||
when {
|
when {
|
||||||
targetState == ContentState.INITIAL -> {
|
targetState == ContentState.INITIAL -> {
|
||||||
|
|
@ -139,12 +139,16 @@ fun HomeScreen(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val bottomSearchState = LocalCategorySearchBottomSheetState.current
|
||||||
val bottomSearchState = LocalSearchBottomSheetState.current
|
val bottomDetailState = LocalDetailBottomSheetState.current
|
||||||
BackHandler(
|
BackHandler(
|
||||||
state.isCollapsed().not() && bottomSearchState.bottomSheetState.isVisible.not()
|
enabled = searchScaffoldState.isExpended || bottomSearchState.bottomSheetState.isVisible || bottomDetailState.bottomSheetState.isVisible
|
||||||
) {
|
) {
|
||||||
state.collapse()
|
when {
|
||||||
|
bottomSearchState.bottomSheetState.isVisible -> bottomSearchState.collapse()
|
||||||
|
bottomDetailState.bottomSheetState.isVisible -> bottomDetailState.collapse()
|
||||||
|
searchScaffoldState.isExpended -> searchScaffoldState.collapse()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.pixelized.biblib.ui.screen.home.common.item
|
package com.pixelized.biblib.ui.screen.home.common.item
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.text.Layout
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
|
@ -10,7 +11,9 @@ import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
@ -64,6 +67,7 @@ private fun SmallBookThumbnailContent(
|
||||||
.clickable { onClick(thumbnail) }
|
.clickable { onClick(thumbnail) }
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.wrapContentHeight(),
|
.wrapContentHeight(),
|
||||||
|
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall,
|
||||||
) {
|
) {
|
||||||
ConstraintLayout(
|
ConstraintLayout(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
|
@ -77,6 +81,7 @@ private fun SmallBookThumbnailContent(
|
||||||
bottom.linkTo(parent.bottom)
|
bottom.linkTo(parent.bottom)
|
||||||
start.linkTo(parent.start)
|
start.linkTo(parent.start)
|
||||||
}
|
}
|
||||||
|
.clip(shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall)
|
||||||
.size(size = MaterialTheme.bibLib.dimen.thumbnail.cover),
|
.size(size = MaterialTheme.bibLib.dimen.thumbnail.cover),
|
||||||
previewPlaceholder = R.drawable.ic_fondation_thumbnail,
|
previewPlaceholder = R.drawable.ic_fondation_thumbnail,
|
||||||
imageModel = thumbnail.cover,
|
imageModel = thumbnail.cover,
|
||||||
|
|
@ -90,7 +95,7 @@ private fun SmallBookThumbnailContent(
|
||||||
width = Dimension.fillToConstraints
|
width = Dimension.fillToConstraints
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.h6,
|
style = MaterialTheme.typography.h6,
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.bibLib.colors.typography.medium,
|
||||||
text = thumbnail.title,
|
text = thumbnail.title,
|
||||||
maxLines = 2,
|
maxLines = 2,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
|
@ -106,7 +111,7 @@ private fun SmallBookThumbnailContent(
|
||||||
height = Dimension.fillToConstraints
|
height = Dimension.fillToConstraints
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.body1,
|
style = MaterialTheme.typography.body1,
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.bibLib.colors.typography.easy,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
text = thumbnail.author
|
text = thumbnail.author
|
||||||
|
|
@ -122,7 +127,7 @@ private fun SmallBookThumbnailContent(
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
style = MaterialTheme.typography.caption,
|
style = MaterialTheme.typography.caption,
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.bibLib.colors.typography.easy,
|
||||||
text = thumbnail.genre
|
text = thumbnail.genre
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -132,7 +137,7 @@ private fun SmallBookThumbnailContent(
|
||||||
end.linkTo(parent.end, margin = dimen.dp8)
|
end.linkTo(parent.end, margin = dimen.dp8)
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.caption,
|
style = MaterialTheme.typography.caption,
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.bibLib.colors.typography.easy,
|
||||||
text = thumbnail.date ?: ""
|
text = thumbnail.date ?: ""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -148,6 +153,7 @@ private fun SmallBookThumbnailPlaceHolder(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.wrapContentHeight(),
|
.wrapContentHeight(),
|
||||||
|
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall,
|
||||||
) {
|
) {
|
||||||
ConstraintLayout(
|
ConstraintLayout(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
|
@ -163,8 +169,8 @@ private fun SmallBookThumbnailPlaceHolder(
|
||||||
}
|
}
|
||||||
.size(size = MaterialTheme.bibLib.dimen.thumbnail.cover)
|
.size(size = MaterialTheme.bibLib.dimen.thumbnail.cover)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.bibLib.color.placeHolder,
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
shape = MaterialTheme.shapes.medium,
|
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -176,7 +182,7 @@ private fun SmallBookThumbnailPlaceHolder(
|
||||||
}
|
}
|
||||||
.size(width = 120.dp, height = 16.dp)
|
.size(width = 120.dp, height = 16.dp)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.bibLib.color.placeHolder,
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -189,7 +195,7 @@ private fun SmallBookThumbnailPlaceHolder(
|
||||||
}
|
}
|
||||||
.size(width = 100.dp, height = 16.dp)
|
.size(width = 100.dp, height = 16.dp)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.bibLib.color.placeHolder,
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -202,7 +208,7 @@ private fun SmallBookThumbnailPlaceHolder(
|
||||||
}
|
}
|
||||||
.size(width = 80.dp, height = 16.dp)
|
.size(width = 80.dp, height = 16.dp)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.bibLib.color.placeHolder,
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -215,7 +221,7 @@ private fun SmallBookThumbnailPlaceHolder(
|
||||||
}
|
}
|
||||||
.size(width = 40.dp, height = 16.dp)
|
.size(width = 40.dp, height = 16.dp)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.bibLib.color.placeHolder,
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -229,16 +235,23 @@ fun LargeBookThumbnail(
|
||||||
thumbnail: BookThumbnailUio?,
|
thumbnail: BookThumbnailUio?,
|
||||||
onClick: (BookThumbnailUio) -> Unit = default<BookThumbnailUio>(),
|
onClick: (BookThumbnailUio) -> Unit = default<BookThumbnailUio>(),
|
||||||
) {
|
) {
|
||||||
if (thumbnail != null) {
|
Card(
|
||||||
LargeBookThumbnailContent(
|
modifier = modifier
|
||||||
modifier = modifier,
|
.fillMaxWidth()
|
||||||
thumbnail = thumbnail,
|
.wrapContentHeight(),
|
||||||
onClick = onClick,
|
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge,
|
||||||
)
|
) {
|
||||||
} else {
|
if (thumbnail != null) {
|
||||||
LargeBookThumbnailPlaceHolder(
|
LargeBookThumbnailContent(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
thumbnail = thumbnail,
|
||||||
|
onClick = onClick,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LargeBookThumbnailPlaceHolder(
|
||||||
|
modifier = modifier,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -253,6 +266,7 @@ private fun LargeBookThumbnailContent(
|
||||||
) {
|
) {
|
||||||
GlideImage(
|
GlideImage(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.clip(shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.aspectRatio(64f / 102f),
|
.aspectRatio(64f / 102f),
|
||||||
previewPlaceholder = R.drawable.ic_fondatoin_cover,
|
previewPlaceholder = R.drawable.ic_fondatoin_cover,
|
||||||
|
|
@ -260,22 +274,30 @@ private fun LargeBookThumbnailContent(
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||||
|
.padding(horizontal = MaterialTheme.bibLib.dimen.dp8),
|
||||||
style = MaterialTheme.typography.body1,
|
style = MaterialTheme.typography.body1,
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.bibLib.colors.typography.medium,
|
||||||
text = thumbnail.title,
|
text = thumbnail.title,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
|
modifier = Modifier.padding(horizontal = MaterialTheme.bibLib.dimen.dp8),
|
||||||
style = MaterialTheme.typography.caption,
|
style = MaterialTheme.typography.caption,
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.bibLib.colors.typography.easy,
|
||||||
text = thumbnail.author
|
text = thumbnail.author
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(alignment = Alignment.End)
|
||||||
|
.padding(horizontal = MaterialTheme.bibLib.dimen.dp8)
|
||||||
|
.padding(bottom = MaterialTheme.bibLib.dimen.dp8),
|
||||||
style = MaterialTheme.typography.caption,
|
style = MaterialTheme.typography.caption,
|
||||||
color = MaterialTheme.colors.onSurface,
|
color = MaterialTheme.bibLib.colors.typography.easy,
|
||||||
text = thumbnail.date ?: ""
|
text = thumbnail.date ?: ""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -291,8 +313,8 @@ private fun LargeBookThumbnailPlaceHolder(
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.aspectRatio(64f / 102f)
|
.aspectRatio(64f / 102f)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.bibLib.color.placeHolder,
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
shape = MaterialTheme.shapes.medium,
|
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -301,7 +323,7 @@ private fun LargeBookThumbnailPlaceHolder(
|
||||||
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||||
.size(width = 80.dp, height = 12.dp)
|
.size(width = 80.dp, height = 12.dp)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.bibLib.color.placeHolder,
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -311,7 +333,7 @@ private fun LargeBookThumbnailPlaceHolder(
|
||||||
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||||
.size(width = 60.dp, height = 12.dp)
|
.size(width = 60.dp, height = 12.dp)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.bibLib.color.placeHolder,
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -321,7 +343,7 @@ private fun LargeBookThumbnailPlaceHolder(
|
||||||
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||||
.size(width = 40.dp, height = 12.dp)
|
.size(width = 40.dp, height = 12.dp)
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.bibLib.color.placeHolder,
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
shape = CircleShape,
|
shape = CircleShape,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -371,7 +393,7 @@ private fun LargeBookThumbnailPreview() {
|
||||||
genre = "Sci-Fi",
|
genre = "Sci-Fi",
|
||||||
title = "Foundation",
|
title = "Foundation",
|
||||||
author = "Asimov",
|
author = "Asimov",
|
||||||
date = "1951",
|
date = "February 1951",
|
||||||
isNew = false,
|
isNew = false,
|
||||||
cover = "",
|
cover = "",
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package com.pixelized.biblib.ui.screen.home.detail
|
||||||
|
|
||||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||||
import androidx.activity.compose.BackHandler
|
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
|
@ -18,7 +17,6 @@ import androidx.compose.material.icons.filled.Send
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
|
@ -111,10 +109,6 @@ fun DetailScreen(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
BackHandler(enabled = sheet.isVisible) {
|
|
||||||
scope.launch { sheet.hide() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.paging.PagingData
|
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.ui.scaffold.LocalSearchBottomSheetState
|
import com.pixelized.biblib.ui.scaffold.LocalCategorySearchBottomSheetState
|
||||||
import com.pixelized.biblib.ui.scaffold.SearchFilter
|
import com.pixelized.biblib.ui.scaffold.SearchFilter
|
||||||
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
|
||||||
|
|
@ -37,7 +37,7 @@ fun CategorySearchPage(
|
||||||
filter: SearchFilter?,
|
filter: SearchFilter?,
|
||||||
onClose: () -> Unit = default(),
|
onClose: () -> Unit = default(),
|
||||||
) {
|
) {
|
||||||
val bottomSearchState = LocalSearchBottomSheetState.current
|
val bottomSearchState = LocalCategorySearchBottomSheetState.current
|
||||||
|
|
||||||
CategorySearchPageContent(
|
CategorySearchPageContent(
|
||||||
focusRequester = focusRequester,
|
focusRequester = focusRequester,
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,12 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
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.draw.alpha
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
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 androidx.paging.LoadState
|
import androidx.paging.LoadState
|
||||||
|
|
@ -26,8 +29,8 @@ import androidx.paging.PagingData
|
||||||
import androidx.paging.compose.LazyPagingItems
|
import androidx.paging.compose.LazyPagingItems
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import androidx.paging.compose.items
|
import androidx.paging.compose.items
|
||||||
|
import com.pixelized.biblib.ui.scaffold.LocalCategorySearchBottomSheetState
|
||||||
import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState
|
import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState
|
||||||
import com.pixelized.biblib.ui.scaffold.LocalSearchBottomSheetState
|
|
||||||
import com.pixelized.biblib.ui.scaffold.LocalSearchViewModel
|
import com.pixelized.biblib.ui.scaffold.LocalSearchViewModel
|
||||||
import com.pixelized.biblib.ui.scaffold.SearchFilter
|
import com.pixelized.biblib.ui.scaffold.SearchFilter
|
||||||
import com.pixelized.biblib.ui.screen.home.common.item.BookThumbnailUio
|
import com.pixelized.biblib.ui.screen.home.common.item.BookThumbnailUio
|
||||||
|
|
@ -39,11 +42,15 @@ 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
|
||||||
|
|
||||||
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun SearchPage(
|
fun SearchPage(
|
||||||
searchViewModel: SearchViewModel = LocalSearchViewModel.current
|
searchViewModel: SearchViewModel = LocalSearchViewModel.current
|
||||||
) {
|
) {
|
||||||
val bottomSearchState = LocalSearchBottomSheetState.current
|
val keyboard = LocalSoftwareKeyboardController.current
|
||||||
|
val detail = LocalDetailBottomSheetState.current
|
||||||
|
val search = LocalCategorySearchBottomSheetState.current
|
||||||
|
val focus = LocalFocusManager.current
|
||||||
val filters = rememberSearchFilter()
|
val filters = rememberSearchFilter()
|
||||||
|
|
||||||
SearchPageContent(
|
SearchPageContent(
|
||||||
|
|
@ -51,7 +58,12 @@ fun SearchPage(
|
||||||
search = searchViewModel.search,
|
search = searchViewModel.search,
|
||||||
filters = filters,
|
filters = filters,
|
||||||
onFilter = {
|
onFilter = {
|
||||||
bottomSearchState.expandSearch(it)
|
search.expandSearch(it)
|
||||||
|
},
|
||||||
|
onDetail = {
|
||||||
|
focus.clearFocus(force = true)
|
||||||
|
keyboard?.hide()
|
||||||
|
detail.expandBookDetail(id = it.id)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -62,9 +74,9 @@ private fun SearchPageContent(
|
||||||
search: Flow<PagingData<BookThumbnailUio>> = emptyFlow(),
|
search: Flow<PagingData<BookThumbnailUio>> = emptyFlow(),
|
||||||
filters: List<SearchFilter> = SearchFilter.all,
|
filters: List<SearchFilter> = SearchFilter.all,
|
||||||
onFilter: (filter: SearchFilter) -> Unit = default<SearchFilter>(),
|
onFilter: (filter: SearchFilter) -> Unit = default<SearchFilter>(),
|
||||||
|
onDetail: (item: BookThumbnailUio) -> Unit = default<BookThumbnailUio>()
|
||||||
) {
|
) {
|
||||||
val items = search.collectAsLazyPagingItems()
|
val items = search.collectAsLazyPagingItems()
|
||||||
val detail = LocalDetailBottomSheetState.current
|
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
|
@ -82,7 +94,7 @@ private fun SearchPageContent(
|
||||||
SmallBookThumbnail(
|
SmallBookThumbnail(
|
||||||
modifier = Modifier.padding(horizontal = MaterialTheme.bibLib.dimen.thumbnail.padding),
|
modifier = Modifier.padding(horizontal = MaterialTheme.bibLib.dimen.thumbnail.padding),
|
||||||
thumbnail = item,
|
thumbnail = item,
|
||||||
onClick = { item?.let { detail.expandBookDetail(it.id) } }
|
onClick = { onDetail(it) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ val LocalBibLibTheme = compositionLocalOf<BibLibTheme> {
|
||||||
@Stable
|
@Stable
|
||||||
@Immutable
|
@Immutable
|
||||||
data class BibLibTheme(
|
data class BibLibTheme(
|
||||||
val color: BibLibColor,
|
val colors: BibLibColor,
|
||||||
val dimen: BibLibDimen,
|
val dimen: BibLibDimen,
|
||||||
val typography: BibLibTypography,
|
val typography: BibLibTypography,
|
||||||
val shape: BibLibShape,
|
val shapes: BibLibShape,
|
||||||
)
|
)
|
||||||
|
|
@ -16,16 +16,16 @@ fun BibLibTheme(
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
val theme = BibLibTheme(
|
val theme = BibLibTheme(
|
||||||
color = if (darkTheme) bibLibDarkColors() else bibLibLightColors(),
|
colors = if (darkTheme) bibLibDarkColors() else bibLibLightColors(),
|
||||||
dimen = BibLibDimen(),
|
dimen = BibLibDimen(),
|
||||||
typography = BibLibTypography(),
|
typography = BibLibTypography(),
|
||||||
shape = BibLibShape(),
|
shapes = BibLibShape(),
|
||||||
)
|
)
|
||||||
CompositionLocalProvider(LocalBibLibTheme provides theme) {
|
CompositionLocalProvider(LocalBibLibTheme provides theme) {
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colors = theme.color.base,
|
colors = theme.colors.base,
|
||||||
typography = theme.typography.base,
|
typography = theme.typography.base,
|
||||||
shapes = theme.shape.base,
|
shapes = theme.shapes.base,
|
||||||
content = content
|
content = content
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,18 @@ import javax.annotation.concurrent.Immutable
|
||||||
@Immutable
|
@Immutable
|
||||||
data class BibLibColor(
|
data class BibLibColor(
|
||||||
val base: Colors,
|
val base: Colors,
|
||||||
|
val typography: Typography,
|
||||||
val placeHolder: Color,
|
val placeHolder: Color,
|
||||||
)
|
) {
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@Immutable
|
||||||
|
data class Typography(
|
||||||
|
val easy: Color,
|
||||||
|
val medium: Color,
|
||||||
|
val strong: Color,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun bibLibDarkColors(
|
fun bibLibDarkColors(
|
||||||
base: Colors = darkColors(
|
base: Colors = darkColors(
|
||||||
|
|
@ -24,9 +34,16 @@ fun bibLibDarkColors(
|
||||||
error = BibLibColorPalette.Red,
|
error = BibLibColorPalette.Red,
|
||||||
onError = Color.White,
|
onError = Color.White,
|
||||||
),
|
),
|
||||||
|
typography: BibLibColor.Typography = BibLibColor.Typography(
|
||||||
|
easy = base.onSurface.copy(alpha = 0.67f),
|
||||||
|
medium = base.onSurface,
|
||||||
|
strong = base.primary,
|
||||||
|
),
|
||||||
|
placeHolder: Color = BibLibColorPalette.DarkGrey,
|
||||||
) = BibLibColor(
|
) = BibLibColor(
|
||||||
base = base,
|
base = base,
|
||||||
placeHolder = BibLibColorPalette.DarkGrey,
|
typography = typography,
|
||||||
|
placeHolder = placeHolder,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun bibLibLightColors(
|
fun bibLibLightColors(
|
||||||
|
|
@ -37,8 +54,15 @@ fun bibLibLightColors(
|
||||||
onSecondary = Color.White,
|
onSecondary = Color.White,
|
||||||
error = BibLibColorPalette.Red,
|
error = BibLibColorPalette.Red,
|
||||||
onError = Color.White,
|
onError = Color.White,
|
||||||
)
|
),
|
||||||
|
typography: BibLibColor.Typography = BibLibColor.Typography(
|
||||||
|
easy = base.onSurface.copy(alpha = 0.67f),
|
||||||
|
medium = base.onSurface,
|
||||||
|
strong = base.primary,
|
||||||
|
),
|
||||||
|
placeHolder: Color = BibLibColorPalette.LightGrey,
|
||||||
) = BibLibColor(
|
) = BibLibColor(
|
||||||
base = base,
|
base = base,
|
||||||
placeHolder = BibLibColorPalette.LightGrey,
|
typography = typography,
|
||||||
|
placeHolder = placeHolder,
|
||||||
)
|
)
|
||||||
|
|
@ -36,7 +36,6 @@ data class BibLibDimen(
|
||||||
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 = DpSize(width = 72.dp, height = 115.dp), // ratio 1.6
|
||||||
val corner: Dp = 8.dp,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,6 @@ data class BibLibShape(
|
||||||
medium = RoundedCornerShape(4.dp),
|
medium = RoundedCornerShape(4.dp),
|
||||||
large = RoundedCornerShape(0.dp),
|
large = RoundedCornerShape(0.dp),
|
||||||
),
|
),
|
||||||
|
val bookThumbnailCoverSmall: Shape = RoundedCornerShape(4.dp),
|
||||||
|
val bookThumbnailCoverLarge: Shape = RoundedCornerShape(4.dp),
|
||||||
)
|
)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue