Fix somes loading bugs. introduce Glide.

This commit is contained in:
Thomas Andres Gomez 2022-07-04 16:51:17 +02:00
parent 142957d490
commit 6aca43bc5f
35 changed files with 219 additions and 565 deletions

View file

@ -18,6 +18,7 @@
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:windowSoftInputMode="adjustResize"
android:theme="@style/Theme.BibLib.Starting">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View file

@ -1,7 +1,17 @@
package com.pixelized.biblib
import android.app.Application
import android.os.StrictMode
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class BibLibApplication : Application()
class BibLibApplication : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictMode.enableDefaults()
}
}
}

View file

@ -4,8 +4,6 @@ import android.content.Context
import android.content.SharedPreferences
import androidx.room.Room
import com.pixelized.biblib.database.BibLibDatabase
import com.pixelized.biblib.utils.cache.BookCoverCache
import com.pixelized.biblib.utils.cache.ImageCache
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -30,26 +28,6 @@ class PersistenceModule {
return builder.fallbackToDestructiveMigration().build()
}
@Provides
@Singleton
fun provideBookCoverCache(
imageCache: ImageCache,
): BookCoverCache {
return BookCoverCache(
cache = imageCache
)
}
@Provides
@Singleton
fun provideImageCache(
@ApplicationContext context: Context,
): ImageCache {
return ImageCache(
context = context
)
}
@Provides
@Singleton
fun providePreferences(

View file

@ -7,9 +7,9 @@ import androidx.activity.viewModels
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.ui.graphics.Color
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import com.google.accompanist.insets.ProvideWindowInsets
import com.google.accompanist.systemuicontroller.SystemUiController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.pixelized.biblib.ui.composable.SystemThemeColor
@ -40,16 +40,8 @@ class MainActivity : ComponentActivity() {
// Compose
setContent {
BibLibTheme {
ProvideWindowInsets {
SystemThemeColor {
Surface(color = MaterialTheme.colors.background) {
// Handle the system colors
val systemUiController: SystemUiController = rememberSystemUiController()
SystemThemeColor(
systemUiController = systemUiController,
statusDarkIcons = isSystemInDarkTheme().not(),
navigationDarkIcons = isSystemInDarkTheme().not(),
)
// Handle the main Navigation
if (launcherViewModel.isLoading.not()) {
ScreenNavHost(

View file

@ -1,21 +0,0 @@
package com.pixelized.biblib.ui.composable
import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
@Composable
fun Cover(
modifier: Modifier = Modifier,
cover: CoverUio,
contentDescription: String? = null,
) {
Image(
modifier = modifier,
painter = cover.painter,
contentScale = cover.contentScale,
colorFilter = cover.colorFilter,
contentDescription = contentDescription,
)
}

View file

@ -18,6 +18,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@ -26,16 +27,17 @@ import com.pixelized.biblib.ui.scaffold.SearchScaffoldState
import com.pixelized.biblib.ui.scaffold.rememberSearchScaffoldState
import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.utils.extention.bibLib
import com.pixelized.biblib.utils.extention.todo
import com.pixelized.biblib.utils.extention.default
import com.skydoves.landscapist.glide.GlideImage
@Composable
fun Search(
modifier: Modifier = Modifier,
state: SearchScaffoldState = rememberSearchScaffoldState(),
avatar: Painter,
onAvatar: () -> Unit = todo(),
onSearch: () -> Unit = todo(),
avatar: String?,
onAvatar: () -> Unit = default(),
onSearch: () -> Unit = default(),
) {
val horizontalPadding by animateDpAsState(
targetValue = when (state.isCollapsed()) {
@ -77,24 +79,36 @@ fun Search(
),
onValueChange = { search = it }
)
IconButton(
modifier = Modifier.padding(end = horizontalPadding),
onClick = onAvatar,
) {
Image(
modifier = Modifier.clip(CircleShape),
painter = avatar,
contentDescription = null
)
avatar?.let {
IconButton(
modifier = Modifier.padding(end = horizontalPadding),
onClick = onAvatar,
) {
GlideImage(
modifier = Modifier.clip(CircleShape).size(32.dp),
previewPlaceholder = R.drawable.ic_google,
contentScale = ContentScale.Fit,
imageModel = it,
)
}
}
}
}
@Composable
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO)
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
private fun SearchContentEmptyPreview() {
BibLibTheme {
Search(avatar = null)
}
}
@Composable
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO)
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
private fun SearchContentPreview() {
BibLibTheme {
Search(avatar = painterResource(R.drawable.ic_google))
Search(avatar = "")
}
}

View file

@ -1,24 +1,35 @@
package com.pixelized.biblib.ui.composable
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.graphics.Color
import com.google.accompanist.systemuicontroller.SystemUiController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
val LocalSystemUiController = compositionLocalOf<SystemUiController> { error("") }
@Composable
fun SystemThemeColor(
systemUiController: SystemUiController,
color: Color = Color.Transparent,
statusDarkIcons: Boolean,
navigationDarkIcons: Boolean,
) = SideEffect {
systemUiController.setStatusBarColor(
color = color,
darkIcons = statusDarkIcons,
)
systemUiController.setNavigationBarColor(
color = color,
darkIcons = navigationDarkIcons,
navigationBarContrastEnforced = false,
)
systemUiController: SystemUiController = rememberSystemUiController(),
color: Color = Color.Black.copy(alpha = 0.3f),
statusDarkIcons: Boolean = false,
navigationDarkIcons: Boolean = false,
content: @Composable () -> Unit,
) {
CompositionLocalProvider(LocalSystemUiController provides systemUiController) {
SideEffect {
systemUiController.setStatusBarColor(
color = color,
darkIcons = statusDarkIcons,
)
systemUiController.setNavigationBarColor(
color = color,
darkIcons = navigationDarkIcons,
navigationBarContrastEnforced = false,
)
}
content()
}
}

View file

@ -5,7 +5,7 @@ import androidx.compose.runtime.Composable
@Composable
fun AnimatedDelayer(
delay: Int = 0,
delay: Int = Delay.DELTA,
content: @Composable AnimatedDelayerScope.() -> Unit
) {
val scope = AnimatedDelayerScope(
@ -18,7 +18,7 @@ fun AnimatedDelayer(
@Composable
fun <T> AnimatedDelayer(
targetState: T,
delay: Int = 0,
delay: Int = Delay.DELTA,
content: @Composable AnimatedDelayerScope.(T) -> Unit
) {
AnimatedContent(
@ -46,6 +46,6 @@ value class Delay(
}
companion object {
private const val DELTA = 100
const val DELTA = 100
}
}

View file

@ -24,7 +24,7 @@ fun SearchScaffold(
search: @Composable () -> Unit,
content: @Composable () -> Unit,
) {
var initialHeight by remember { mutableStateOf(0) }
var initialCardBoxHeight by remember { mutableStateOf(0) }
Layout(
modifier = modifier,
content = {
@ -68,13 +68,15 @@ fun SearchScaffold(
}
) { measurables, constraints ->
val cardBox = measurables.first { it.layoutId == "cardBox" }.measure(constraints)
val contentBox = measurables.first { it.layoutId == "contentBox" }.measure(constraints)
val contentBox = measurables.first { it.layoutId == "contentBox" }.measure(constraints.copy(
maxHeight = constraints.maxHeight - initialCardBoxHeight
))
layout(constraints.maxWidth, constraints.maxHeight) {
if (initialHeight == 0) {
initialHeight = cardBox.measuredHeight
if (initialCardBoxHeight == 0) {
initialCardBoxHeight = cardBox.measuredHeight
}
contentBox.place(x = 0, y = initialHeight)
contentBox.place(x = 0, y = initialCardBoxHeight)
cardBox.place(x = 0, y = 0)
}
}

View file

@ -29,7 +29,6 @@ import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.google.accompanist.insets.systemBarsPadding
import com.pixelized.biblib.R
import com.pixelized.biblib.network.client.IBibLibClient
import com.pixelized.biblib.ui.composable.StateUio
@ -52,6 +51,7 @@ fun AuthenticationScreen(
val navHostController = LocalScreenNavHostController.current
AuthenticationScreenContent(
modifier = Modifier.systemBarsPadding(),
login = formViewModel.form.login,
password = formViewModel.form.password,
rememberPassword = formViewModel.form.remember,
@ -90,6 +90,7 @@ fun AuthenticationScreen(
@Composable
private fun AuthenticationScreenContent(
modifier: Modifier = Modifier,
login: String,
onLoginChange: (String) -> Unit,
password: String,
@ -105,10 +106,9 @@ private fun AuthenticationScreenContent(
AnimatedDelayer {
Column(
modifier = Modifier
modifier = modifier
.fillMaxSize()
.verticalScroll(scrollState)
.systemBarsPadding()
) {
Spacer(modifier = Modifier.weight(1f))

View file

@ -1,34 +1,23 @@
package com.pixelized.biblib.ui.screen.detail
import android.app.Application
import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.ui.layout.ContentScale
import com.pixelized.biblib.R
import androidx.lifecycle.ViewModel
import com.pixelized.biblib.model.book.Book
import com.pixelized.biblib.network.client.IBibLibClient
import com.pixelized.biblib.network.factory.BookFactory
import com.pixelized.biblib.ui.composable.StateUio
import com.pixelized.biblib.ui.screen.home.common.uio.BookUio
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
import com.pixelized.biblib.ui.screen.home.common.viewModel.ACoverViewModel
import com.pixelized.biblib.utils.cache.BookCoverCache
import com.pixelized.biblib.utils.extention.capitalize
import com.pixelized.biblib.utils.extention.context
import com.pixelized.biblib.utils.extention.shortDate
import com.pixelized.biblib.utils.painterResource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.net.URL
import javax.inject.Inject
@HiltViewModel
class BookDetailViewModel @Inject constructor(
application: Application,
bookCoverCache: BookCoverCache,
private val client: IBibLibClient,
) : ACoverViewModel(application, bookCoverCache) {
) : ViewModel() {
suspend fun getDetail(id: Int): StateUio<BookUio> {
return withContext(Dispatchers.IO) {
@ -50,16 +39,7 @@ class BookDetailViewModel @Inject constructor(
}
private fun Book.toUio(): BookUio {
val thumbnailCover by cover(
placeHolder = CoverUio(
type = CoverUio.Type.PLACE_HOLDER,
contentScale = ContentScale.FillBounds,
painter = painterResource(context, R.drawable.ic_baseline_auto_stories_24),
),
type = CoverUio.Type.THUMBNAIL,
contentScale = ContentScale.FillHeight,
url = URL("${IBibLibClient.THUMBNAIL_URL}/$id.jpg"),
)
return BookUio(
id = id,
title = title,
@ -69,12 +49,7 @@ class BookDetailViewModel @Inject constructor(
date = releaseDate.shortDate(),
series = series?.name,
description = synopsis ?: "",
coverState = cover(
placeHolder = thumbnailCover,
type = CoverUio.Type.DETAIL,
contentScale = ContentScale.FillHeight,
url = URL("${IBibLibClient.COVER_URL}/$id.jpg"),
)
cover = "${IBibLibClient.COVER_URL}/$id.jpg",
)
}
}

View file

@ -18,7 +18,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
@ -28,7 +27,6 @@ import androidx.core.text.HtmlCompat
import androidx.core.text.toSpannable
import androidx.hilt.navigation.compose.hiltViewModel
import com.pixelized.biblib.R
import com.pixelized.biblib.ui.composable.Cover
import com.pixelized.biblib.ui.composable.SpannedText
import com.pixelized.biblib.ui.composable.StateUio
import com.pixelized.biblib.ui.composable.animation.AnimatedDelayer
@ -37,12 +35,13 @@ import com.pixelized.biblib.ui.composable.isSuccessful
import com.pixelized.biblib.ui.scaffold.BottomDetailState
import com.pixelized.biblib.ui.scaffold.LocalBottomDetailState
import com.pixelized.biblib.ui.screen.home.common.uio.BookUio
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
import com.pixelized.biblib.ui.screen.profile.ProfileViewModel
import com.pixelized.biblib.ui.screen.profile.UserUio
import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.utils.extention.bibLib
import com.pixelized.biblib.utils.extention.todo
import com.pixelized.biblib.utils.extention.default
import com.skydoves.landscapist.CircularReveal
import com.skydoves.landscapist.glide.GlideImage
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class)
@ -103,9 +102,9 @@ fun DetailScreen(
private fun DetailScreenContent(
modifier: Modifier = Modifier,
book: BookUio,
onMobi: () -> Unit = todo(),
onEpub: () -> Unit = todo(),
onSend: () -> Unit = todo(),
onMobi: () -> Unit = default(),
onEpub: () -> Unit = default(),
onSend: () -> Unit = default(),
) {
AnimatedDelayer(
targetState = book,
@ -117,23 +116,16 @@ private fun DetailScreenContent(
.padding(all = MaterialTheme.bibLib.dimen.dp16)
.then(modifier)
) {
AnimatedOffset(
GlideImage(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = MaterialTheme.bibLib.dimen.dp16)
.height(MaterialTheme.bibLib.dimen.detail.cover),
contentAlignment = Alignment.Center
) {
val sizeModifier = if (book.cover.type == CoverUio.Type.PLACE_HOLDER) {
Modifier.size(MaterialTheme.bibLib.dimen.detail.placeHolder)
} else {
Modifier.fillMaxSize()
}
Cover(
modifier = sizeModifier,
cover = book.cover,
)
}
previewPlaceholder = R.drawable.ic_launcher_foreground,
circularReveal = CircularReveal(duration = 1000),
contentScale = ContentScale.FillHeight,
imageModel = book.cover,
)
Row(modifier = Modifier.padding(vertical = MaterialTheme.bibLib.dimen.dp16)) {
AnimatedOffset(
@ -318,16 +310,6 @@ private fun DetailScreenSendContent(
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO)
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
private fun DetailScreenContentPreview() {
val painter = painterResource(id = R.drawable.ic_baseline_auto_stories_24)
val cover = remember {
mutableStateOf(
CoverUio(
type = CoverUio.Type.PLACE_HOLDER,
contentScale = ContentScale.FillBounds,
painter = painter,
)
)
}
val book = BookUio(
id = 90,
title = "Foundation",
@ -337,7 +319,7 @@ private fun DetailScreenContentPreview() {
description = "En ce début de treizième millénaire, l'Empire n'a jamais été aussi puissant, aussi étendu à travers toute la galaxie. C'est dans sa capitale, Trantor, que l'éminent savant Hari Seldon invente la psychohistoire, une science nouvelle permettant de prédire l'avenir. Grâce à elle, Seldon prévoit l'effondrement de l'Empire d'ici cinq siècles, suivi d'une ère de ténèbres de trente mille ans. Réduire cette période à mille ans est peut-être possible, à condition de mener à terme son projet : la Fondation, chargée de rassembler toutes les connaissances humaines. Une entreprise visionnaire qui rencontre de nombreux et puissants détracteurs...",
rating = 4.5f,
language = "Français",
coverState = cover,
cover = "",
)
BibLibTheme {
DetailScreenContent(book = book)

View file

@ -44,10 +44,8 @@ fun HomeScreen(
BottomDetailScaffold {
SearchScaffold(
modifier = Modifier.statusBarsPadding(),
state = searchScaffoldState,
modifier = Modifier
.systemBarsPadding()
.clipToBounds(),
topBar = {
Search(
state = searchScaffoldState,
@ -98,7 +96,7 @@ fun HomeScreenContent(
val scope: CoroutineScope = rememberCoroutineScope()
val pagerState: PagerState = rememberPagerState()
Column(modifier = Modifier.navigationBarsPadding()) {
Column {
ScrollableTabRow(
selectedTabIndex = pagerState.currentPage,
edgePadding = MaterialTheme.bibLib.dimen.dp16,
@ -112,15 +110,16 @@ fun HomeScreenContent(
}
}
HorizontalPager(
modifier = Modifier.fillMaxSize(),
state = pagerState,
count = pages.size
) {
when (pages[it]) {
is Page.News -> NewsPage()
is Page.Books -> BooksPage()
is Page.Author -> Box(modifier = Modifier.fillMaxSize())
is Page.Series -> Box(modifier = Modifier.fillMaxSize())
is Page.Tag -> Box(modifier = Modifier.fillMaxSize())
is Page.Author -> Box(modifier = Modifier)
is Page.Series -> Box(modifier = Modifier)
is Page.Tag -> Box(modifier = Modifier)
}
}
}

View file

@ -1,47 +1,15 @@
package com.pixelized.biblib.ui.screen.home
import android.app.Application
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.layout.ContentScale
import com.pixelized.biblib.R
import androidx.lifecycle.ViewModel
import com.pixelized.biblib.repository.googleSignIn.IGoogleSingInRepository
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
import com.pixelized.biblib.ui.screen.home.common.viewModel.ACoverViewModel
import com.pixelized.biblib.utils.cache.BookCoverCache
import com.pixelized.biblib.utils.extention.context
import com.pixelized.biblib.utils.painterResource
import dagger.hilt.android.lifecycle.HiltViewModel
import java.net.URL
import javax.inject.Inject
@HiltViewModel
class HomeViewModel @Inject constructor(
application: Application,
cacheBook: BookCoverCache,
private val account: IGoogleSingInRepository,
) : ACoverViewModel(application, cacheBook) {
private val _avatar = mutableStateOf(
painterResource(context, R.drawable.ic_launcher_foreground)
)
val avatar by _avatar
init {
updateAvatar()
}
private fun updateAvatar() {
account.account?.photoUrl?.let {
_avatar.value = cover(
placeHolder = CoverUio(
type = CoverUio.Type.PLACE_HOLDER,
painter = painterResource(context, R.drawable.ic_launcher_foreground),
),
type = CoverUio.Type.DETAIL,
contentScale = ContentScale.None,
url = URL("$it"),
).value.painter
}
}
account: IGoogleSingInRepository,
) : ViewModel() {
val avatar by mutableStateOf(account.account?.photoUrl?.toString())
}

View file

@ -1,26 +1,15 @@
package com.pixelized.biblib.ui.screen.home.common.composable
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.paging.PagingData
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import com.pixelized.biblib.R
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
import kotlinx.coroutines.flow.flowOf
@Composable
fun bookPreviewResources(): LazyPagingItems<BookThumbnailUio> {
val cover = CoverUio(
type = CoverUio.Type.PLACE_HOLDER,
painter = painterResource(id = R.drawable.ic_baseline_auto_stories_24),
contentScale = ContentScale.None,
)
val thumbnails = listOf(
BookThumbnailUio(
id = 112,
@ -29,7 +18,7 @@ fun bookPreviewResources(): LazyPagingItems<BookThumbnailUio> {
date = "1988",
genre = "Sci-Fi",
isNew = false,
cover = remember { mutableStateOf(cover) },
cover = "",
),
BookThumbnailUio(
id = 78,
@ -38,7 +27,7 @@ fun bookPreviewResources(): LazyPagingItems<BookThumbnailUio> {
date = "1993",
genre = "Sci-Fi",
isNew = false,
cover = remember { mutableStateOf(cover) },
cover = "",
),
BookThumbnailUio(
id = 90,
@ -47,7 +36,7 @@ fun bookPreviewResources(): LazyPagingItems<BookThumbnailUio> {
date = "1951",
genre = "Sci-Fi",
isNew = false,
cover = remember { mutableStateOf(cover) },
cover = "",
),
BookThumbnailUio(
id = 184,
@ -56,7 +45,7 @@ fun bookPreviewResources(): LazyPagingItems<BookThumbnailUio> {
date = "1952",
genre = "Sci-Fi",
isNew = false,
cover = remember { mutableStateOf(cover) },
cover = "",
),
BookThumbnailUio(
id = 185,
@ -65,7 +54,7 @@ fun bookPreviewResources(): LazyPagingItems<BookThumbnailUio> {
date = "1953",
genre = "Sci-Fi",
isNew = false,
cover = remember { mutableStateOf(cover) },
cover = "",
),
BookThumbnailUio(
id = 119,
@ -74,7 +63,7 @@ fun bookPreviewResources(): LazyPagingItems<BookThumbnailUio> {
date = "1982",
genre = "Sci-Fi",
isNew = false,
cover = remember { mutableStateOf(cover) },
cover = "",
),
BookThumbnailUio(
id = 163,
@ -83,7 +72,7 @@ fun bookPreviewResources(): LazyPagingItems<BookThumbnailUio> {
date = "1986",
genre = "Sci-Fi",
isNew = false,
cover = remember { mutableStateOf(cover) },
cover = "",
),
)
return flowOf(PagingData.from(thumbnails)).collectAsLazyPagingItems()

View file

@ -1,7 +1,5 @@
package com.pixelized.biblib.ui.screen.home.common.uio
import androidx.compose.runtime.State
class BookThumbnailUio(
val id: Int,
val genre: String,
@ -9,5 +7,5 @@ class BookThumbnailUio(
val author: String,
val date: String?,
val isNew: Boolean,
val cover: State<CoverUio>,
val cover: String,
)

View file

@ -1,8 +1,5 @@
package com.pixelized.biblib.ui.screen.home.common.uio
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
data class BookUio(
val id: Int,
val title: String,
@ -12,7 +9,5 @@ data class BookUio(
val date: String?,
val series: String?,
val description: String,
private val coverState: State<CoverUio>,
) {
val cover by coverState
}
val cover: String,
)

View file

@ -1,22 +0,0 @@
package com.pixelized.biblib.ui.screen.home.common.uio
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
@Stable
@Immutable
data class CoverUio(
val type: Type,
val contentScale: ContentScale = ContentScale.FillBounds,
val colorFilter: ColorFilter? = null,
val painter: Painter,
) {
enum class Type {
PLACE_HOLDER,
THUMBNAIL,
DETAIL,
}
}

View file

@ -1,39 +0,0 @@
package com.pixelized.biblib.ui.screen.home.common.viewModel
import android.app.Application
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.layout.ContentScale
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
import com.pixelized.biblib.utils.cache.BookCoverCache
import kotlinx.coroutines.CoroutineScope
import java.net.URL
abstract class ACoverViewModel(
application: Application,
private val cacheBook: BookCoverCache,
) : AndroidViewModel(application) {
fun cover(
cacheBook: BookCoverCache = this.cacheBook,
coroutineScope: CoroutineScope = viewModelScope,
placeHolder: CoverUio,
type: CoverUio.Type,
contentScale: ContentScale = ContentScale.FillBounds,
tint: ColorFilter? = null,
url: URL,
) = cacheBook.cover(
placeHolder = placeHolder,
coroutineScope = coroutineScope,
type = type,
contentScale = contentScale,
tint = tint,
url = url,
)
companion object {
const val PAGING_SIZE = 30
}
}

View file

@ -8,18 +8,18 @@ import androidx.compose.foundation.layout.*
import androidx.compose.material.Card
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import com.pixelized.biblib.R
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.utils.extention.bibLib
import com.skydoves.landscapist.glide.GlideImage
@Composable
fun BookThumbnail(
@ -40,9 +40,10 @@ fun BookThumbnail(
verticalAlignment = Alignment.CenterVertically,
) {
thumbnail?.cover?.let { it ->
Cover(
GlideImage(
modifier = Modifier.size(MaterialTheme.bibLib.dimen.thumbnail.cover),
image = it,
previewPlaceholder = R.drawable.ic_launcher_foreground,
imageModel = it,
)
}
Column(
@ -51,16 +52,19 @@ fun BookThumbnail(
.padding(MaterialTheme.bibLib.dimen.dp8)
) {
Text(
style = MaterialTheme.typography.body1,
modifier = Modifier.padding(bottom = MaterialTheme.bibLib.dimen.dp4),
style = MaterialTheme.typography.h6,
color = MaterialTheme.colors.onSurface,
text = thumbnail?.title ?: "",
maxLines = 1,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
)
Text(
style = MaterialTheme.typography.caption,
style = MaterialTheme.typography.body1,
color = MaterialTheme.colors.onSurface,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
text = thumbnail?.author ?: ""
)
@ -86,33 +90,10 @@ fun BookThumbnail(
}
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun Cover(
modifier: Modifier = Modifier,
image: State<CoverUio>
) {
val cover by image
AnimatedContent(
targetState = cover.painter,
transitionSpec = { fadeIn() with fadeOut() }
) {
Image(
modifier = modifier,
alignment = Alignment.Center,
contentScale = cover.contentScale,
colorFilter = cover.colorFilter,
painter = cover.painter,
contentDescription = null,
)
}
}
@Composable
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun BookThumbnailPreview() {
val painter = painterResource(id = R.drawable.ic_baseline_auto_stories_24)
val thumbnail = BookThumbnailUio(
id = 0,
genre = "Sci-Fi",
@ -120,15 +101,7 @@ private fun BookThumbnailPreview() {
author = "Asimov",
date = "1951",
isNew = false,
cover = remember {
mutableStateOf(
CoverUio(
type = CoverUio.Type.PLACE_HOLDER,
contentScale = ContentScale.None,
painter = painter,
)
)
},
cover = "",
)
BibLibTheme {
BookThumbnail(thumbnail = thumbnail)

View file

@ -1,6 +1,5 @@
package com.pixelized.biblib.ui.screen.home.page.books
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
@ -23,6 +22,7 @@ import com.pixelized.biblib.ui.screen.home.common.composable.bookPreviewResource
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.utils.extention.bibLib
import com.pixelized.biblib.utils.extention.navigationBarsHeight
@Composable
@ -38,7 +38,6 @@ fun BooksPage(
)
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun BooksPageContent(
isNetworkAvailable: () -> State<Boolean>,
@ -51,7 +50,10 @@ private fun BooksPageContent(
isNetworkAvailable = isNetworkAvailable,
)
LazyColumn(
contentPadding = PaddingValues(vertical = MaterialTheme.bibLib.dimen.thumbnail.padding),
contentPadding = PaddingValues(
top = MaterialTheme.bibLib.dimen.thumbnail.padding,
bottom = MaterialTheme.bibLib.dimen.thumbnail.padding + navigationBarsHeight(),
),
verticalArrangement = Arrangement.spacedBy(MaterialTheme.bibLib.dimen.thumbnail.arrangement),
) {
items(

View file

@ -1,34 +1,24 @@
package com.pixelized.biblib.ui.screen.home.page.books
import android.app.Application
import androidx.compose.runtime.Composable
import androidx.compose.ui.layout.ContentScale
import androidx.lifecycle.ViewModel
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.compose.collectAsLazyPagingItems
import com.pixelized.biblib.R
import com.pixelized.biblib.model.book.Book
import com.pixelized.biblib.network.client.IBibLibClient
import com.pixelized.biblib.repository.book.IBookRepository
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
import com.pixelized.biblib.ui.screen.home.common.viewModel.ACoverViewModel
import com.pixelized.biblib.utils.cache.BookCoverCache
import com.pixelized.biblib.utils.extention.context
import com.pixelized.biblib.utils.extention.longDate
import com.pixelized.biblib.utils.painterResource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import java.net.URL
import javax.inject.Inject
@HiltViewModel
class BooksViewModel @Inject constructor(
application: Application,
bookRepository: IBookRepository,
cacheBook: BookCoverCache,
) : ACoverViewModel(application, cacheBook) {
) : ViewModel() {
private val booksSource = Pager(
config = PagingConfig(pageSize = PAGING_SIZE),
@ -46,14 +36,10 @@ class BooksViewModel @Inject constructor(
author = author.joinToString { it.name },
date = releaseDate.longDate(),
isNew = isNew,
cover = cover(
placeHolder = CoverUio(
type = CoverUio.Type.PLACE_HOLDER,
contentScale = ContentScale.None,
painter = painterResource(context, R.drawable.ic_baseline_auto_stories_24),
),
type = CoverUio.Type.THUMBNAIL,
url = URL("${IBibLibClient.THUMBNAIL_URL}/$id.jpg"),
)
cover = "${IBibLibClient.THUMBNAIL_URL}/$id.jpg"
)
companion object {
private const val PAGING_SIZE = 16
}
}

View file

@ -2,7 +2,6 @@ package com.pixelized.biblib.ui.screen.home.page.news
import android.content.res.Configuration
import androidx.compose.animation.*
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
@ -10,20 +9,17 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.pixelized.biblib.R
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.utils.extention.bibLib
import com.skydoves.landscapist.glide.GlideImage
import com.pixelized.biblib.R
@Composable
fun NewThumbnail(
@ -35,12 +31,13 @@ fun NewThumbnail(
modifier = modifier.clickable { thumbnail?.let(onClick) }
) {
thumbnail?.cover?.let { it ->
Cover(
GlideImage(
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.bibLib.shape.base.medium)
.aspectRatio(64f / 102f),
image = it,
previewPlaceholder = R.drawable.ic_baseline_auto_stories_24,
imageModel = it,
)
}
@ -66,33 +63,10 @@ fun NewThumbnail(
}
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun Cover(
modifier: Modifier = Modifier,
image: State<CoverUio>
) {
val cover by image
AnimatedContent(
targetState = cover.painter,
transitionSpec = { fadeIn() with fadeOut() }
) {
Image(
modifier = modifier,
alignment = Alignment.Center,
contentScale = cover.contentScale,
colorFilter = cover.colorFilter,
painter = cover.painter,
contentDescription = null,
)
}
}
@Composable
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun BookThumbnailPreview() {
val painter = painterResource(id = R.drawable.ic_baseline_auto_stories_24)
val thumbnail = BookThumbnailUio(
id = 0,
genre = "Sci-Fi",
@ -100,15 +74,7 @@ private fun BookThumbnailPreview() {
author = "Asimov",
date = "1951",
isNew = false,
cover = remember {
mutableStateOf(
CoverUio(
type = CoverUio.Type.PLACE_HOLDER,
contentScale = ContentScale.None,
painter = painter,
)
)
},
cover = "",
)
BibLibTheme {
NewThumbnail(

View file

@ -1,37 +1,26 @@
package com.pixelized.biblib.ui.screen.home.page.news
import android.app.Application
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.layout.ContentScale
import androidx.lifecycle.ViewModel
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.compose.collectAsLazyPagingItems
import com.pixelized.biblib.R
import com.pixelized.biblib.model.book.Book
import com.pixelized.biblib.network.client.IBibLibClient
import com.pixelized.biblib.repository.book.IBookRepository
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
import com.pixelized.biblib.ui.screen.home.common.viewModel.ACoverViewModel
import com.pixelized.biblib.utils.cache.BookCoverCache
import com.pixelized.biblib.utils.extention.context
import com.pixelized.biblib.utils.extention.longDate
import com.pixelized.biblib.utils.painterResource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import java.net.URL
import javax.inject.Inject
@HiltViewModel
class NewsBookViewModel @Inject constructor(
application: Application,
bookRepository: IBookRepository,
cacheBook: BookCoverCache,
) : ACoverViewModel(application, cacheBook) {
) : ViewModel() {
private val newsSource: Flow<PagingData<BookThumbnailUio>> = Pager(
config = PagingConfig(pageSize = PAGING_SIZE),
@ -42,16 +31,7 @@ class NewsBookViewModel @Inject constructor(
val news @Composable get() = newsSource.collectAsLazyPagingItems()
private fun Book.toThumbnail() : BookThumbnailUio{
val thumbnail by cover(
placeHolder = CoverUio(
type = CoverUio.Type.PLACE_HOLDER,
contentScale = ContentScale.None,
painter = painterResource(context, R.drawable.ic_baseline_auto_stories_24),
),
type = CoverUio.Type.THUMBNAIL,
url = URL("${IBibLibClient.THUMBNAIL_URL}/$id.jpg"),
)
private fun Book.toThumbnail(): BookThumbnailUio {
return BookThumbnailUio(
id = id,
genre = genre?.joinToString { it.name } ?: "",
@ -59,11 +39,11 @@ class NewsBookViewModel @Inject constructor(
author = author.joinToString { it.name },
date = releaseDate.longDate(),
isNew = isNew,
cover = cover(
placeHolder = thumbnail,
type = CoverUio.Type.DETAIL,
url = URL("${IBibLibClient.COVER_URL}/$id.jpg"),
)
cover = "${IBibLibClient.COVER_URL}/$id.jpg"
)
}
companion object {
private const val PAGING_SIZE = 8
}
}

View file

@ -2,16 +2,9 @@ package com.pixelized.biblib.ui.screen.home.page.news
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyItemScope
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyGridScope
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
@ -21,7 +14,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.items
import com.pixelized.biblib.ui.scaffold.BottomDetailState
import com.pixelized.biblib.ui.scaffold.LocalBottomDetailState
import com.pixelized.biblib.ui.screen.connectivity.ConnectivityViewModel
@ -30,7 +22,7 @@ import com.pixelized.biblib.ui.screen.home.common.composable.bookPreviewResource
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.utils.extention.bibLib
import java.util.*
import com.pixelized.biblib.utils.extention.navigationBarsHeight
@Composable
fun NewsPage(
@ -58,10 +50,16 @@ private fun NewsPageContent(
isNetworkAvailable = isNetworkAvailable,
)
LazyVerticalGrid(
modifier = Modifier.weight(1f),
columns = GridCells.Fixed(2),
contentPadding = PaddingValues(all = MaterialTheme.bibLib.dimen.thumbnail.padding),
contentPadding = PaddingValues(
start = MaterialTheme.bibLib.dimen.thumbnail.padding,
end = MaterialTheme.bibLib.dimen.thumbnail.padding,
top = MaterialTheme.bibLib.dimen.thumbnail.padding,
bottom = MaterialTheme.bibLib.dimen.thumbnail.padding + navigationBarsHeight(),
),
verticalArrangement = Arrangement.spacedBy(MaterialTheme.bibLib.dimen.thumbnail.arrangement),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.bibLib.dimen.thumbnail.arrangement)
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.bibLib.dimen.thumbnail.arrangement),
) {
items(
count = books.itemCount

View file

@ -18,7 +18,7 @@ import com.pixelized.biblib.network.client.IBibLibClient
import com.pixelized.biblib.ui.composable.StateUio
import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.utils.extention.bibLib
import com.pixelized.biblib.utils.extention.todo
import com.pixelized.biblib.utils.extention.default
@Composable
fun ProfileScreen(
@ -33,7 +33,7 @@ fun ProfileScreen(
onEditClick = {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(IBibLibClient.EDIT_PROFILE))
context.startActivity(intent)
}
},
)
is StateUio.Failure -> Unit
}
@ -43,7 +43,8 @@ fun ProfileScreen(
private fun ProfileScreenContent(
modifier: Modifier = Modifier,
user: UserUio,
onEditClick: () -> Unit = todo()
onEditClick: () -> Unit = default(),
onLogoutClick: () -> Unit = default(),
) {
Column(modifier = modifier.fillMaxWidth()) {
Text(
@ -107,8 +108,19 @@ private fun ProfileScreenContent(
text = "Edit profile"
)
}
}
Button(
modifier = Modifier
.padding(top = MaterialTheme.bibLib.dimen.dp8)
.align(Alignment.End),
colors = ButtonDefaults.outlinedButtonColors(),
onClick = onLogoutClick,
) {
Text(
text = "Logout"
)
}
}
}
@Composable

View file

@ -1,17 +1,15 @@
package com.pixelized.biblib.ui.screen.profile
import android.app.Application
import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.biblib.model.user.User
import com.pixelized.biblib.network.client.IBibLibClient
import com.pixelized.biblib.network.factory.UserFactory
import com.pixelized.biblib.ui.composable.StateUio
import com.pixelized.biblib.ui.screen.home.common.viewModel.ACoverViewModel
import com.pixelized.biblib.utils.cache.BookCoverCache
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -19,10 +17,8 @@ import javax.inject.Inject
@HiltViewModel
class ProfileViewModel @Inject constructor(
application: Application,
cacheBook: BookCoverCache,
private val client: IBibLibClient,
) : ACoverViewModel(application, cacheBook) {
) : ViewModel() {
var user by mutableStateOf<StateUio<UserUio>>(StateUio.Progress())
private set

View file

@ -33,7 +33,7 @@ data class BibLibDimen(
data class BookThumbnail(
val padding: Dp = 16.dp,
val arrangement: Dp = 16.dp,
val cover: DpSize = DpSize(64.dp, 102.dp), // ratio 1.6
val cover: DpSize = DpSize(width = 72.dp, height = 115.dp), // ratio 1.6
val corner: Dp = 8.dp,
)

View file

@ -1,74 +0,0 @@
package com.pixelized.biblib.utils.cache
import android.graphics.BitmapFactory
import android.util.Log
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.layout.ContentScale
import com.pixelized.biblib.ui.screen.home.common.uio.CoverUio
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.net.URL
import javax.inject.Inject
class BookCoverCache @Inject constructor(
private val cache: ImageCache
) {
fun cover(
coroutineScope: CoroutineScope,
placeHolder: CoverUio,
url: URL,
type: CoverUio.Type,
contentScale: ContentScale,
tint: ColorFilter?,
): State<CoverUio> {
// read the cache a convert it to a UIO.
val cache = cache.readFromDisk(url)?.let {
CoverUio(
type = type,
contentScale = contentScale,
colorFilter = tint,
painter = BitmapPainter(it.asImageBitmap()),
)
}
// publish the cache and stop there, or publish the placeHolder and download the proper file.
return mutableStateOf(cache ?: placeHolder).also {
if (cache == null) {
coroutineScope.launch(Dispatchers.IO) {
it.download(
type = type,
contentScale = contentScale,
tint = tint,
url = url,
)
}
}
}
}
private fun MutableState<CoverUio>.download(
type: CoverUio.Type,
contentScale: ContentScale,
tint: ColorFilter?,
url: URL,
) {
try {
val bitmap = BitmapFactory.decodeStream(url.openStream())
val painter = BitmapPainter(bitmap.asImageBitmap())
cache.writeToDisk(url, bitmap)
value = CoverUio(
type = type,
contentScale = contentScale,
colorFilter = tint,
painter = painter,
)
} catch (exception: Exception) {
Log.w("CoverCache", "Fail to download: {$url}", exception)
}
}
}

View file

@ -1,37 +0,0 @@
package com.pixelized.biblib.utils.cache
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Log
import java.io.File
import java.io.IOException
import java.net.URL
import javax.inject.Inject
class ImageCache @Inject constructor(context: Context) {
private var cache: File? = context.cacheDir
private fun file(url: URL): File = File(cache?.absolutePath + url.file)
fun writeToDisk(url: URL, bitmap: Bitmap) {
val file = file(url)
try {
file.mkdirs()
file.delete()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, file.outputStream())
} catch (e: Exception) {
Log.e("BitmapCache", "bitmap?.compress() FAILED !", e)
}
}
fun readFromDisk(url: URL): Bitmap? {
val file = file(url)
return try {
if (file.exists()) BitmapFactory.decodeStream(file.inputStream()) else null
} catch (e: IOException) {
null
}
}
}

View file

@ -13,7 +13,7 @@ fun Context.notImplemented() {
}
@Composable
fun todo(): () -> Unit {
fun default(): () -> Unit {
val context = LocalContext.current
return { context.notImplemented() }
}

View file

@ -1,5 +0,0 @@
package com.pixelized.biblib.utils.extention
import android.util.Log
fun logC(message: String): Int = Log.v("Composition", message)

View file

@ -0,0 +1,11 @@
package com.pixelized.biblib.utils.extention
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.Dp
@Composable
fun navigationBarsHeight(): Dp =
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()

View file

@ -1,7 +1,18 @@
<vector android:height="24dp" android:viewportHeight="512"
android:viewportWidth="512" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FBBB00" android:pathData="M113.47,309.408L95.648,375.94l-65.139,1.378C11.042,341.211 0,299.9 0,256c0,-42.451 10.324,-82.483 28.624,-117.732h0.014l57.992,10.632l25.404,57.644c-5.317,15.501 -8.215,32.141 -8.215,49.456C103.821,274.792 107.225,292.797 113.47,309.408z"/>
<path android:fillColor="#518EF8" android:pathData="M507.527,208.176C510.467,223.662 512,239.655 512,256c0,18.328 -1.927,36.206 -5.598,53.451c-12.462,58.683 -45.025,109.925 -90.134,146.187l-0.014,-0.014l-73.044,-3.727l-10.338,-64.535c29.932,-17.554 53.324,-45.025 65.646,-77.911h-136.89V208.176h138.887L507.527,208.176L507.527,208.176z"/>
<path android:fillColor="#28B446" android:pathData="M416.253,455.624l0.014,0.014C372.396,490.901 316.666,512 256,512c-97.491,0 -182.252,-54.491 -225.491,-134.681l82.961,-67.91c21.619,57.698 77.278,98.771 142.53,98.771c28.047,0 54.323,-7.582 76.87,-20.818L416.253,455.624z"/>
<path android:fillColor="#F14336" android:pathData="M419.404,58.936l-82.933,67.896c-23.335,-14.586 -50.919,-23.012 -80.471,-23.012c-66.729,0 -123.429,42.957 -143.965,102.724l-83.397,-68.276h-0.014C71.23,56.123 157.06,0 256,0C318.115,0 375.068,22.126 419.404,58.936z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="512"
android:viewportHeight="512">
<path
android:fillColor="#FBBB00"
android:pathData="M113.47,309.408L95.648,375.94l-65.139,1.378C11.042,341.211 0,299.9 0,256c0,-42.451 10.324,-82.483 28.624,-117.732h0.014l57.992,10.632l25.404,57.644c-5.317,15.501 -8.215,32.141 -8.215,49.456C103.821,274.792 107.225,292.797 113.47,309.408z" />
<path
android:fillColor="#518EF8"
android:pathData="M507.527,208.176C510.467,223.662 512,239.655 512,256c0,18.328 -1.927,36.206 -5.598,53.451c-12.462,58.683 -45.025,109.925 -90.134,146.187l-0.014,-0.014l-73.044,-3.727l-10.338,-64.535c29.932,-17.554 53.324,-45.025 65.646,-77.911h-136.89V208.176h138.887L507.527,208.176L507.527,208.176z" />
<path
android:fillColor="#28B446"
android:pathData="M416.253,455.624l0.014,0.014C372.396,490.901 316.666,512 256,512c-97.491,0 -182.252,-54.491 -225.491,-134.681l82.961,-67.91c21.619,57.698 77.278,98.771 142.53,98.771c28.047,0 54.323,-7.582 76.87,-20.818L416.253,455.624z" />
<path
android:fillColor="#F14336"
android:pathData="M419.404,58.936l-82.933,67.896c-23.335,-14.586 -50.919,-23.012 -80.471,-23.012c-66.729,0 -123.429,42.957 -143.965,102.724l-83.397,-68.276h-0.014C71.23,56.123 157.06,0 256,0C318.115,0 375.068,22.126 419.404,58.936z" />
</vector>