Add email bottom sheet choice in book detail.

This commit is contained in:
Thomas Andres Gomez 2022-06-30 15:56:06 +02:00
parent f6739f60ee
commit 3137c358c7
6 changed files with 131 additions and 22 deletions

View file

@ -15,6 +15,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.window.Dialog
import com.pixelized.biblib.ui.composable.dialog.ErrorCard
import com.pixelized.biblib.ui.composable.dialog.LoadingCard
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
sealed class StateUio<T> {
class Progress<T>(val progress: Float? = null) : StateUio<T>()
@ -22,6 +24,14 @@ sealed class StateUio<T> {
class Success<T>(val value: T) : StateUio<T>()
}
@OptIn(ExperimentalContracts::class)
fun <T> StateUio<T>.isSuccessful(): Boolean {
contract {
returns(true) implies (this@isSuccessful is StateUio.Success<T>)
}
return this is StateUio.Success<T>
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun <T> StateUioHandler(

View file

@ -20,7 +20,7 @@ import com.pixelized.biblib.utils.extention.showToast
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
val LocalBottomDetailController = staticCompositionLocalOf<BottomDetailState> {
val LocalBottomDetailState = staticCompositionLocalOf<BottomDetailState> {
error("LocalBottomDetailController is not ready yet")
}
@ -31,7 +31,7 @@ fun BottomDetailScaffold(
content: @Composable () -> Unit,
) {
CompositionLocalProvider(
LocalBottomDetailController provides bottomDetailState
LocalBottomDetailState provides bottomDetailState
) {
ModalBottomSheetLayout(
scrimColor = Color.Black.copy(alpha = 0.37f),
@ -89,7 +89,6 @@ class BottomDetailState constructor(
}
is StateUio.Success -> {
bookDetail.value = book.value
// bottomSheetState.animateTo(ModalBottomSheetValue.Expanded)
bottomSheetState.show()
}
else -> Unit

View file

@ -2,21 +2,21 @@ package com.pixelized.biblib.ui.screen.detail
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.activity.compose.BackHandler
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Button
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Send
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.*
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
@ -26,28 +26,76 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
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
import com.pixelized.biblib.ui.composable.animation.AnimatedOffset
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 kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun DetailScreen(
detailState: BottomDetailState = LocalBottomDetailState.current,
profileViewModel: ProfileViewModel = hiltViewModel(),
detail: BookUio? = null,
) {
if (detail != null) {
DetailScreenContent(
modifier = Modifier.fillMaxSize(),
book = detail,
)
} else {
Box(modifier = Modifier.fillMaxSize())
val scope = rememberCoroutineScope()
val sheet = rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
skipHalfExpanded = true,
)
ModalBottomSheetLayout(
sheetState = sheet,
scrimColor = Color.Black.copy(alpha = 0.37f),
sheetContent = {
Box(
modifier = Modifier
.fillMaxWidth()
.heightIn(min = 1.dp)
.animateContentSize()
) {
val user by derivedStateOf { profileViewModel.user }
if (user.isSuccessful()) {
DetailScreenSendContent(
modifier = Modifier.navigationBarsPadding(),
emails = (user as StateUio.Success<UserUio>).value.amazonEmails,
)
}
}
},
content = {
if (detailState.bottomSheetState.isVisible) {
if (detail != null) {
DetailScreenContent(
modifier = Modifier.fillMaxSize(),
book = detail,
onSend = { scope.launch { sheet.show() } }
)
} else {
Box(modifier = Modifier.fillMaxSize())
}
} else {
LaunchedEffect(key1 = "email bottom sheet close") { sheet.hide() }
}
},
)
BackHandler(enabled = sheet.isVisible) {
scope.launch { sheet.hide() }
}
}
@ -61,7 +109,6 @@ private fun DetailScreenContent(
) {
AnimatedDelayer(
targetState = book,
delay = 300,
) {
Column(
modifier = Modifier
@ -230,6 +277,44 @@ private fun TitleLabel(
}
}
@Composable
private fun DetailScreenSendContent(
modifier: Modifier = Modifier,
emails: List<String>,
) {
Column(
modifier = modifier.fillMaxWidth(),
) {
Text(
modifier = Modifier.padding(
vertical = MaterialTheme.bibLib.dimen.dp8,
horizontal = MaterialTheme.bibLib.dimen.dp16,
),
color = MaterialTheme.colors.primary,
style = MaterialTheme.typography.caption,
text = "Send this eBook to:",
)
LazyColumn {
items(items = emails) {
Box(
modifier = Modifier
.height(height = MaterialTheme.bibLib.dimen.dp48)
.fillMaxWidth(),
contentAlignment = Alignment.CenterStart
) {
Text(
modifier = Modifier.padding(horizontal = MaterialTheme.bibLib.dimen.dp16),
style = MaterialTheme.typography.body1,
color = MaterialTheme.colors.onSurface,
text = it
)
}
}
}
}
}
@Composable
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO)
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
@ -258,4 +343,18 @@ private fun DetailScreenContentPreview() {
BibLibTheme {
DetailScreenContent(book = book)
}
}
@Composable
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO)
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
private fun DetailScreenSendPreview() {
BibLibTheme {
DetailScreenSendContent(
emails = listOf(
"R.Giskard.Reventlov.Kindle@gmailcom",
"R.Daneel.Olivaw.Kindle@gmailcom",
),
)
}
}

View file

@ -6,7 +6,7 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import com.pixelized.biblib.ui.scaffold.LocalBottomDetailController
import com.pixelized.biblib.ui.scaffold.LocalBottomDetailState
import com.pixelized.biblib.ui.screen.connectivity.ConnectivityViewModel
import com.pixelized.biblib.ui.screen.home.common.composable.LazyBookThumbnailColumn
import com.pixelized.biblib.ui.screen.home.page.news.NewsPage
@ -18,7 +18,7 @@ fun BooksPage(
connectivityViewModel: ConnectivityViewModel = hiltViewModel(),
booksViewModel: BooksViewModel = hiltViewModel()
) {
val bottomDetailState = LocalBottomDetailController.current
val bottomDetailState = LocalBottomDetailState.current
LazyBookThumbnailColumn(
verticalArrangement = Arrangement.spacedBy(MaterialTheme.bibLib.dimen.thumbnail.arrangement),

View file

@ -6,7 +6,7 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import com.pixelized.biblib.ui.scaffold.LocalBottomDetailController
import com.pixelized.biblib.ui.scaffold.LocalBottomDetailState
import com.pixelized.biblib.ui.screen.connectivity.ConnectivityViewModel
import com.pixelized.biblib.ui.screen.home.common.composable.LazyBookThumbnailColumn
import com.pixelized.biblib.ui.theme.BibLibTheme
@ -17,7 +17,7 @@ fun NewsPage(
connectivityViewModel: ConnectivityViewModel = hiltViewModel(),
booksViewModel: NewsBookViewModel = hiltViewModel()
) {
val bottomDetail = LocalBottomDetailController.current
val bottomDetail = LocalBottomDetailState.current
LazyBookThumbnailColumn(
verticalArrangement = Arrangement.spacedBy(MaterialTheme.bibLib.dimen.thumbnail.arrangement),

View file

@ -14,6 +14,7 @@ data class BibLibDimen(
val dp8: Dp = 8.dp,
val dp16: Dp = 16.dp,
val dp32: Dp = 32.dp,
val dp48: Dp = 48.dp,
val dp64: Dp = 64.dp,
val dialog: Dialog = Dialog(),
val thumbnail: BookThumbnail = BookThumbnail(),