Migrate from glide to coil.
This commit is contained in:
parent
ca41948a75
commit
15eb013579
12 changed files with 227 additions and 152 deletions
|
|
@ -128,8 +128,7 @@ dependencies {
|
|||
implementation "com.google.accompanist:accompanist-swiperefresh:0.34.0"
|
||||
|
||||
// Landscapist
|
||||
implementation "com.github.skydoves:landscapist-glide:1.5.2"
|
||||
kapt 'com.github.bumptech.glide:compiler:4.13.2' // this have to be align with landscapist-glide
|
||||
implementation("io.coil-kt:coil-compose:2.6.0")
|
||||
|
||||
// Reorder element in lazylist
|
||||
implementation "org.burnoutcrew.composereorderable:reorderable:0.9.6"
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
package com.pixelized.biblib.module
|
||||
|
||||
import android.content.Context
|
||||
import com.bumptech.glide.GlideBuilder
|
||||
import com.bumptech.glide.annotation.GlideModule
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.module.AppGlideModule
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
|
||||
@GlideModule
|
||||
class AppNameGlideModule : AppGlideModule() {
|
||||
override fun applyOptions(context: Context, builder: GlideBuilder) {
|
||||
super.applyOptions(context, builder)
|
||||
builder.apply {
|
||||
this.setDefaultRequestOptions {
|
||||
RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,17 +3,20 @@ package com.pixelized.biblib.ui
|
|||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.ScaffoldState
|
||||
import androidx.compose.material.Snackbar
|
||||
import androidx.compose.material.SnackbarHost
|
||||
import androidx.compose.material.SnackbarHostState
|
||||
import androidx.compose.material.rememberScaffoldState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.pixelized.biblib.ui.navigation.ScreenNavHost
|
||||
import com.pixelized.biblib.ui.screen.launch.LauncherViewModel
|
||||
import com.skydoves.landscapist.glide.LocalGlideRequestOptions
|
||||
|
||||
val LocalSnackHostState = staticCompositionLocalOf<SnackbarHostState> {
|
||||
error("SnackBarHostState is not ready yet.")
|
||||
|
|
@ -22,12 +25,10 @@ val LocalSnackHostState = staticCompositionLocalOf<SnackbarHostState> {
|
|||
@Composable
|
||||
fun MainContent(
|
||||
launcherViewModel: LauncherViewModel = hiltViewModel(),
|
||||
glideOptions: RequestOptions = RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
) {
|
||||
val scaffoldState: ScaffoldState = rememberScaffoldState()
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalGlideRequestOptions provides glideOptions,
|
||||
LocalSnackHostState provides scaffoldState.snackbarHostState,
|
||||
) {
|
||||
Scaffold(
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
|
|
@ -63,6 +64,7 @@ import androidx.compose.ui.platform.LocalUriHandler
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
|
|
@ -131,17 +133,19 @@ fun AuthenticationScreen(
|
|||
R.drawable.biblib_background_2,
|
||||
R.drawable.biblib_background_3,
|
||||
)
|
||||
mutableStateOf(tmp.random())
|
||||
mutableIntStateOf(tmp.random())
|
||||
}
|
||||
val displayBibLibSignIn = rememberSaveable { mutableStateOf(false) }
|
||||
val blur = remember(displayBibLibSignIn) {
|
||||
derivedStateOf { if (displayBibLibSignIn.value) 8.dp else 0.dp }
|
||||
}
|
||||
val displayBibLibSignIn = remember { mutableStateOf(false) }
|
||||
val blur = remember { derivedStateOf { if (displayBibLibSignIn.value) 8.dp else 0.dp } }
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
AuthenticationScreenContent(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
background = background.value,
|
||||
background = background.intValue,
|
||||
blur = blur,
|
||||
onGoogleSignIn = authenticationViewModel::loginWithGoogle,
|
||||
onBibLibSingIn = { displayBibLibSignIn.value = true },
|
||||
|
|
@ -216,7 +220,7 @@ private fun AuthenticationScreenContent(
|
|||
val colorScheme = MaterialTheme.colors
|
||||
val animatedBlur = animateDpAsState(
|
||||
targetValue = blur.value,
|
||||
// label = "AnimatedContentBlur",
|
||||
label = "AnimatedContentBlur",
|
||||
)
|
||||
|
||||
Column(
|
||||
|
|
@ -231,9 +235,7 @@ private fun AuthenticationScreenContent(
|
|||
.weight(1f),
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.matchParentSize()
|
||||
.background(color = MaterialTheme.colors.surface.copy(alpha = 0.8f)),
|
||||
modifier = Modifier.matchParentSize(),
|
||||
contentScale = ContentScale.FillHeight,
|
||||
painter = painterResource(id = background),
|
||||
contentDescription = null,
|
||||
|
|
@ -282,7 +284,11 @@ private fun AuthenticationScreenContent(
|
|||
colors = ButtonDefaults.textButtonColors(),
|
||||
onClick = onBibLibSingIn,
|
||||
) {
|
||||
Text(text = "Sign in with BibLib account")
|
||||
Text(
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
text = stringResource(id = R.string.authentication_sign_in_with_biblib),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -314,10 +320,10 @@ private fun AuthenticationSignDialog(
|
|||
.background(
|
||||
color = animateColorAsState(
|
||||
targetValue = when (visibility.value) {
|
||||
true -> colorScheme.surface.copy(alpha = 0.3f)
|
||||
true -> colorScheme.surface.copy(alpha = 0.5f)
|
||||
else -> Color.Transparent
|
||||
},
|
||||
// label = "AnimatedSignInScrim"
|
||||
label = "AnimatedSignInScrim"
|
||||
).value
|
||||
),
|
||||
) {
|
||||
|
|
@ -380,9 +386,7 @@ private fun AuthenticationSignDialog(
|
|||
) {
|
||||
TextButton(
|
||||
modifier = Modifier.height(height = 48.dp),
|
||||
colors = ButtonDefaults.textButtonColors(
|
||||
contentColor = MaterialTheme.colors.onSurface
|
||||
),
|
||||
colors = ButtonDefaults.textButtonColors(),
|
||||
onClick = onRegister,
|
||||
) {
|
||||
Text(text = stringResource(id = R.string.action_register))
|
||||
|
|
|
|||
|
|
@ -2,30 +2,66 @@ package com.pixelized.biblib.ui.screen.home
|
|||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.*
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.calculateEndPadding
|
||||
import androidx.compose.foundation.layout.calculateStartPadding
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyGridState
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.SnackbarResult
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextField
|
||||
import androidx.compose.material.TextFieldDefaults
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.pullrefresh.PullRefreshState
|
||||
import androidx.compose.material.pullrefresh.pullRefresh
|
||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.*
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
|
@ -34,6 +70,7 @@ import androidx.compose.ui.unit.max
|
|||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import coil.compose.AsyncImage
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.model.search.FilterType
|
||||
import com.pixelized.biblib.model.search.SortType
|
||||
|
|
@ -41,10 +78,23 @@ import com.pixelized.biblib.model.search.SortValue
|
|||
import com.pixelized.biblib.ui.LocalSnackHostState
|
||||
import com.pixelized.biblib.ui.composable.Loader
|
||||
import com.pixelized.biblib.ui.composable.colorElevation
|
||||
import com.pixelized.biblib.ui.composable.scaffold.*
|
||||
import com.pixelized.biblib.ui.composable.scaffold.DetailBottomSheet
|
||||
import com.pixelized.biblib.ui.composable.scaffold.DetailBottomSheetState
|
||||
import com.pixelized.biblib.ui.composable.scaffold.FilterBottomSheet
|
||||
import com.pixelized.biblib.ui.composable.scaffold.FilterBottomSheetResult
|
||||
import com.pixelized.biblib.ui.composable.scaffold.FilterBottomSheetState
|
||||
import com.pixelized.biblib.ui.composable.scaffold.SortBottomSheet
|
||||
import com.pixelized.biblib.ui.composable.scaffold.SortBottomSheetResult
|
||||
import com.pixelized.biblib.ui.composable.scaffold.SortBottomSheetState
|
||||
import com.pixelized.biblib.ui.composable.scaffold.rememberDetailBottomSheetState
|
||||
import com.pixelized.biblib.ui.composable.scaffold.rememberFilterBottomSheetState
|
||||
import com.pixelized.biblib.ui.composable.scaffold.rememberSortBottomSheetState
|
||||
import com.pixelized.biblib.ui.navigation.LocalScreenNavHostController
|
||||
import com.pixelized.biblib.ui.navigation.navigateToProfile
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.*
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.LargeBookThumbnail
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnail
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.SmallBookThumbnail
|
||||
import com.pixelized.biblib.ui.screen.home.common.preview.thumbnailPreviewResources
|
||||
import com.pixelized.biblib.ui.screen.home.filter.FilterChip
|
||||
import com.pixelized.biblib.ui.screen.home.filter.FilterChipUio
|
||||
|
|
@ -56,7 +106,6 @@ import com.pixelized.biblib.ui.theme.BibLibTheme
|
|||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.pixelized.biblib.utils.extention.imeHeight
|
||||
import com.pixelized.biblib.utils.extention.navigationBarsHeight
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -238,18 +287,22 @@ private fun rememberOnFilter(
|
|||
author = result.filter.filterLabel,
|
||||
authorId = result.filter.filterId,
|
||||
)
|
||||
|
||||
FilterType.Series -> filterBySeries(
|
||||
series = result.filter.filterLabel,
|
||||
seriesId = result.filter.filterId,
|
||||
)
|
||||
|
||||
FilterType.Genre -> filterByGenre(
|
||||
genre = result.filter.filterLabel,
|
||||
genreId = result.filter.filterId,
|
||||
)
|
||||
|
||||
FilterType.Language -> filterByLanguage(
|
||||
language = result.filter.filterLabel,
|
||||
languageId = result.filter.filterId,
|
||||
)
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
|
@ -262,18 +315,22 @@ private fun rememberOnFilter(
|
|||
author = null,
|
||||
authorId = null,
|
||||
)
|
||||
|
||||
FilterType.Series -> filterBySeries(
|
||||
series = null,
|
||||
seriesId = null,
|
||||
)
|
||||
|
||||
FilterType.Genre -> filterByGenre(
|
||||
genre = null,
|
||||
genreId = null,
|
||||
)
|
||||
|
||||
FilterType.Language -> filterByLanguage(
|
||||
language = null,
|
||||
languageId = null,
|
||||
)
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
|
@ -474,14 +531,14 @@ private fun HomeToolbar(
|
|||
onClick = onAvatarTap,
|
||||
) {
|
||||
if (avatar != null) {
|
||||
GlideImage(
|
||||
AsyncImage(
|
||||
modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.size(MaterialTheme.bibLib.dimen.avatar.medium),
|
||||
previewPlaceholder = R.drawable.ic_google,
|
||||
placeHolder = painterResource(id = R.drawable.ic_google),
|
||||
model = avatar,
|
||||
placeholder = painterResource(id = R.drawable.ic_google),
|
||||
contentScale = ContentScale.Fit,
|
||||
imageModel = avatar,
|
||||
contentDescription = null,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
|
|
@ -598,7 +655,7 @@ private fun BookList(
|
|||
@OptIn(ExperimentalMaterialApi::class)
|
||||
private fun rememberPullRefreshState(
|
||||
viewModel: BookSearchViewModel,
|
||||
scope : CoroutineScope = rememberCoroutineScope()
|
||||
scope: CoroutineScope = rememberCoroutineScope()
|
||||
): PullRefreshState {
|
||||
return rememberPullRefreshState(
|
||||
refreshing = viewModel.updating.value,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@ package com.pixelized.biblib.ui.screen.home.common.item
|
|||
import android.annotation.SuppressLint
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -11,17 +15,18 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.AsyncImage
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.pixelized.biblib.utils.extention.modifier.drawDiagonalLabel
|
||||
import com.pixelized.biblib.utils.extention.placeholder
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
|
||||
@Composable
|
||||
fun LargeBookThumbnail(
|
||||
|
|
@ -55,15 +60,17 @@ private fun LargeBookThumbnailContent(
|
|||
thumbnail: BookThumbnailUio,
|
||||
onClick: (BookThumbnailUio) -> Unit,
|
||||
) {
|
||||
GlideImage(
|
||||
AsyncImage(
|
||||
modifier = Modifier
|
||||
.clip(shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge)
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(64f / 102f)
|
||||
.isNew { thumbnail.isNew }
|
||||
.clickable { thumbnail.let(onClick) },
|
||||
previewPlaceholder = R.drawable.ic_fondatoin_cover,
|
||||
imageModel = thumbnail.cover,
|
||||
.clickable { thumbnail.let(onClick) }
|
||||
.then(other = modifier),
|
||||
model = thumbnail.cover,
|
||||
contentScale = ContentScale.Crop,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -79,6 +86,7 @@ private fun LargeBookThumbnailPlaceHolder(
|
|||
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge,
|
||||
visible = { true }
|
||||
)
|
||||
.then(other = modifier)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
|
|
@ -24,12 +25,12 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.compose.ui.unit.sp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import coil.compose.AsyncImage
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.pixelized.biblib.utils.extention.modifier.drawDiagonalLabel
|
||||
import com.pixelized.biblib.utils.extention.placeholder
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
|
||||
@Composable
|
||||
fun MicroBookThumbnail(
|
||||
|
|
@ -68,7 +69,7 @@ private fun MicroBookThumbnailContent(
|
|||
) {
|
||||
val (cover, title, author, series) = createRefs()
|
||||
|
||||
GlideImage(
|
||||
AsyncImage(
|
||||
modifier = Modifier
|
||||
.constrainAs(cover) {
|
||||
top.linkTo(parent.top)
|
||||
|
|
@ -78,8 +79,9 @@ private fun MicroBookThumbnailContent(
|
|||
.clip(shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall)
|
||||
.size(size = MaterialTheme.bibLib.dimen.thumbnail.micro)
|
||||
.isNew { thumbnail.isNew },
|
||||
previewPlaceholder = R.drawable.ic_fondation_thumbnail,
|
||||
imageModel = thumbnail.thumbnail,
|
||||
model = thumbnail.thumbnail,
|
||||
contentScale = ContentScale.Crop,
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ package com.pixelized.biblib.ui.screen.home.common.item
|
|||
import android.annotation.SuppressLint
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
|
|
@ -12,6 +15,7 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
|
|
@ -20,12 +24,12 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import coil.compose.AsyncImage
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.pixelized.biblib.utils.extention.modifier.drawDiagonalLabel
|
||||
import com.pixelized.biblib.utils.extention.placeholder
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
|
||||
@Composable
|
||||
fun SmallBookThumbnail(
|
||||
|
|
@ -64,7 +68,7 @@ private fun SmallBookThumbnailContent(
|
|||
) {
|
||||
val (cover, title, author, series, genre, date) = createRefs()
|
||||
|
||||
GlideImage(
|
||||
AsyncImage(
|
||||
modifier = Modifier
|
||||
.constrainAs(cover) {
|
||||
top.linkTo(parent.top)
|
||||
|
|
@ -74,8 +78,9 @@ private fun SmallBookThumbnailContent(
|
|||
.clip(shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall)
|
||||
.size(size = MaterialTheme.bibLib.dimen.thumbnail.cover)
|
||||
.isNew { thumbnail.isNew },
|
||||
previewPlaceholder = R.drawable.ic_fondation_thumbnail,
|
||||
imageModel = thumbnail.thumbnail,
|
||||
model = thumbnail.thumbnail,
|
||||
contentScale = ContentScale.Crop,
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -2,12 +2,25 @@ 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_YES
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Button
|
||||
|
|
@ -15,12 +28,18 @@ 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.Send
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.material.icons.automirrored.filled.Send
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
|
@ -31,20 +50,17 @@ import androidx.compose.ui.unit.Dp
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.core.text.toSpannable
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.engine.GlideException
|
||||
import com.bumptech.glide.request.RequestListener
|
||||
import com.bumptech.glide.request.target.Target
|
||||
import coil.compose.AsyncImagePainter
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import coil.request.ImageRequest
|
||||
import coil.size.Dimension
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.composable.Handle
|
||||
import com.pixelized.biblib.ui.composable.SpannedText
|
||||
import com.pixelized.biblib.ui.composable.animation.AnimatedDelayer
|
||||
import com.pixelized.biblib.ui.composable.animation.AnimatedOffset
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.pixelized.biblib.utils.extention.placeholder
|
||||
import com.skydoves.landscapist.CircularReveal
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
import java.io.Serializable
|
||||
|
||||
@Stable
|
||||
|
|
@ -243,7 +259,7 @@ fun DetailScreenContent(
|
|||
Button(
|
||||
onClick = onSend,
|
||||
) {
|
||||
Icon(imageVector = Icons.Default.Send, contentDescription = "")
|
||||
Icon(imageVector = Icons.AutoMirrored.Filled.Send, contentDescription = "")
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(text = stringResource(id = R.string.action_send))
|
||||
}
|
||||
|
|
@ -257,43 +273,75 @@ private fun Cover(
|
|||
modifier: Modifier = Modifier,
|
||||
cover: String,
|
||||
) {
|
||||
val placeholder = remember(cover) { mutableStateOf(true) }
|
||||
val error = remember(cover) { mutableStateOf(false) }
|
||||
|
||||
Box(
|
||||
modifier = modifier,
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
GlideImage(
|
||||
requestListener = rememberRequestListener(
|
||||
placeholder = placeholder,
|
||||
error = error,
|
||||
),
|
||||
previewPlaceholder = R.drawable.ic_fondatoin_cover,
|
||||
circularReveal = CircularReveal(duration = 500),
|
||||
contentScale = ContentScale.FillHeight,
|
||||
imageModel = cover,
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(MaterialTheme.bibLib.dimen.detail.cover)
|
||||
.aspectRatio(ratio = remember { 1f / 1.5f })
|
||||
.placeholder(
|
||||
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge,
|
||||
isShimmering = { error.value.not() },
|
||||
visible = { placeholder.value },
|
||||
)
|
||||
)
|
||||
AnimatedVisibility(
|
||||
visible = error.value,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(64.dp),
|
||||
painter = painterResource(id = R.drawable.ic_no_photography_24),
|
||||
contentDescription = null
|
||||
val painter = rememberAsyncImagePainter(
|
||||
model = ImageRequest.Builder(LocalContext.current)
|
||||
.data(data = cover)
|
||||
.size(
|
||||
width = Dimension.Undefined,
|
||||
height = Dimension.Pixels(
|
||||
px = with(LocalDensity.current) {
|
||||
MaterialTheme.bibLib.dimen.detail.cover.roundToPx()
|
||||
},
|
||||
),
|
||||
)
|
||||
.build()
|
||||
)
|
||||
|
||||
AnimatedContent(
|
||||
targetState = painter.state,
|
||||
label = "Cover image animation",
|
||||
transitionSpec = { fadeIn() togetherWith fadeOut() }
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier,
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
when (it) {
|
||||
AsyncImagePainter.State.Empty -> {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(MaterialTheme.bibLib.dimen.detail.cover)
|
||||
.aspectRatio(ratio = remember { 1f / 1.5f })
|
||||
)
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Error -> {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(MaterialTheme.bibLib.dimen.detail.cover)
|
||||
.aspectRatio(ratio = remember { 1f / 1.5f }),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(64.dp),
|
||||
painter = painterResource(id = R.drawable.ic_no_photography_24),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Loading -> {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(MaterialTheme.bibLib.dimen.detail.cover)
|
||||
.aspectRatio(ratio = remember { 1f / 1.5f })
|
||||
.placeholder(
|
||||
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge,
|
||||
isShimmering = { painter.state is AsyncImagePainter.State.Loading },
|
||||
visible = { true },
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Success -> {
|
||||
Image(
|
||||
modifier = Modifier.height(MaterialTheme.bibLib.dimen.detail.cover),
|
||||
painter = painter,
|
||||
contentScale = ContentScale.FillHeight,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -327,37 +375,6 @@ private fun TitleLabel(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberRequestListener(
|
||||
placeholder: MutableState<Boolean>,
|
||||
error: MutableState<Boolean>,
|
||||
): RequestListener<Drawable> {
|
||||
return remember(placeholder, error) {
|
||||
object : RequestListener<Drawable> {
|
||||
override fun onLoadFailed(
|
||||
exception: GlideException?,
|
||||
model: Any?,
|
||||
target: Target<Drawable>?,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
error.value = true
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onResourceReady(
|
||||
resource: Drawable?,
|
||||
model: Any?,
|
||||
target: Target<Drawable>?,
|
||||
dataSource: DataSource?,
|
||||
isFirstResource: Boolean
|
||||
): Boolean {
|
||||
placeholder.value = false
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO, heightDp = 1000)
|
||||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES, heightDp = 1000)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ fun Modifier.drawDiagonalLabel(
|
|||
val textWidth = textSize.width
|
||||
val textHeight = textSize.height
|
||||
|
||||
val rectWidth = textWidth * labelTextRatio * 1.1f
|
||||
val rectWidth = textWidth * labelTextRatio * 1.5f
|
||||
|
||||
val rect = Rect(
|
||||
offset = Offset(canvasWidth - rectWidth, 0f),
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
<string name="authentication_login">Alias du compte</string>
|
||||
<string name="authentication_password">Mot de passe</string>
|
||||
<string name="authentication_credential_remember">Mémoriser mes identifiants</string>
|
||||
<string name="authentication_sign_in_with_biblib">Authentifiez-vous avec votre compte BibLib</string>
|
||||
|
||||
<string name="detail_open_on_biblib">ouvrir sur bib.bibulle.fr</string>
|
||||
<string name="detail_rating">Note</string>
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
<string name="authentication_login">Login</string>
|
||||
<string name="authentication_password">Password</string>
|
||||
<string name="authentication_credential_remember">Remember my credential</string>
|
||||
<string name="authentication_sign_in_with_biblib">Sign in with your BibLib account</string>
|
||||
|
||||
<string name="list_is_new" translatable="false">New</string>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue