Migrate top reader app bar to Compose

(cherry picked from commit d18022c25990f1961fef77eabb3924c68f283250)

# Conflicts:
#	app/src/main/java/eu/kanade/presentation/reader/appbars/BottomReaderBar.kt
#	app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt
#	app/src/main/java/eu/kanade/tachiyomi/widget/listener/SimpleAnimationListener.kt
#	app/src/main/res/anim/enter_from_top.xml
#	app/src/main/res/anim/exit_to_top.xml
#	app/src/main/res/layout/reader_activity.xml
#	app/src/main/res/menu/reader.xml
This commit is contained in:
arkon
2023-10-14 12:30:17 -04:00
committed by Jobobby04
parent 868a27110a
commit 3842056d9c
15 changed files with 626 additions and 657 deletions
@@ -1,7 +1,6 @@
package eu.kanade.presentation.reader.appbars
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
@@ -13,11 +12,10 @@ import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material.icons.outlined.Share
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@@ -31,6 +29,7 @@ fun BottomReaderBar(
// SY -->
enabledButtons: Set<String>,
// SY <--
backgroundColor: Color,
readingMode: ReadingModeType,
onClickReadingMode: () -> Unit,
orientationMode: OrientationType,
@@ -39,21 +38,15 @@ fun BottomReaderBar(
onClickCropBorder: () -> Unit,
onClickSettings: () -> Unit,
// SY -->
isHttpSource: Boolean,
dualPageSplitEnabled: Boolean,
doublePages: Boolean,
onClickChapterList: () -> Unit,
onClickWebView: () -> Unit,
onClickShare: () -> Unit,
onClickWebView: (() -> Unit)?,
onClickShare: (() -> Unit)?,
onClickPageLayout: () -> Unit,
onClickShiftPage: () -> Unit,
// SY <--
) {
// Match with toolbar background color set in ReaderActivity
val backgroundColor = MaterialTheme.colorScheme
.surfaceColorAtElevation(3.dp)
.copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f)
Row(
modifier = Modifier
.fillMaxWidth()
@@ -72,7 +65,7 @@ fun BottomReaderBar(
}
}
if (ReaderBottomButton.WebView.isIn(enabledButtons) && isHttpSource) {
if (ReaderBottomButton.WebView.isIn(enabledButtons) && onClickWebView != null) {
IconButton(onClick = onClickWebView) {
Icon(
imageVector = Icons.Outlined.Public,
@@ -81,7 +74,7 @@ fun BottomReaderBar(
}
}
if (ReaderBottomButton.Share.isIn(enabledButtons) && isHttpSource) {
if (ReaderBottomButton.Share.isIn(enabledButtons) && onClickShare != null) {
IconButton(onClick = onClickShare) {
Icon(
imageVector = Icons.Outlined.Share,
@@ -0,0 +1,243 @@
package eu.kanade.presentation.reader.appbars
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.KeyboardArrowDown
import androidx.compose.material.icons.outlined.KeyboardArrowUp
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.R
import tachiyomi.presentation.core.util.ThemePreviews
@Composable
fun ExhUtils(
modifier: Modifier = Modifier,
isVisible: Boolean,
onSetExhUtilsVisibility: (Boolean) -> Unit,
backgroundColor: Color,
isAutoScroll: Boolean,
isAutoScrollEnabled: Boolean,
onToggleAutoscroll: (Boolean) -> Unit,
autoScrollFrequency: String,
onSetAutoScrollFrequency: (String) -> Unit,
onClickAutoScrollHelp: () -> Unit,
onClickRetryAll: () -> Unit,
onClickRetryAllHelp: () -> Unit,
onClickBoostPage: () -> Unit,
onClickBoostPageHelp: () -> Unit,
) {
Column(
modifier
.fillMaxWidth()
.background(backgroundColor)
) {
AnimatedVisibility(visible = isVisible) {
Column {
Row(
Modifier.fillMaxWidth().height(IntrinsicSize.Min),
verticalAlignment = Alignment.CenterVertically,
) {
Row(
Modifier
.fillMaxWidth(0.5f)
.fillMaxHeight()
.clickable(enabled = isAutoScrollEnabled) { onToggleAutoscroll(!isAutoScroll) },
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = stringResource(R.string.eh_autoscroll),
color = MaterialTheme.colorScheme.onSurface,
fontSize = 13.sp,
fontFamily = FontFamily.SansSerif,
style = MaterialTheme.typography.labelLarge,
modifier = Modifier.padding(start = 24.dp)
)
Switch(
checked = isAutoScroll,
onCheckedChange = null,
enabled = isAutoScrollEnabled
)
}
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Column(Modifier.weight(3f)) {
var autoScrollFrequencyState by remember {
mutableStateOf(autoScrollFrequency)
}
TextField(
value = autoScrollFrequencyState,
onValueChange = {
autoScrollFrequencyState = it
onSetAutoScrollFrequency(it)
},
isError = !isAutoScrollEnabled,
singleLine = true,
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
focusedTextColor = MaterialTheme.colorScheme.onSurface,
unfocusedTextColor = MaterialTheme.colorScheme.onSurface
),
modifier = Modifier.fillMaxWidth(),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Decimal
),
)
AnimatedVisibility(!isAutoScrollEnabled) {
Text(
text = stringResource(R.string.eh_autoscroll_freq_invalid),
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.labelSmall
)
}
}
TextButton(
onClick = onClickAutoScrollHelp,
modifier = Modifier.weight(1f),
) {
Text(
text = "?",
color = MaterialTheme.colorScheme.onSurface,
fontSize = 15.sp,
fontWeight = FontWeight.Bold,
)
}
}
}
Row(
Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
Row(
Modifier.fillMaxWidth(0.5f),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
TextButton(
onClick = onClickRetryAll,
modifier = Modifier.weight(3f),
) {
Text(
text = stringResource(R.string.eh_retry_all),
color = MaterialTheme.colorScheme.onSurface,
fontSize = 13.sp,
fontFamily = FontFamily.SansSerif
)
}
TextButton(
onClick = onClickRetryAllHelp,
modifier = Modifier.weight(1f),
) {
Text(
text = "?",
color = MaterialTheme.colorScheme.onSurface,
fontSize = 15.sp,
fontWeight = FontWeight.Bold,
)
}
}
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
TextButton(
onClick = onClickBoostPage,
modifier = Modifier.weight(3f),
) {
Text(
text = stringResource(R.string.eh_boost_page),
color = MaterialTheme.colorScheme.onSurface,
fontSize = 13.sp,
fontFamily = FontFamily.SansSerif
)
}
TextButton(
onClick = onClickBoostPageHelp,
modifier = Modifier.weight(1f),
) {
Text(
text = "?",
color = MaterialTheme.colorScheme.onSurface,
fontSize = 15.sp,
fontWeight = FontWeight.Bold,
)
}
}
}
}
}
IconButton(
onClick = { onSetExhUtilsVisibility(!isVisible) },
modifier = Modifier.fillMaxWidth()
) {
Icon(
imageVector = if (isVisible) {
Icons.Outlined.KeyboardArrowUp
} else {
Icons.Outlined.KeyboardArrowDown
},
contentDescription = null,
)
}
}
}
@Composable
@ThemePreviews
private fun ExhUtilsPreview() {
TachiyomiTheme {
ExhUtils(
isVisible = true,
onSetExhUtilsVisibility = {},
backgroundColor = Color.Black,
isAutoScroll = true,
isAutoScrollEnabled = true,
onToggleAutoscroll = {},
autoScrollFrequency = "3.0",
onSetAutoScrollFrequency = {},
onClickAutoScrollHelp = {},
onClickBoostPage = {},
onClickBoostPageHelp = {},
onClickRetryAll = {},
onClickRetryAllHelp = {}
)
}
}
@@ -6,14 +6,23 @@ import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
@@ -22,6 +31,7 @@ import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import eu.kanade.presentation.components.AppBar
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
@@ -56,8 +66,18 @@ fun BoxIgnoreLayoutDirection(modifier: Modifier, content: @Composable BoxScope.(
@Composable
fun ReaderAppBars(
visible: Boolean,
viewer: Viewer?,
fullscreen: Boolean,
mangaTitle: String?,
chapterTitle: String?,
navigateUp: () -> Unit,
onClickTopAppBar: () -> Unit,
// bookmarked: Boolean,
// onToggleBookmarked: () -> Unit,
onOpenInWebView: (() -> Unit)?,
onShare: (() -> Unit)?,
viewer: Viewer?,
onNextChapter: () -> Unit,
enabledNext: Boolean,
onPreviousChapter: () -> Unit,
@@ -74,20 +94,40 @@ fun ReaderAppBars(
onClickCropBorder: () -> Unit,
onClickSettings: () -> Unit,
// SY -->
isExhToolsVisible: Boolean,
onSetExhUtilsVisibility: (Boolean) -> Unit,
isAutoScroll: Boolean,
isAutoScrollEnabled: Boolean,
onToggleAutoscroll: (Boolean) -> Unit,
autoScrollFrequency: String,
onSetAutoScrollFrequency: (String) -> Unit,
onClickAutoScrollHelp: () -> Unit,
onClickRetryAll: () -> Unit,
onClickRetryAllHelp: () -> Unit,
onClickBoostPage: () -> Unit,
onClickBoostPageHelp: () -> Unit,
navBarType: NavBarType,
currentPageText: String,
enabledButtons: Set<String>,
isHttpSource: Boolean,
dualPageSplitEnabled: Boolean,
doublePages: Boolean,
onClickChapterList: () -> Unit,
onClickWebView: () -> Unit,
onClickShare: () -> Unit,
onClickPageLayout: () -> Unit,
onClickShiftPage: () -> Unit,
) {
val isRtl = viewer is R2LPagerViewer
val backgroundColor = MaterialTheme.colorScheme
.surfaceColorAtElevation(3.dp)
.copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f)
val appBarModifier = if (fullscreen) {
// SY -->
Modifier.windowInsetsPadding(WindowInsets.systemBars.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal))
// SY <--
} else {
Modifier
}
// SY -->
@@ -104,7 +144,8 @@ fun ReaderAppBars(
targetOffsetX = { -it },
animationSpec = animationSpec,
),
modifier = Modifier.padding(bottom = 48.dp, top = 120.dp)
modifier = Modifier
.padding(bottom = 48.dp, top = 120.dp)
.align(Alignment.TopStart)
) {
ChapterNavigator(
@@ -131,7 +172,8 @@ fun ReaderAppBars(
targetOffsetX = { it },
animationSpec = animationSpec,
),
modifier = Modifier.padding(bottom = 48.dp, top = 120.dp)
modifier = Modifier
.padding(bottom = 48.dp, top = 120.dp)
.align(Alignment.TopEnd)
) {
ChapterNavigator(
@@ -152,6 +194,72 @@ fun ReaderAppBars(
modifier = Modifier.fillMaxHeight(),
verticalArrangement = Arrangement.SpaceBetween,
) {
AnimatedVisibility(
visible = visible,
enter = slideInVertically(
initialOffsetY = { -it },
animationSpec = animationSpec,
),
exit = slideOutVertically(
targetOffsetY = { -it },
animationSpec = animationSpec,
),
) {
// SY -->
Column(appBarModifier) {
// SY <--
AppBar(
modifier = /*SY --> */ Modifier /*SY <-- */
.clickable(onClick = onClickTopAppBar),
backgroundColor = backgroundColor,
title = mangaTitle,
subtitle = chapterTitle,
navigateUp = navigateUp,
/* SY --> actions = {
AppBarActions(
listOfNotNull(
AppBar.Action(
title = stringResource(if (bookmarked) R.string.action_remove_bookmark else R.string.action_bookmark),
icon = if (bookmarked) Icons.Outlined.Bookmark else Icons.Outlined.BookmarkBorder,
onClick = onToggleBookmarked,
),
onOpenInWebView?.let {
AppBar.OverflowAction(
title = stringResource(R.string.action_open_in_web_view),
onClick = it,
)
},
onShare?.let {
AppBar.OverflowAction(
title = stringResource(R.string.action_share),
onClick = it,
)
},
),
)
}, SY <-- */
)
// SY -->
ExhUtils(
isVisible = isExhToolsVisible,
onSetExhUtilsVisibility = onSetExhUtilsVisibility,
backgroundColor = backgroundColor,
isAutoScroll = isAutoScroll,
isAutoScrollEnabled = isAutoScrollEnabled,
onToggleAutoscroll = onToggleAutoscroll,
autoScrollFrequency = autoScrollFrequency,
onSetAutoScrollFrequency = onSetAutoScrollFrequency,
onClickAutoScrollHelp = onClickAutoScrollHelp,
onClickRetryAll = onClickRetryAll,
onClickRetryAllHelp = onClickRetryAllHelp,
onClickBoostPage = onClickBoostPage,
onClickBoostPageHelp = onClickBoostPageHelp
)
// SY <--
}
}
Spacer(modifier = Modifier.weight(1f))
AnimatedVisibility(
@@ -187,6 +295,7 @@ fun ReaderAppBars(
// SY -->
enabledButtons = enabledButtons,
// SY <--
backgroundColor = backgroundColor,
readingMode = readingMode,
onClickReadingMode = onClickReadingMode,
orientationMode = orientationMode,
@@ -195,12 +304,11 @@ fun ReaderAppBars(
onClickCropBorder = onClickCropBorder,
onClickSettings = onClickSettings,
// SY -->
isHttpSource = isHttpSource,
dualPageSplitEnabled = dualPageSplitEnabled,
doublePages = doublePages,
onClickChapterList = onClickChapterList,
onClickWebView = onClickWebView,
onClickShare = onClickShare,
onClickWebView = onOpenInWebView,
onClickShare = onShare,
onClickPageLayout = onClickPageLayout,
onClickShiftPage = onClickShiftPage
)