Add new manga screen variant

master
Zakhar Timoshenko 2 years ago
parent b8c2446335
commit 210da5db8a
Signed by: Xtimms
SSH Key Fingerprint: SHA256:wH6spYepK/A5erBh7ZyAnr1ru9H4eaMVBEuiw6DSpxI

@ -1,14 +1,9 @@
package org.xtimms.shirizu.core.components
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Share
import androidx.compose.material.icons.outlined.Download
@ -32,13 +27,12 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DetailsToolbar(
fun ModernDetailsToolbar(
title: String,
titleAlphaProvider: () -> Float,
navigateBack: () -> Unit,
@ -119,3 +113,75 @@ fun DetailsToolbar(
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ClassicDetailsToolbar(
title: String,
titleAlphaProvider: () -> Float,
navigateBack: () -> Unit,
navigateToWebBrowser: () -> Unit,
modifier: Modifier = Modifier,
backgroundAlphaProvider: () -> Float = titleAlphaProvider
) {
var expanded by remember { mutableStateOf(false) }
Column(
modifier = modifier
) {
TopAppBar(
navigationIcon = {
BackIconButton(
onClick = navigateBack
)
},
title = {
Text(
text = title,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
color = LocalContentColor.current.copy(alpha = titleAlphaProvider()),
)
},
actions = {
IconButton(
onClick = { expanded = true }
) {
Icon(imageVector = Icons.Default.MoreVert, contentDescription = null)
}
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
DropdownMenuItem(
text = { Text("Share") },
onClick = { /*TODO*/ },
leadingIcon = {
Icon(imageVector = Icons.Default.Share, contentDescription = null)
}
)
DropdownMenuItem(
text = { Text("Download") },
onClick = { /*TODO*/ },
leadingIcon = {
Icon(imageVector = Icons.Outlined.Download, contentDescription = null)
}
)
DropdownMenuItem(
text = { Text("Open in web browser") },
onClick = {
navigateToWebBrowser()
expanded = false
},
leadingIcon = {
Icon(imageVector = Icons.Outlined.Language, contentDescription = null)
}
)
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme
.surfaceColorAtElevation(3.dp)
.copy(alpha = backgroundAlphaProvider())
)
)
}
}

@ -27,9 +27,9 @@ fun SettingTitle(text: String) {
Text(
modifier = Modifier
.padding(top = 32.dp)
.padding(horizontal = 20.dp, vertical = 16.dp),
.padding(horizontal = 16.dp, vertical = 16.dp),
text = text,
style = MaterialTheme.typography.displaySmall
style = MaterialTheme.typography.headlineLarge
)
}

@ -22,8 +22,8 @@ import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.QueryStats
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material.icons.outlined.QueryStats
import androidx.compose.material.icons.outlined.RssFeed
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material.icons.outlined.SentimentSatisfiedAlt
@ -41,6 +41,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
@ -63,6 +64,7 @@ import org.xtimms.shirizu.R
import org.xtimms.shirizu.core.DURATION_ENTER
import org.xtimms.shirizu.core.DURATION_EXIT
import org.xtimms.shirizu.core.initialOffset
import org.xtimms.shirizu.core.prefs.AppSettings
import org.xtimms.shirizu.core.toEasing
import org.xtimms.shirizu.sections.explore.EXPLORE_DESTINATION
import org.xtimms.shirizu.sections.feed.FEED_DESTINATION
@ -167,53 +169,76 @@ fun TopAppBar(
Row(
modifier = modifier.padding(end = 16.dp),
) {
IconButton(
onClick = { navController.navigate(FEED_DESTINATION) },
modifier = Modifier.padding(0.dp),
) {
Icon(
Icons.Outlined.RssFeed,
contentDescription = stringResource(id = R.string.feed),
tint = MaterialTheme.colorScheme.outline
)
}
IconButton(
onClick = { expanded = true },
modifier = Modifier.padding(0.dp),
) {
Icon(
Icons.Outlined.MoreVert,
contentDescription = stringResource(id = R.string.open_menu),
tint = MaterialTheme.colorScheme.outline
)
}
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
DropdownMenuItem(
text = { Text(text = stringResource(id = R.string.statistics)) },
onClick = {
navController.navigate(STATS_DESTINATION)
expanded = false
},
leadingIcon = {
Icon(
imageVector = Icons.Default.QueryStats,
contentDescription = stringResource(id = R.string.statistics)
)
}
)
DropdownMenuItem(
text = { Text(text = stringResource(id = R.string.settings)) },
onClick = {
navController.navigate(SETTINGS_DESTINATION)
expanded = false
},
leadingIcon = {
Icon(
imageVector = Icons.Outlined.Settings,
contentDescription = stringResource(id = R.string.settings)
)
}
)
if (AppSettings.isTrackerEnabled()) {
IconButton(
onClick = { navController.navigate(FEED_DESTINATION) },
modifier = Modifier.padding(0.dp),
) {
Icon(
Icons.Outlined.RssFeed,
contentDescription = stringResource(id = R.string.feed),
tint = MaterialTheme.colorScheme.outline
)
}
IconButton(
onClick = { expanded = true },
modifier = Modifier.padding(0.dp),
) {
Icon(
Icons.Outlined.MoreVert,
contentDescription = stringResource(id = R.string.open_menu),
tint = MaterialTheme.colorScheme.outline
)
}
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
DropdownMenuItem(
text = { Text(text = stringResource(id = R.string.statistics)) },
onClick = {
navController.navigate(STATS_DESTINATION)
expanded = false
},
leadingIcon = {
Icon(
imageVector = Icons.Outlined.QueryStats,
contentDescription = stringResource(id = R.string.statistics)
)
}
)
DropdownMenuItem(
text = { Text(text = stringResource(id = R.string.settings)) },
onClick = {
navController.navigate(SETTINGS_DESTINATION)
expanded = false
},
leadingIcon = {
Icon(
imageVector = Icons.Outlined.Settings,
contentDescription = stringResource(id = R.string.settings)
)
}
)
}
} else {
IconButton(
onClick = { navController.navigate(STATS_DESTINATION) },
modifier = Modifier.padding(0.dp),
) {
Icon(
Icons.Outlined.QueryStats,
contentDescription = stringResource(id = R.string.statistics),
tint = MaterialTheme.colorScheme.outline
)
}
IconButton(
onClick = { navController.navigate(SETTINGS_DESTINATION) },
modifier = Modifier.padding(0.dp),
) {
Icon(
Icons.Outlined.Settings,
contentDescription = stringResource(id = R.string.settings),
tint = MaterialTheme.colorScheme.outline
)
}
}
}
}
@ -271,18 +296,36 @@ fun SmallTopAppBarWithChips(
}
}
private val path = Path().apply {
moveTo(0f,0f)
lineTo(0.7f, 0.1f)
cubicTo(0.7f, 0.1f, .95F, .5F, 1F, 1F)
moveTo(1f,1f)
}
val fraction: (Float) -> Float = { PathInterpolator(path).getInterpolation(it) }
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SmallTopAppBar(
title: String,
scrollBehavior: TopAppBarScrollBehavior? = null,
navigateBack: () -> Unit,
modifier: Modifier = Modifier,
titleText: String = "",
scrollBehavior: TopAppBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
title: @Composable () -> Unit = {
Text(
text = titleText,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = fraction(scrollBehavior.state.overlappedFraction)),
maxLines = 1
)
},
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
) {
MediumTopAppBar(
title = { Text(text = title) },
navigationIcon = {
BackIconButton(onClick = navigateBack)
},
androidx.compose.material3.TopAppBar(
modifier = modifier,
title = title,
navigationIcon = navigationIcon,
actions = actions,
scrollBehavior = scrollBehavior
)
}

@ -59,6 +59,7 @@ const val RELATED = "related"
const val TRACKER = "tracker"
const val CELLULAR_DOWNLOAD = "cellular_download"
const val STATISTICS = "statistics"
const val MODERN_VIEW = "modern_view"
const val PROXY_TYPE = "proxy_type"
const val PROXY_ADDRESS = "proxy_address"
@ -170,6 +171,8 @@ object AppSettings {
fun isStatisticsEnabled() = STATISTICS.getBoolean()
fun isModernViewEnabled() = MODERN_VIEW.getBoolean(true)
fun getGridColumnsCount(columns: Int = GRID_COLUMNS.getInt()): Float {
return when (columns) {
1 -> 1f

@ -1,4 +1,4 @@
package org.xtimms.shirizu.core.screens
package org.xtimms.shirizu.core.ui.screens
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement

@ -1,4 +1,4 @@
package org.xtimms.shirizu.core.screens
package org.xtimms.shirizu.core.ui.screens
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.core.RepeatMode

@ -1,4 +1,4 @@
package org.xtimms.shirizu.core.screens
package org.xtimms.shirizu.core.ui.screens
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize

@ -19,7 +19,7 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import org.acra.ktx.sendWithAcra
import org.xtimms.shirizu.R
import org.xtimms.shirizu.core.screens.InfoScreen
import org.xtimms.shirizu.core.ui.screens.InfoScreen
import org.xtimms.shirizu.ui.theme.ShirizuTheme
import org.xtimms.shirizu.utils.system.toast

@ -0,0 +1,244 @@
package org.xtimms.shirizu.sections.details
import android.net.Uri
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.blur
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import coil.ImageLoader
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaState
import org.xtimms.shirizu.R
import org.xtimms.shirizu.core.AsyncImageImpl
import org.xtimms.shirizu.core.components.MangaCover
import org.xtimms.shirizu.sections.details.data.ReadingTime
import org.xtimms.shirizu.sections.details.model.HistoryInfo
@Composable
fun ClassicDetailsInfoBox(
coil: ImageLoader,
imageUrl: String,
favicon: Uri,
title: String,
altTitle: String,
author: String,
isNsfw: Boolean,
state: MangaState?,
source: MangaSource,
historyInfo: HistoryInfo,
readingTime: ReadingTime?,
isTabletUi: Boolean,
appBarPadding: Dp,
modifier: Modifier = Modifier,
onCoverClick: () -> Unit,
isInShelf: Boolean,
onAddToShelfClicked: () -> Unit,
onSourceClicked: () -> Unit,
onDownloadClick: () -> Unit,
) {
Box(modifier = modifier) {
// Backdrop
val backdropGradientColors = listOf(
Color.Transparent,
MaterialTheme.colorScheme.background,
)
AsyncImageImpl(
coil = coil,
model = imageUrl,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.matchParentSize()
.drawWithContent {
drawContent()
drawRect(
brush = Brush.verticalGradient(colors = backdropGradientColors),
)
}
.blur(3.dp)
.alpha(0.33f),
)
// Manga & source info
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) {
if (!isTabletUi) {
MangaInfoSmall(
coil = coil,
appBarPadding = appBarPadding,
imageUrl = imageUrl,
favicon = favicon,
title = title,
altTitle = altTitle,
author = author,
state = state,
source = source,
isInShelf = isInShelf,
onAddToShelfClicked = onAddToShelfClicked,
onCoverClick = onCoverClick,
onSourceClicked = onSourceClicked,
historyInfo = historyInfo,
readingTime = readingTime,
onDownloadClick = onDownloadClick
)
} else {
MangaInfoLarge(
coil = coil,
appBarPadding = appBarPadding,
imageUrl = imageUrl,
favicon = favicon,
title = title,
altTitle = altTitle,
author = author,
state = state,
source = source,
isInShelf = isInShelf,
onAddToShelfClicked = onAddToShelfClicked,
onCoverClick = onCoverClick,
onSourceClicked = onSourceClicked,
historyInfo = historyInfo,
readingTime = readingTime,
onDownloadClick = onDownloadClick
)
}
}
}
}
@Composable
fun MangaInfoLarge(
coil: ImageLoader,
appBarPadding: Dp,
imageUrl: String,
favicon: Uri,
title: String,
altTitle: String,
author: String,
source: MangaSource,
state: MangaState?,
historyInfo: HistoryInfo,
readingTime: ReadingTime?,
isInShelf: Boolean,
onAddToShelfClicked: () -> Unit,
onCoverClick: () -> Unit,
onSourceClicked: () -> Unit,
onDownloadClick: () -> Unit,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, top = appBarPadding + 16.dp, end = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
MangaCover.Book(
coil = coil,
modifier = Modifier
.fillMaxWidth(0.65f)
.clickable(
role = Role.Button,
onClick = onCoverClick
),
data = imageUrl,
contentDescription = stringResource(R.string.manga_cover),
)
Spacer(modifier = Modifier.height(16.dp))
DetailsContentInfo(
coil = coil,
favicon = favicon,
title = title,
altTitle = altTitle,
author = author,
state = state,
source = source.title,
isInShelf = isInShelf,
onAddToShelfClicked = onAddToShelfClicked,
onSourceClicked = onSourceClicked,
historyInfo = historyInfo,
readingTime = readingTime,
onDownloadClick = onDownloadClick
)
}
}
@Composable
fun MangaInfoSmall(
coil: ImageLoader,
appBarPadding: Dp,
imageUrl: String,
favicon: Uri,
title: String,
altTitle: String,
author: String,
state: MangaState?,
source: MangaSource,
historyInfo: HistoryInfo,
readingTime: ReadingTime?,
isInShelf: Boolean,
onAddToShelfClicked: () -> Unit,
onCoverClick: () -> Unit,
onSourceClicked: () -> Unit,
onDownloadClick: () -> Unit,
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = appBarPadding + 32.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
AsyncImageImpl(
coil = coil,
modifier = Modifier
.padding(horizontal = 16.dp)
.sizeIn(maxWidth = 54.dp)
.align(Alignment.Start)
.aspectRatio(1f)
.clip(CircleShape)
.clickable(
role = Role.Button,
onClick = onCoverClick
),
model = imageUrl,
contentDescription = stringResource(R.string.manga_cover),
)
DetailsContentInfo(
coil = coil,
favicon = favicon,
title = title,
altTitle = altTitle,
author = author,
state = state,
source = source.title,
isInShelf = isInShelf,
onAddToShelfClicked = onAddToShelfClicked,
onSourceClicked = onSourceClicked,
historyInfo = historyInfo,
readingTime = readingTime,
onDownloadClick = onDownloadClick
)
}
}

@ -15,33 +15,26 @@ import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
import androidx.compose.animation.graphics.vector.AnimatedImageVector
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
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.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
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.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.MenuBook
import androidx.compose.material.icons.outlined.Block
import androidx.compose.material.icons.outlined.Close
import androidx.compose.material.icons.outlined.DoneAll
import androidx.compose.material.icons.outlined.FileDownload
import androidx.compose.material.icons.outlined.KeyboardArrowDown
import androidx.compose.material.icons.outlined.Language
import androidx.compose.material.icons.outlined.LocalLibrary
import androidx.compose.material.icons.outlined.Pause
import androidx.compose.material.icons.outlined.Person
@ -49,20 +42,16 @@ import androidx.compose.material.icons.outlined.Schedule
import androidx.compose.material.icons.outlined.Sync
import androidx.compose.material.icons.outlined.Upcoming
import androidx.compose.material3.AssistChip
import androidx.compose.material3.AssistChipDefaults
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ElevatedAssistChip
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.InputChip
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalMinimumInteractiveComponentEnforcement
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedIconButton
import androidx.compose.material3.ProvideTextStyle
import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -82,14 +71,11 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@ -105,10 +91,8 @@ import org.xtimms.shirizu.core.components.ButtonType
import org.xtimms.shirizu.core.components.HtmlTextField
import org.xtimms.shirizu.core.components.MangaCover
import org.xtimms.shirizu.core.components.ReadButton
import org.xtimms.shirizu.core.parser.favicon.faviconUri
import org.xtimms.shirizu.sections.details.data.ReadingTime
import org.xtimms.shirizu.sections.details.model.HistoryInfo
import org.xtimms.shirizu.ui.theme.ShirizuTheme
import org.xtimms.shirizu.utils.composable.clickableNoIndication
import org.xtimms.shirizu.utils.composable.secondaryItemAlpha
import kotlin.math.roundToInt
@ -116,106 +100,7 @@ import kotlin.math.roundToInt
private val whitespaceLineRegex = Regex("[\\r\\n]{2,}", setOf(RegexOption.MULTILINE))
@Composable
fun DetailsInfoBox(
coil: ImageLoader,
imageUrl: String,
favicon: Uri,
title: String,
altTitle: String,
author: String,
isNsfw: Boolean,
state: MangaState?,
source: MangaSource,
historyInfo: HistoryInfo,
readingTime: ReadingTime?,
isTabletUi: Boolean,
appBarPadding: Dp,
modifier: Modifier = Modifier,
onCoverClick: () -> Unit,
isInShelf: Boolean,
onAddToShelfClicked: () -> Unit,
onSourceClicked: () -> Unit,
onDownloadClick: () -> Unit,
) {
Column(modifier = modifier) {
Box(
modifier = Modifier
.fillMaxWidth(),
contentAlignment = Alignment.BottomEnd,
) {
AsyncImageImpl(
coil = coil,
model = imageUrl,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.padding(start = 16.dp, end = 16.dp)
.aspectRatio(1f)
.clickable(
role = Role.Button,
onClick = onCoverClick
)
.clip(MaterialTheme.shapes.large)
)
if (isNsfw) {
ElevatedAssistChip(
modifier = Modifier.padding(end = 32.dp, bottom = 8.dp),
onClick = { /*TODO*/ },
label = {
Text(
text = "18+",
color = MaterialTheme.colorScheme.onErrorContainer
)
},
border = BorderStroke(1.dp, MaterialTheme.colorScheme.errorContainer),
colors = AssistChipDefaults.elevatedAssistChipColors()
.copy(containerColor = MaterialTheme.colorScheme.errorContainer)
)
}
}
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) {
if (!isTabletUi) {
MangaAndSourceTitlesSmall(
coil = coil,
favicon = favicon,
title = title,
altTitle = altTitle,
author = author,
state = state,
source = source,
isInShelf = isInShelf,
onAddToShelfClicked = onAddToShelfClicked,
onSourceClicked = onSourceClicked,
historyInfo = historyInfo,
readingTime = readingTime,
onDownloadClick = onDownloadClick
)
} else {
MangaAndSourceTitlesLarge(
coil = coil,
appBarPadding = appBarPadding,
imageUrl = imageUrl,
favicon = favicon,
title = title,
altTitle = altTitle,
author = author,
state = state,
source = source,
isInShelf = isInShelf,
onAddToShelfClicked = onAddToShelfClicked,
onSourceClicked = onSourceClicked,
historyInfo = historyInfo,
readingTime = readingTime,
onDownloadClick = onDownloadClick
)
}
}
}
}
@Composable
private fun MangaAndSourceTitlesLarge(
fun MangaAndSourceTitlesLarge(
coil: ImageLoader,
appBarPadding: Dp,
imageUrl: String,
@ -264,7 +149,7 @@ private fun MangaAndSourceTitlesLarge(
}
@Composable
private fun MangaAndSourceTitlesSmall(
fun MangaAndSourceTitlesSmall(
coil: ImageLoader,
favicon: Uri,
title: String,
@ -288,15 +173,6 @@ private fun MangaAndSourceTitlesSmall(
.padding(top = 8.dp),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
/*AsyncImage(
model = imageUrl,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.padding(PaddingValues(bottom = 8.dp))
.clip(RoundedCornerShape(100))
.size(48.dp),
)*/
DetailsContentInfo(
coil = coil,
favicon = favicon,
@ -321,7 +197,7 @@ private fun MangaAndSourceTitlesSmall(
ExperimentalMaterial3Api::class
)
@Composable
private fun DetailsContentInfo(
fun DetailsContentInfo(
coil: ImageLoader,
favicon: Uri,
title: String,
@ -528,23 +404,6 @@ private fun DetailsContentInfo(
}
HorizontalDivider(modifier = Modifier.padding(vertical = 16.dp))
}
/*Row(modifier = Modifier
.weight(.5f)
.padding(start = 4.dp, end = 16.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
AnimatedButton(
modifier = Modifier.size(54.dp),
type = KeyboardButtonType.PRIMARY,
icon = Icons.Outlined.FavoriteBorder
)
AnimatedButton(
modifier = Modifier
.height(54.dp)
.fillMaxWidth(),
type = KeyboardButtonType.TERTIARY,
icon = Icons.Outlined.PlayArrow
)
}*/
}
}
@ -621,7 +480,7 @@ fun ExpandableMangaDescription(
) {
tags.forEach {
TagsChip(
modifier = DefaultTagChipModifier,
modifier = modifier.padding(vertical = 4.dp),
tag = it,
onClick = {
tagSelected = it.title
@ -645,8 +504,6 @@ private fun MangaSummary(
modifier: Modifier = Modifier,
) {
val uriHandler = LocalUriHandler.current
val animProgress by animateFloatAsState(
targetValue = if (expanded) 1f else 0f,
label = "summary",
@ -728,8 +585,6 @@ private fun MangaSummary(
}
}
private val DefaultTagChipModifier = Modifier.padding(vertical = 4.dp)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TagsChip(

@ -15,8 +15,6 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.fillMaxHeight
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.sizeIn
@ -62,12 +60,12 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaState
import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN
import org.xtimms.shirizu.LocalWindowWidthState
import org.xtimms.shirizu.R
import org.xtimms.shirizu.core.HapticFeedback.slightHapticFeedback
import org.xtimms.shirizu.core.components.DetailsToolbar
import org.xtimms.shirizu.core.components.ClassicDetailsToolbar
import org.xtimms.shirizu.core.components.MangaHorizontalItem
import org.xtimms.shirizu.core.components.ModernDetailsToolbar
import org.xtimms.shirizu.core.parser.favicon.faviconUri
import org.xtimms.shirizu.core.prefs.AppSettings
import org.xtimms.shirizu.core.prefs.AppSettings.getBoolean
@ -115,6 +113,7 @@ fun DetailsView(
}
}
} else null
val isModernView = AppSettings.isModernViewEnabled()
val checkNetworkOrDownload = {
if (!AppSettings.isNetworkAvailableForDownload()) {
@ -224,13 +223,23 @@ fun DetailsView(
if (!isFirstItemVisible || isFirstItemScrolled) 1f else 0f,
label = "Top Bar Background",
)
DetailsToolbar(
title = viewModel.details.value?.toManga()?.title.orEmpty(),
titleAlphaProvider = { animatedTitleAlpha },
backgroundAlphaProvider = { animatedBgAlpha },
navigateBack = { navigateBack() },
navigateToWebBrowser = { openUrl(viewModel.details.value?.toManga()?.publicUrl.orEmpty()) },
)
if (isModernView) {
ModernDetailsToolbar(
title = viewModel.details.value?.toManga()?.title.orEmpty(),
titleAlphaProvider = { animatedTitleAlpha },
backgroundAlphaProvider = { animatedBgAlpha },
navigateBack = { navigateBack() },
navigateToWebBrowser = { openUrl(viewModel.details.value?.toManga()?.publicUrl.orEmpty()) },
)
} else {
ClassicDetailsToolbar(
title = viewModel.details.value?.toManga()?.title.orEmpty(),
titleAlphaProvider = { animatedTitleAlpha },
backgroundAlphaProvider = { animatedBgAlpha },
navigateBack = { navigateBack() },
navigateToWebBrowser = { openUrl(viewModel.details.value?.toManga()?.publicUrl.orEmpty()) },
)
}
},
snackbarHost = {
SnackbarHost(
@ -245,7 +254,7 @@ fun DetailsView(
modifier = Modifier.fillMaxHeight(),
state = chapterListState,
contentPadding = PaddingValues(
top = contentPadding.calculateTopPadding() - 60.dp,
top = if (isModernView) contentPadding.calculateTopPadding() - 60.dp else 0.dp,
start = contentPadding.calculateStartPadding(layoutDirection),
end = contentPadding.calculateEndPadding(layoutDirection),
bottom = contentPadding.calculateBottomPadding(),
@ -256,38 +265,73 @@ fun DetailsView(
key = DetailsViewItem.INFO_BOX,
contentType = DetailsViewItem.INFO_BOX
) {
DetailsInfoBox(
coil = coil,
imageUrl = manga?.largeCoverUrl ?: manga?.coverUrl.orEmpty(),
favicon = manga?.source?.faviconUri() ?: Uri.EMPTY,
title = manga?.title.orEmpty(),
altTitle = manga?.altTitle.orEmpty(),
author = manga?.author.orEmpty(),
isNsfw = manga?.isNsfw ?: true,
state = manga?.state ?: MangaState.FINISHED,
source = manga?.source ?: MangaSource.DUMMY,
isTabletUi = false,
appBarPadding = topPadding,
onCoverClick = {
navigateToFullImage(
arrayOf(
manga?.largeCoverUrl ?: manga?.coverUrl.orEmpty(),
).toNavArgument()
)
},
historyInfo = historyInfo,
readingTime = readingTime,
isInShelf = favouriteCategories,
onAddToShelfClicked = {
openCategoriesBottomSheet = !openCategoriesBottomSheet
},
onSourceClicked = {
navigateToSource(
manga?.source ?: MangaSource.DUMMY
)
},
onDownloadClick = downloadCallback
)
if (isModernView) {
ModernDetailsInfoBox(
coil = coil,
imageUrl = manga?.largeCoverUrl ?: manga?.coverUrl.orEmpty(),
favicon = manga?.source?.faviconUri() ?: Uri.EMPTY,
title = manga?.title.orEmpty(),
altTitle = manga?.altTitle.orEmpty(),
author = manga?.author.orEmpty(),
isNsfw = manga?.isNsfw ?: true,
state = manga?.state ?: MangaState.FINISHED,
source = manga?.source ?: MangaSource.DUMMY,
isTabletUi = false,
appBarPadding = topPadding,
onCoverClick = {
navigateToFullImage(
arrayOf(
manga?.largeCoverUrl ?: manga?.coverUrl.orEmpty(),
).toNavArgument()
)
},
historyInfo = historyInfo,
readingTime = readingTime,
isInShelf = favouriteCategories,
onAddToShelfClicked = {
openCategoriesBottomSheet = !openCategoriesBottomSheet
},
onSourceClicked = {
navigateToSource(
manga?.source ?: MangaSource.DUMMY
)
},
onDownloadClick = downloadCallback
)
} else {
ClassicDetailsInfoBox(
coil = coil,
imageUrl = manga?.largeCoverUrl ?: manga?.coverUrl.orEmpty(),
favicon = manga?.source?.faviconUri() ?: Uri.EMPTY,
title = manga?.title.orEmpty(),
altTitle = manga?.altTitle.orEmpty(),
author = manga?.author.orEmpty(),
isNsfw = manga?.isNsfw ?: true,
state = manga?.state ?: MangaState.FINISHED,
source = manga?.source ?: MangaSource.DUMMY,
isTabletUi = false,
appBarPadding = topPadding,
onCoverClick = {
navigateToFullImage(
arrayOf(
manga?.largeCoverUrl ?: manga?.coverUrl.orEmpty(),
).toNavArgument()
)
},
historyInfo = historyInfo,
readingTime = readingTime,
isInShelf = favouriteCategories,
onAddToShelfClicked = {
openCategoriesBottomSheet = !openCategoriesBottomSheet
},
onSourceClicked = {
navigateToSource(
manga?.source ?: MangaSource.DUMMY
)
},
onDownloadClick = downloadCallback
)
}
}
item(

@ -0,0 +1,129 @@
package org.xtimms.shirizu.sections.details
import android.net.Uri
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.AssistChipDefaults
import androidx.compose.material3.ElevatedAssistChip
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import coil.ImageLoader
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaState
import org.xtimms.shirizu.core.AsyncImageImpl
import org.xtimms.shirizu.sections.details.data.ReadingTime
import org.xtimms.shirizu.sections.details.model.HistoryInfo
@Composable
fun ModernDetailsInfoBox(
coil: ImageLoader,
imageUrl: String,
favicon: Uri,
title: String,
altTitle: String,
author: String,
isNsfw: Boolean,
state: MangaState?,
source: MangaSource,
historyInfo: HistoryInfo,
readingTime: ReadingTime?,
isTabletUi: Boolean,
appBarPadding: Dp,
modifier: Modifier = Modifier,
onCoverClick: () -> Unit,
isInShelf: Boolean,
onAddToShelfClicked: () -> Unit,
onSourceClicked: () -> Unit,
onDownloadClick: () -> Unit,
) {
Column(modifier = modifier) {
Box(
modifier = Modifier
.fillMaxWidth(),
contentAlignment = Alignment.BottomEnd,
) {
AsyncImageImpl(
coil = coil,
model = imageUrl,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.padding(start = 16.dp, end = 16.dp)
.aspectRatio(1f)
.clickable(
role = Role.Button,
onClick = onCoverClick
)
.clip(MaterialTheme.shapes.large)
)
if (isNsfw) {
ElevatedAssistChip(
modifier = Modifier.padding(end = 32.dp, bottom = 8.dp),
onClick = { /*TODO*/ },
label = {
Text(
text = "18+",
color = MaterialTheme.colorScheme.onErrorContainer
)
},
border = BorderStroke(1.dp, MaterialTheme.colorScheme.errorContainer),
colors = AssistChipDefaults.elevatedAssistChipColors()
.copy(containerColor = MaterialTheme.colorScheme.errorContainer)
)
}
}
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) {
if (!isTabletUi) {
MangaAndSourceTitlesSmall(
coil = coil,
favicon = favicon,
title = title,
altTitle = altTitle,
author = author,
state = state,
source = source,
isInShelf = isInShelf,
onAddToShelfClicked = onAddToShelfClicked,
onSourceClicked = onSourceClicked,
historyInfo = historyInfo,
readingTime = readingTime,
onDownloadClick = onDownloadClick
)
} else {
MangaAndSourceTitlesLarge(
coil = coil,
appBarPadding = appBarPadding,
imageUrl = imageUrl,
favicon = favicon,
title = title,
altTitle = altTitle,
author = author,
state = state,
source = source,
isInShelf = isInShelf,
onAddToShelfClicked = onAddToShelfClicked,
onSourceClicked = onSourceClicked,
historyInfo = historyInfo,
readingTime = readingTime,
onDownloadClick = onDownloadClick
)
}
}
}
}

@ -45,7 +45,7 @@ import org.xtimms.shirizu.core.components.effects.RowEntity
import org.xtimms.shirizu.core.components.effects.RowEntityType
import org.xtimms.shirizu.core.components.effects.animatedItemsIndexed
import org.xtimms.shirizu.core.components.effects.updateAnimatedItemsState
import org.xtimms.shirizu.core.screens.EmptyScreen
import org.xtimms.shirizu.core.ui.screens.EmptyScreen
import org.xtimms.shirizu.core.tracker.model.TrackingLogItem
import org.xtimms.shirizu.sections.feed.model.toFeedItem
import org.xtimms.shirizu.utils.lang.calculateTimeAgo

@ -1,24 +1,17 @@
package org.xtimms.shirizu.sections.history
//noinspection UsingMaterialAndMaterial3Libraries
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.AnimationVector1D
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.gestures.ScrollableState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues
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.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.DismissDirection
import androidx.compose.material.ExperimentalMaterialApi
@ -43,14 +36,12 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.min
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil.ImageLoader
import org.xtimms.shirizu.R
import org.xtimms.shirizu.core.collapsable
import org.xtimms.shirizu.core.components.ListGroupHeader
import org.xtimms.shirizu.core.components.effects.RowEntity
import org.xtimms.shirizu.core.components.effects.RowEntityType
@ -58,8 +49,8 @@ import org.xtimms.shirizu.core.components.effects.animatedItemsIndexed
import org.xtimms.shirizu.core.components.effects.updateAnimatedItemsState
import org.xtimms.shirizu.core.prefs.AppSettings
import org.xtimms.shirizu.core.prefs.SWIPE_TUTORIAL
import org.xtimms.shirizu.core.screens.EmptyScreen
import org.xtimms.shirizu.core.screens.LoadingScreen
import org.xtimms.shirizu.core.ui.screens.EmptyScreen
import org.xtimms.shirizu.core.ui.screens.LoadingScreen
import org.xtimms.shirizu.utils.lang.calculateTimeAgo
import org.xtimms.shirizu.utils.lang.isSameDay
import java.time.Instant

@ -34,7 +34,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import org.xtimms.shirizu.R
import org.xtimms.shirizu.core.components.BackIconButton
import org.xtimms.shirizu.core.screens.EmptyScreen
import org.xtimms.shirizu.core.ui.screens.EmptyScreen
import org.xtimms.shirizu.ui.theme.ShirizuTheme
const val SEARCH_DESTINATION = "search"

@ -15,8 +15,11 @@ import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
@ -30,6 +33,9 @@ import androidx.compose.material.icons.outlined.Palette
import androidx.compose.material.icons.outlined.SettingsBackupRestore
import androidx.compose.material.icons.outlined.Storage
import androidx.compose.material.icons.outlined.Wifi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@ -37,18 +43,22 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.xtimms.shirizu.R
import org.xtimms.shirizu.core.components.BackIconButton
import org.xtimms.shirizu.core.components.PreferencesHintCard
import org.xtimms.shirizu.core.components.ScaffoldWithTopAppBar
import org.xtimms.shirizu.core.components.SettingItem
import org.xtimms.shirizu.core.components.SettingTitle
import org.xtimms.shirizu.core.components.SmallTopAppBar
import org.xtimms.shirizu.utils.FileSize
const val SETTINGS_DESTINATION = "settings"
@OptIn(ExperimentalMaterial3Api::class)
@SuppressLint("BatteryLife")
@Composable
fun SettingsView(
@ -76,6 +86,8 @@ fun SettingsView(
mutableStateOf(!pm.isIgnoringBatteryOptimizations(context.packageName))
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val intent =
Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply {
data = Uri.parse("package:${context.packageName}")
@ -96,9 +108,22 @@ fun SettingsView(
showBatteryHint = !pm.isIgnoringBatteryOptimizations(context.packageName)
}
ScaffoldWithTopAppBar(
title = stringResource(R.string.settings),
navigateBack = navigateBack
Scaffold(
modifier = Modifier
.fillMaxSize()
.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
SmallTopAppBar(
titleText = stringResource(id = R.string.settings),
navigationIcon = {
BackIconButton {
navigateBack()
}
},
scrollBehavior = scrollBehavior
)
},
contentWindowInsets = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal),
) { padding ->
LazyColumn(
modifier = Modifier.padding(padding),
@ -106,6 +131,9 @@ fun SettingsView(
bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
)
) {
item {
SettingTitle(text = stringResource(id = R.string.settings))
}
item {
AnimatedVisibility(
visible = showBatteryHint && isActivityAvailable,

@ -31,8 +31,8 @@ import androidx.compose.material.icons.outlined.Check
import androidx.compose.material.icons.outlined.ColorLens
import androidx.compose.material.icons.outlined.DarkMode
import androidx.compose.material.icons.outlined.Language
import androidx.compose.material.icons.outlined.Layers
import androidx.compose.material.icons.outlined.LightMode
import androidx.compose.material.icons.outlined.Timelapse
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
@ -72,7 +72,7 @@ import org.xtimms.shirizu.core.components.ScaffoldWithTopAppBar
import org.xtimms.shirizu.core.prefs.AppSettings
import org.xtimms.shirizu.core.prefs.DarkThemePreference.Companion.OFF
import org.xtimms.shirizu.core.prefs.DarkThemePreference.Companion.ON
import org.xtimms.shirizu.core.prefs.READING_TIME
import org.xtimms.shirizu.core.prefs.MODERN_VIEW
import org.xtimms.shirizu.core.prefs.STYLE_MONOCHROME
import org.xtimms.shirizu.core.prefs.STYLE_TONAL_SPOT
import org.xtimms.shirizu.core.prefs.paletteStyles
@ -85,7 +85,6 @@ import org.xtimms.shirizu.ui.monet.TonalPalettes.Companion.toTonalPalettes
import org.xtimms.shirizu.ui.monet.a1
import org.xtimms.shirizu.ui.monet.a2
import org.xtimms.shirizu.ui.monet.a3
import org.xtimms.shirizu.utils.material.combineColors
import org.xtimms.shirizu.utils.system.toDisplayName
import java.util.Locale
@ -101,6 +100,10 @@ fun AppearanceView(
) {
val localDensity = LocalDensity.current
var isModernViewEnabled by remember {
mutableStateOf(AppSettings.isModernViewEnabled())
}
ScaffoldWithTopAppBar(
title = stringResource(R.string.appearance),
navigateBack = navigateBack
@ -246,6 +249,15 @@ fun AppearanceView(
icon = Icons.Outlined.Language,
description = Locale.getDefault().toDisplayName(),
onClick = { navigateToLanguages() })
PreferenceSubtitle(text = stringResource(id = R.string.user_interface))
PreferenceSwitch(
icon = Icons.Outlined.Layers,
title = stringResource(id = R.string.details_modern_look),
isChecked = isModernViewEnabled,
) {
isModernViewEnabled = !isModernViewEnabled
AppSettings.updateValue(MODERN_VIEW, isModernViewEnabled)
}
}
}
}
@ -286,8 +298,12 @@ fun RowScope.ColorButtonImpl(
onClick: () -> Unit = {}
) {
val containerSize by animateDpAsState(targetValue = if (isSelected.invoke()) 28.dp else 0.dp)
val iconSize by animateDpAsState(targetValue = if (isSelected.invoke()) 16.dp else 0.dp)
val containerSize by animateDpAsState(targetValue = if (isSelected.invoke()) 28.dp else 0.dp,
label = "containerSize"
)
val iconSize by animateDpAsState(targetValue = if (isSelected.invoke()) 16.dp else 0.dp,
label = "iconSize"
)
Surface(
modifier = modifier

@ -66,6 +66,7 @@ import org.xtimms.shirizu.utils.MaskVisualTransformation
import org.xtimms.shirizu.utils.NumberDefaults.INPUT_LENGTH
import org.xtimms.shirizu.utils.NumberDefaults.MASK
import org.xtimms.shirizu.utils.NumberDefaults.MAX_PORT
import org.xtimms.shirizu.utils.lang.ifNullOrEmpty
import org.xtimms.shirizu.utils.lang.intState
import java.net.Proxy
@ -175,14 +176,14 @@ fun NetworkView(
PreferenceItem(
enabled = proxy != Proxy.Type.DIRECT.ordinal,
title = stringResource(id = R.string.proxy_address),
description = address,
description = address.ifNullOrEmpty { stringResource(id = R.string.not_set) },
) { showProxyAddressDialog = true }
}
item {
PreferenceItem(
enabled = proxy != Proxy.Type.DIRECT.ordinal,
title = stringResource(id = R.string.proxy_port),
description = port.toString()
description = if (port == 0) stringResource(id = R.string.not_set) else port.toString()
) { showProxyPortDialog = true }
}
item {
@ -192,14 +193,14 @@ fun NetworkView(
PreferenceItem(
enabled = proxy != Proxy.Type.DIRECT.ordinal,
title = stringResource(id = R.string.proxy_username),
description = username,
description = username.ifNullOrEmpty { stringResource(id = R.string.not_set) },
) { showProxyUsernameDialog = true }
}
item {
PreferenceItem(
enabled = proxy != Proxy.Type.DIRECT.ordinal,
title = stringResource(id = R.string.proxy_password),
description = String(CharArray(password.length) { '\u2022' }),
description = String(CharArray(password.length) { '\u2022' }).ifNullOrEmpty { stringResource(id = R.string.not_set) },
) { showProxyPasswordDialog = true }
}
}

@ -3,50 +3,60 @@ package org.xtimms.shirizu.sections.settings.sources.catalog
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Label
import androidx.compose.material.icons.outlined.Add
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import coil.ImageLoader
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.xtimms.shirizu.core.AsyncImageImpl
import org.xtimms.shirizu.core.parser.favicon.faviconUri
import org.xtimms.shirizu.ui.theme.ShirizuTheme
@Composable
fun SourceCatalogItem(
coil: ImageLoader,
source: MangaSource,
modifier: Modifier = Modifier,
) {
Card(
modifier = modifier,
Row(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Row(
AsyncImageImpl(
modifier = Modifier.size(42.dp),
coil = coil,
contentDescription = null,
model = source.faviconUri()
)
Text(
text = source.title,
modifier = Modifier
.fillMaxWidth()
.padding(
start = 16.dp,
top = 16.dp,
end = 16.dp,
),
verticalAlignment = Alignment.CenterVertically,
) {
AsyncImageImpl(
coil = coil,
contentDescription = null,
model = source.faviconUri()
)
Text(
text = source.title,
modifier = Modifier
.padding(start = 16.dp),
)
.padding(start = 16.dp)
.weight(1f),
)
IconButton(onClick = { /*TODO*/ }) {
Icon(imageVector = Icons.Outlined.Add, contentDescription = null)
}
}
}
@Preview
@Composable
fun SourceCatalogItemPreview() {
ShirizuTheme {
SourceCatalogItem(coil = ImageLoader(LocalContext.current), source = MangaSource.MANGADEX)
}
}

@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState
@ -17,14 +16,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastAny
import coil.ImageLoader
import org.xtimms.shirizu.R
import org.xtimms.shirizu.core.components.MangaGridItem
import org.xtimms.shirizu.core.screens.EmptyScreen
import org.xtimms.shirizu.sections.shelf.LazyShelfGrid
import org.xtimms.shirizu.sections.shelf.ShelfGrid
import org.xtimms.shirizu.sections.shelf.ShelfManga
import org.xtimms.shirizu.core.ui.screens.EmptyScreen
import org.xtimms.shirizu.utils.system.plus
@Composable

@ -17,7 +17,7 @@ import androidx.compose.ui.unit.dp
import coil.ImageLoader
import org.xtimms.shirizu.R
import org.xtimms.shirizu.core.prefs.AppSettings
import org.xtimms.shirizu.core.screens.EmptyScreen
import org.xtimms.shirizu.core.ui.screens.EmptyScreen
import org.xtimms.shirizu.utils.system.plus
@Composable

@ -306,4 +306,6 @@
<string name="open_menu">Open menu</string>
<string name="crash_screen_something_went_wrong">My bad…</string>
<string name="crash_screen_toast">Logs about this bug have been sent to the developers, thank you.</string>
<string name="user_interface">User interface</string>
<string name="details_modern_look">Modern look of the manga information screen</string>
</resources>
Loading…
Cancel
Save