Add new manga screen variant
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user