Blurred background in ReaderStartItem if cover is present (v1.0.0)

This commit is contained in:
acclorite 2024-04-27 17:37:54 +03:00
parent cd221a685e
commit 51b9f2ffd8
4 changed files with 172 additions and 108 deletions

View file

@ -70,10 +70,10 @@ import ua.acclorite.book_story.presentation.screens.history.data.HistoryViewMode
import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent import ua.acclorite.book_story.presentation.screens.library.data.LibraryEvent
import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel import ua.acclorite.book_story.presentation.screens.library.data.LibraryViewModel
import ua.acclorite.book_story.presentation.screens.reader.components.ReaderEndItem import ua.acclorite.book_story.presentation.screens.reader.components.ReaderEndItem
import ua.acclorite.book_story.presentation.screens.reader.components.ReaderStartItem
import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.ReaderBottomBar import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.ReaderBottomBar
import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.ReaderTopBar import ua.acclorite.book_story.presentation.screens.reader.components.app_bar.ReaderTopBar
import ua.acclorite.book_story.presentation.screens.reader.components.settings_bottom_sheet.ReaderSettingsBottomSheet import ua.acclorite.book_story.presentation.screens.reader.components.settings_bottom_sheet.ReaderSettingsBottomSheet
import ua.acclorite.book_story.presentation.screens.reader.components.start_item.ReaderStartItem
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent import ua.acclorite.book_story.presentation.screens.reader.data.ReaderEvent
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel import ua.acclorite.book_story.presentation.screens.reader.data.ReaderViewModel

View file

@ -1,107 +0,0 @@
package ua.acclorite.book_story.presentation.screens.reader.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
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.statusBarsIgnoringVisibility
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Image
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.components.CustomCoverImage
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState
/**
* Reader start item. Displays at the beginning of the book.
*/
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun ReaderStartItem(state: State<ReaderState>) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.surface)
.windowInsetsPadding(WindowInsets.statusBarsIgnoringVisibility)
.padding(horizontal = 24.dp, vertical = 80.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically, modifier = Modifier
.fillMaxWidth()
) {
Box(
modifier = Modifier
.height(135.dp)
.width(90.dp)
.clip(RoundedCornerShape(10.dp))
.background(MaterialTheme.colorScheme.surfaceContainerLow)
) {
if (state.value.book.coverImage != null) {
CustomCoverImage(
uri = state.value.book.coverImage!!,
modifier = Modifier
.fillMaxSize()
.clip(RoundedCornerShape(10.dp))
)
} else {
Icon(
imageVector = Icons.Default.Image,
contentDescription = stringResource(id = R.string.cover_image_not_found_content_desc),
modifier = Modifier
.align(Alignment.Center)
.fillMaxWidth(0.7f)
.aspectRatio(1f),
tint = MaterialTheme.colorScheme.surfaceContainerHigh
)
}
}
Spacer(modifier = Modifier.width(18.dp))
Column(verticalArrangement = Arrangement.Center) {
Text(
state.value.book.title,
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier
.fillMaxWidth(),
maxLines = 4,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(4.dp))
Text(
stringResource(id = R.string.happy_reading),
color = MaterialTheme.colorScheme.onSurfaceVariant,
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier
.fillMaxWidth(),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
}
}

View file

@ -0,0 +1,128 @@
package ua.acclorite.book_story.presentation.screens.reader.components.start_item
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
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.statusBarsIgnoringVisibility
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Image
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.R
import ua.acclorite.book_story.presentation.components.CustomCoverImage
import ua.acclorite.book_story.presentation.screens.reader.data.ReaderState
/**
* Reader start item. Displays at the beginning of the book.
*/
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun ReaderStartItem(state: State<ReaderState>) {
val statusBarHeight = WindowInsets
.statusBarsIgnoringVisibility
.asPaddingValues()
.calculateTopPadding()
val itemsHeight = remember(statusBarHeight) {
statusBarHeight + 80.dp + 135.dp + 40.dp
}
Box(
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.surface)
) {
if (state.value.book.coverImage != null) {
ReaderStartItemBackground(
height = itemsHeight,
image = state.value.book.coverImage!!
)
}
Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = statusBarHeight)
.padding(horizontal = 24.dp, vertical = 80.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically, modifier = Modifier
.fillMaxWidth()
) {
Box(
modifier = Modifier
.height(135.dp)
.width(90.dp)
.clip(RoundedCornerShape(10.dp))
.background(MaterialTheme.colorScheme.surfaceContainerLow)
) {
if (state.value.book.coverImage != null) {
CustomCoverImage(
uri = state.value.book.coverImage!!,
modifier = Modifier
.fillMaxSize()
.clip(RoundedCornerShape(10.dp))
)
} else {
Icon(
imageVector = Icons.Default.Image,
contentDescription = stringResource(id = R.string.cover_image_not_found_content_desc),
modifier = Modifier
.align(Alignment.Center)
.fillMaxWidth(0.7f)
.aspectRatio(1f),
tint = MaterialTheme.colorScheme.surfaceContainerHigh
)
}
}
Spacer(modifier = Modifier.width(18.dp))
Column(verticalArrangement = Arrangement.Center) {
Text(
state.value.book.title,
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier
.fillMaxWidth(),
maxLines = 4,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.height(4.dp))
Text(
stringResource(id = R.string.happy_reading),
color = MaterialTheme.colorScheme.onSurfaceVariant,
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier
.fillMaxWidth(),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
}
}
}

View file

@ -0,0 +1,43 @@
package ua.acclorite.book_story.presentation.screens.reader.components.start_item
import android.net.Uri
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import ua.acclorite.book_story.presentation.components.CustomCoverImage
/**
* Background of the [ReaderStartItem].
*/
@Composable
fun ReaderStartItemBackground(height: Dp, image: Uri) {
val background = MaterialTheme.colorScheme.surface
CustomCoverImage(
uri = image,
animationDurationMillis = 300,
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.height(height)
.drawWithContent {
drawContent()
drawRect(
brush = Brush.verticalGradient(
0f to Color.Transparent,
0.8f to background
)
)
}
.blur(5.dp),
alpha = 0.4f
)
}