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:
parent
868a27110a
commit
3842056d9c
@ -1,5 +1,6 @@
|
|||||||
package eu.kanade.presentation.components
|
package eu.kanade.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.basicMarquee
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
@ -60,6 +61,7 @@ const val SEARCH_DEBOUNCE_MILLIS = 250L
|
|||||||
@Composable
|
@Composable
|
||||||
fun AppBar(
|
fun AppBar(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
backgroundColor: Color? = null,
|
||||||
// Text
|
// Text
|
||||||
title: String?,
|
title: String?,
|
||||||
subtitle: String? = null,
|
subtitle: String? = null,
|
||||||
@ -81,6 +83,7 @@ fun AppBar(
|
|||||||
|
|
||||||
AppBar(
|
AppBar(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
backgroundColor = backgroundColor,
|
||||||
titleContent = {
|
titleContent = {
|
||||||
if (isActionMode) {
|
if (isActionMode) {
|
||||||
AppBarTitle(actionModeCounter.toString())
|
AppBarTitle(actionModeCounter.toString())
|
||||||
@ -106,6 +109,7 @@ fun AppBar(
|
|||||||
@Composable
|
@Composable
|
||||||
fun AppBar(
|
fun AppBar(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
backgroundColor: Color? = null,
|
||||||
// Title
|
// Title
|
||||||
titleContent: @Composable () -> Unit,
|
titleContent: @Composable () -> Unit,
|
||||||
// Up button
|
// Up button
|
||||||
@ -142,7 +146,7 @@ fun AppBar(
|
|||||||
title = titleContent,
|
title = titleContent,
|
||||||
actions = actions,
|
actions = actions,
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
|
containerColor = backgroundColor ?: MaterialTheme.colorScheme.surfaceColorAtElevation(
|
||||||
elevation = if (isActionMode) 3.dp else 0.dp,
|
elevation = if (isActionMode) 3.dp else 0.dp,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -170,6 +174,9 @@ fun AppBarTitle(
|
|||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.basicMarquee(
|
||||||
|
delayMillis = 2_000,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package eu.kanade.presentation.reader.appbars
|
package eu.kanade.presentation.reader.appbars
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
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.material.icons.outlined.Share
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.surfaceColorAtElevation
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@ -31,6 +29,7 @@ fun BottomReaderBar(
|
|||||||
// SY -->
|
// SY -->
|
||||||
enabledButtons: Set<String>,
|
enabledButtons: Set<String>,
|
||||||
// SY <--
|
// SY <--
|
||||||
|
backgroundColor: Color,
|
||||||
readingMode: ReadingModeType,
|
readingMode: ReadingModeType,
|
||||||
onClickReadingMode: () -> Unit,
|
onClickReadingMode: () -> Unit,
|
||||||
orientationMode: OrientationType,
|
orientationMode: OrientationType,
|
||||||
@ -39,21 +38,15 @@ fun BottomReaderBar(
|
|||||||
onClickCropBorder: () -> Unit,
|
onClickCropBorder: () -> Unit,
|
||||||
onClickSettings: () -> Unit,
|
onClickSettings: () -> Unit,
|
||||||
// SY -->
|
// SY -->
|
||||||
isHttpSource: Boolean,
|
|
||||||
dualPageSplitEnabled: Boolean,
|
dualPageSplitEnabled: Boolean,
|
||||||
doublePages: Boolean,
|
doublePages: Boolean,
|
||||||
onClickChapterList: () -> Unit,
|
onClickChapterList: () -> Unit,
|
||||||
onClickWebView: () -> Unit,
|
onClickWebView: (() -> Unit)?,
|
||||||
onClickShare: () -> Unit,
|
onClickShare: (() -> Unit)?,
|
||||||
onClickPageLayout: () -> Unit,
|
onClickPageLayout: () -> Unit,
|
||||||
onClickShiftPage: () -> Unit,
|
onClickShiftPage: () -> Unit,
|
||||||
// SY <--
|
// 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(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@ -72,7 +65,7 @@ fun BottomReaderBar(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ReaderBottomButton.WebView.isIn(enabledButtons) && isHttpSource) {
|
if (ReaderBottomButton.WebView.isIn(enabledButtons) && onClickWebView != null) {
|
||||||
IconButton(onClick = onClickWebView) {
|
IconButton(onClick = onClickWebView) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Outlined.Public,
|
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) {
|
IconButton(onClick = onClickShare) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Outlined.Share,
|
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.slideInVertically
|
||||||
import androidx.compose.animation.slideOutHorizontally
|
import androidx.compose.animation.slideOutHorizontally
|
||||||
import androidx.compose.animation.slideOutVertically
|
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.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
import androidx.compose.foundation.layout.BoxScope
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
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.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
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.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.ui.Alignment
|
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.IntOffset
|
||||||
import androidx.compose.ui.unit.LayoutDirection
|
import androidx.compose.ui.unit.LayoutDirection
|
||||||
import androidx.compose.ui.unit.dp
|
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.OrientationType
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
|
import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
|
||||||
@ -56,8 +66,18 @@ fun BoxIgnoreLayoutDirection(modifier: Modifier, content: @Composable BoxScope.(
|
|||||||
@Composable
|
@Composable
|
||||||
fun ReaderAppBars(
|
fun ReaderAppBars(
|
||||||
visible: Boolean,
|
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,
|
onNextChapter: () -> Unit,
|
||||||
enabledNext: Boolean,
|
enabledNext: Boolean,
|
||||||
onPreviousChapter: () -> Unit,
|
onPreviousChapter: () -> Unit,
|
||||||
@ -74,20 +94,40 @@ fun ReaderAppBars(
|
|||||||
onClickCropBorder: () -> Unit,
|
onClickCropBorder: () -> Unit,
|
||||||
onClickSettings: () -> Unit,
|
onClickSettings: () -> Unit,
|
||||||
// SY -->
|
// 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,
|
navBarType: NavBarType,
|
||||||
currentPageText: String,
|
currentPageText: String,
|
||||||
enabledButtons: Set<String>,
|
enabledButtons: Set<String>,
|
||||||
isHttpSource: Boolean,
|
|
||||||
dualPageSplitEnabled: Boolean,
|
dualPageSplitEnabled: Boolean,
|
||||||
doublePages: Boolean,
|
doublePages: Boolean,
|
||||||
onClickChapterList: () -> Unit,
|
onClickChapterList: () -> Unit,
|
||||||
onClickWebView: () -> Unit,
|
|
||||||
onClickShare: () -> Unit,
|
|
||||||
onClickPageLayout: () -> Unit,
|
onClickPageLayout: () -> Unit,
|
||||||
onClickShiftPage: () -> Unit,
|
onClickShiftPage: () -> Unit,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
val isRtl = viewer is R2LPagerViewer
|
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 -->
|
// SY -->
|
||||||
@ -104,7 +144,8 @@ fun ReaderAppBars(
|
|||||||
targetOffsetX = { -it },
|
targetOffsetX = { -it },
|
||||||
animationSpec = animationSpec,
|
animationSpec = animationSpec,
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(bottom = 48.dp, top = 120.dp)
|
modifier = Modifier
|
||||||
|
.padding(bottom = 48.dp, top = 120.dp)
|
||||||
.align(Alignment.TopStart)
|
.align(Alignment.TopStart)
|
||||||
) {
|
) {
|
||||||
ChapterNavigator(
|
ChapterNavigator(
|
||||||
@ -131,7 +172,8 @@ fun ReaderAppBars(
|
|||||||
targetOffsetX = { it },
|
targetOffsetX = { it },
|
||||||
animationSpec = animationSpec,
|
animationSpec = animationSpec,
|
||||||
),
|
),
|
||||||
modifier = Modifier.padding(bottom = 48.dp, top = 120.dp)
|
modifier = Modifier
|
||||||
|
.padding(bottom = 48.dp, top = 120.dp)
|
||||||
.align(Alignment.TopEnd)
|
.align(Alignment.TopEnd)
|
||||||
) {
|
) {
|
||||||
ChapterNavigator(
|
ChapterNavigator(
|
||||||
@ -152,6 +194,72 @@ fun ReaderAppBars(
|
|||||||
modifier = Modifier.fillMaxHeight(),
|
modifier = Modifier.fillMaxHeight(),
|
||||||
verticalArrangement = Arrangement.SpaceBetween,
|
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))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
@ -187,6 +295,7 @@ fun ReaderAppBars(
|
|||||||
// SY -->
|
// SY -->
|
||||||
enabledButtons = enabledButtons,
|
enabledButtons = enabledButtons,
|
||||||
// SY <--
|
// SY <--
|
||||||
|
backgroundColor = backgroundColor,
|
||||||
readingMode = readingMode,
|
readingMode = readingMode,
|
||||||
onClickReadingMode = onClickReadingMode,
|
onClickReadingMode = onClickReadingMode,
|
||||||
orientationMode = orientationMode,
|
orientationMode = orientationMode,
|
||||||
@ -195,12 +304,11 @@ fun ReaderAppBars(
|
|||||||
onClickCropBorder = onClickCropBorder,
|
onClickCropBorder = onClickCropBorder,
|
||||||
onClickSettings = onClickSettings,
|
onClickSettings = onClickSettings,
|
||||||
// SY -->
|
// SY -->
|
||||||
isHttpSource = isHttpSource,
|
|
||||||
dualPageSplitEnabled = dualPageSplitEnabled,
|
dualPageSplitEnabled = dualPageSplitEnabled,
|
||||||
doublePages = doublePages,
|
doublePages = doublePages,
|
||||||
onClickChapterList = onClickChapterList,
|
onClickChapterList = onClickChapterList,
|
||||||
onClickWebView = onClickWebView,
|
onClickWebView = onOpenInWebView,
|
||||||
onClickShare = onClickShare,
|
onClickShare = onShare,
|
||||||
onClickPageLayout = onClickPageLayout,
|
onClickPageLayout = onClickPageLayout,
|
||||||
onClickShiftPage = onClickShiftPage
|
onClickShiftPage = onClickShiftPage
|
||||||
)
|
)
|
||||||
|
@ -5,7 +5,6 @@ import android.annotation.TargetApi
|
|||||||
import android.app.assist.AssistContent
|
import android.app.assist.AssistContent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
@ -15,19 +14,11 @@ import android.graphics.Paint
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
|
||||||
import android.text.TextUtils
|
|
||||||
import android.text.TextWatcher
|
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.LAYER_TYPE_HARDWARE
|
import android.view.View.LAYER_TYPE_HARDWARE
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.view.animation.Animation
|
|
||||||
import android.view.animation.AnimationUtils
|
|
||||||
import android.widget.CompoundButton
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@ -35,6 +26,7 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@ -55,9 +47,7 @@ import androidx.lifecycle.Lifecycle
|
|||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.elevation.SurfaceColors
|
||||||
import com.google.android.material.internal.ToolbarUtils
|
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
|
||||||
import com.google.android.material.transition.platform.MaterialContainerTransform
|
import com.google.android.material.transition.platform.MaterialContainerTransform
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
@ -75,6 +65,7 @@ import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
|||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
import eu.kanade.tachiyomi.databinding.ReaderActivityBinding
|
import eu.kanade.tachiyomi.databinding.ReaderActivityBinding
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderViewModel.SetAsCoverResult.AddToLibraryFirst
|
import eu.kanade.tachiyomi.ui.reader.ReaderViewModel.SetAsCoverResult.AddToLibraryFirst
|
||||||
@ -94,22 +85,16 @@ import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerViewer
|
|||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.VerticalPagerViewer
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.VerticalPagerViewer
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
|
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
|
||||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||||
import eu.kanade.tachiyomi.util.system.applySystemAnimatorScale
|
|
||||||
import eu.kanade.tachiyomi.util.system.hasDisplayCutout
|
import eu.kanade.tachiyomi.util.system.hasDisplayCutout
|
||||||
import eu.kanade.tachiyomi.util.system.isNightMode
|
import eu.kanade.tachiyomi.util.system.isNightMode
|
||||||
import eu.kanade.tachiyomi.util.system.toShareIntent
|
import eu.kanade.tachiyomi.util.system.toShareIntent
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.setComposeContent
|
import eu.kanade.tachiyomi.util.view.setComposeContent
|
||||||
import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener
|
|
||||||
import exh.source.isEhBasedSource
|
import exh.source.isEhBasedSource
|
||||||
import exh.util.defaultReaderType
|
import exh.util.defaultReaderType
|
||||||
import exh.util.mangaType
|
import exh.util.mangaType
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.conflate
|
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
@ -118,7 +103,6 @@ import kotlinx.coroutines.flow.map
|
|||||||
import kotlinx.coroutines.flow.mapLatest
|
import kotlinx.coroutines.flow.mapLatest
|
||||||
import kotlinx.coroutines.flow.merge
|
import kotlinx.coroutines.flow.merge
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.onStart
|
|
||||||
import kotlinx.coroutines.flow.sample
|
import kotlinx.coroutines.flow.sample
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
@ -271,19 +255,6 @@ class ReaderActivity : BaseActivity() {
|
|||||||
.launchIn(lifecycleScope)
|
.launchIn(lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SY -->
|
|
||||||
private fun setEhUtilsVisibility(visible: Boolean) {
|
|
||||||
viewModel.showEhUtils(visible)
|
|
||||||
if (visible) {
|
|
||||||
binding.ehUtils.isVisible = true
|
|
||||||
binding.expandEhButton.setImageResource(R.drawable.ic_keyboard_arrow_up_white_32dp)
|
|
||||||
} else {
|
|
||||||
binding.ehUtils.isVisible = false
|
|
||||||
binding.expandEhButton.setImageResource(R.drawable.ic_keyboard_arrow_down_white_32dp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the activity is destroyed. Cleans up the viewer, configuration and any view.
|
* Called when the activity is destroyed. Cleans up the viewer, configuration and any view.
|
||||||
*/
|
*/
|
||||||
@ -326,47 +297,6 @@ class ReaderActivity : BaseActivity() {
|
|||||||
assistUrl?.let { outContent.webUri = it.toUri() }
|
assistUrl?.let { outContent.webUri = it.toUri() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
||||||
menuInflater.inflate(R.menu.reader, menu)
|
|
||||||
|
|
||||||
/*val isChapterBookmarked = viewModel.getCurrentChapter()?.chapter?.bookmark ?: false
|
|
||||||
menu.findItem(R.id.action_bookmark).isVisible = !isChapterBookmarked
|
|
||||||
menu.findItem(R.id.action_remove_bookmark).isVisible = isChapterBookmarked
|
|
||||||
|
|
||||||
val isHttpSource = viewModel.getSource() is HttpSource
|
|
||||||
menu.findItem(R.id.action_open_in_web_view).isVisible = isHttpSource
|
|
||||||
menu.findItem(R.id.action_share).isVisible = isHttpSource*/
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when an item of the options menu was clicked. Used to handle clicks on our menu
|
|
||||||
* entries.
|
|
||||||
*/
|
|
||||||
/*override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
when (item.itemId) {
|
|
||||||
R.id.action_open_in_web_view -> {
|
|
||||||
openChapterInWebView()
|
|
||||||
}
|
|
||||||
R.id.action_bookmark -> {
|
|
||||||
viewModel.bookmarkCurrentChapter(true)
|
|
||||||
invalidateOptionsMenu()
|
|
||||||
}
|
|
||||||
R.id.action_remove_bookmark -> {
|
|
||||||
viewModel.bookmarkCurrentChapter(false)
|
|
||||||
invalidateOptionsMenu()
|
|
||||||
}
|
|
||||||
R.id.action_share -> {
|
|
||||||
assistUrl?.let {
|
|
||||||
val intent = it.toUri().toShareIntent(this, type = "text/plain")
|
|
||||||
startActivity(Intent.createChooser(intent, getString(R.string.action_share)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the user clicks the back key or the button on the toolbar. The call is
|
* Called when the user clicks the back key or the button on the toolbar. The call is
|
||||||
* delegated to the presenter.
|
* delegated to the presenter.
|
||||||
@ -405,69 +335,16 @@ class ReaderActivity : BaseActivity() {
|
|||||||
return handled || super.dispatchGenericMotionEvent(event)
|
return handled || super.dispatchGenericMotionEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SY -->
|
|
||||||
fun TextView.textChanges(): Flow<CharSequence> = callbackFlow {
|
|
||||||
val listener = object : TextWatcher {
|
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) = Unit
|
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
|
||||||
trySend(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun afterTextChanged(s: Editable) = Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
addTextChangedListener(listener)
|
|
||||||
awaitClose { removeTextChangedListener(listener) }
|
|
||||||
}
|
|
||||||
.conflate()
|
|
||||||
.onStart { emit(text) }
|
|
||||||
|
|
||||||
fun CompoundButton.checkedChanges(): Flow<Boolean> = callbackFlow {
|
|
||||||
val listener = CompoundButton.OnCheckedChangeListener { _, isChecked ->
|
|
||||||
trySend(isChecked)
|
|
||||||
}
|
|
||||||
setOnCheckedChangeListener(listener)
|
|
||||||
|
|
||||||
awaitClose { setOnCheckedChangeListener(null) }
|
|
||||||
}
|
|
||||||
.conflate()
|
|
||||||
.onStart { emit(isChecked) }
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the reader menu. It sets up click listeners and the initial visibility.
|
* Initializes the reader menu. It sets up click listeners and the initial visibility.
|
||||||
*/
|
*/
|
||||||
private fun initializeMenu() {
|
private fun initializeMenu() {
|
||||||
setSupportActionBar(binding.toolbar)
|
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
|
||||||
binding.toolbar.setNavigationOnClickListener {
|
|
||||||
onBackPressedDispatcher.onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.header.applyInsetter {
|
|
||||||
type(navigationBars = true, statusBars = true) {
|
|
||||||
margin(top = true, horizontal = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.dialogRoot.applyInsetter {
|
binding.dialogRoot.applyInsetter {
|
||||||
type(navigationBars = true) {
|
type(navigationBars = true) {
|
||||||
margin(vertical = true, horizontal = true)
|
margin(vertical = true, horizontal = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.toolbar.setOnClickListener {
|
|
||||||
viewModel.manga?.id?.let { id ->
|
|
||||||
startActivity(
|
|
||||||
Intent(this, MainActivity::class.java).apply {
|
|
||||||
action = Constants.SHORTCUT_MANGA
|
|
||||||
putExtra(Constants.MANGA_EXTRA, id)
|
|
||||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.pageNumber.setComposeContent {
|
binding.pageNumber.setComposeContent {
|
||||||
val state by viewModel.state.collectAsState()
|
val state by viewModel.state.collectAsState()
|
||||||
val showPageNumber by viewModel.readerPreferences.showPageNumber().collectAsState()
|
val showPageNumber by viewModel.readerPreferences.showPageNumber().collectAsState()
|
||||||
@ -493,6 +370,9 @@ class ReaderActivity : BaseActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isHttpSource = viewModel.getSource() is HttpSource
|
||||||
|
val isFullscreen by readerPreferences.fullscreen().collectAsState()
|
||||||
|
|
||||||
val cropBorderPaged by readerPreferences.cropBorders().collectAsState()
|
val cropBorderPaged by readerPreferences.cropBorders().collectAsState()
|
||||||
val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState()
|
val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState()
|
||||||
// SY -->
|
// SY -->
|
||||||
@ -526,11 +406,20 @@ class ReaderActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
|
|
||||||
ReaderAppBars(
|
ReaderAppBars(
|
||||||
visible = state.menuVisible,
|
visible = state.menuVisible,
|
||||||
viewer = state.viewer,
|
fullscreen = isFullscreen,
|
||||||
|
|
||||||
|
mangaTitle = state.manga?.title,
|
||||||
|
chapterTitle = state.currentChapter?.chapter?.name,
|
||||||
|
navigateUp = onBackPressedDispatcher::onBackPressed,
|
||||||
|
onClickTopAppBar = ::openMangaScreen,
|
||||||
|
// bookmarked = state.bookmarked,
|
||||||
|
// onToggleBookmarked = viewModel::toggleChapterBookmark,
|
||||||
|
onOpenInWebView = ::openChapterInWebView.takeIf { isHttpSource },
|
||||||
|
onShare = ::shareChapter.takeIf { isHttpSource },
|
||||||
|
|
||||||
|
viewer = state.viewer,
|
||||||
onNextChapter = ::loadNextChapter,
|
onNextChapter = ::loadNextChapter,
|
||||||
enabledNext = state.viewerChapters?.nextChapter != null,
|
enabledNext = state.viewerChapters?.nextChapter != null,
|
||||||
onPreviousChapter = ::loadPreviousChapter,
|
onPreviousChapter = ::loadPreviousChapter,
|
||||||
@ -557,34 +446,29 @@ class ReaderActivity : BaseActivity() {
|
|||||||
cropEnabled = cropEnabled,
|
cropEnabled = cropEnabled,
|
||||||
onClickCropBorder = {
|
onClickCropBorder = {
|
||||||
val enabled = viewModel.toggleCropBorders()
|
val enabled = viewModel.toggleCropBorders()
|
||||||
|
|
||||||
menuToggleToast?.cancel()
|
menuToggleToast?.cancel()
|
||||||
menuToggleToast = toast(
|
menuToggleToast = toast(if (enabled) R.string.on else R.string.off)
|
||||||
if (enabled) {
|
|
||||||
R.string.on
|
|
||||||
} else {
|
|
||||||
R.string.off
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
onClickSettings = viewModel::openSettingsDialog,
|
onClickSettings = viewModel::openSettingsDialog,
|
||||||
// SY -->
|
// SY -->
|
||||||
|
isExhToolsVisible = state.ehUtilsVisible,
|
||||||
|
onSetExhUtilsVisibility = viewModel::showEhUtils,
|
||||||
|
isAutoScroll = state.autoScroll,
|
||||||
|
isAutoScrollEnabled = state.isAutoScrollEnabled,
|
||||||
|
onToggleAutoscroll = viewModel::toggleAutoScroll,
|
||||||
|
autoScrollFrequency = state.ehAutoscrollFreq,
|
||||||
|
onSetAutoScrollFrequency = viewModel::setAutoScrollFrequency,
|
||||||
|
onClickAutoScrollHelp = viewModel::openAutoScrollHelpDialog,
|
||||||
|
onClickRetryAll = ::exhRetryAll,
|
||||||
|
onClickRetryAllHelp = viewModel::openRetryAllHelp,
|
||||||
|
onClickBoostPage = ::exhBoostPage,
|
||||||
|
onClickBoostPageHelp = viewModel::openBoostPageHelp,
|
||||||
currentPageText = state.currentPageText,
|
currentPageText = state.currentPageText,
|
||||||
navBarType = navBarType,
|
navBarType = navBarType,
|
||||||
enabledButtons = readerBottomButtons,
|
enabledButtons = readerBottomButtons,
|
||||||
isHttpSource = remember {
|
|
||||||
viewModel.getSource() != null
|
|
||||||
},
|
|
||||||
dualPageSplitEnabled = dualPageSplitPaged,
|
dualPageSplitEnabled = dualPageSplitPaged,
|
||||||
doublePages = state.doublePages,
|
doublePages = state.doublePages,
|
||||||
onClickChapterList = viewModel::openChapterListDialog,
|
onClickChapterList = viewModel::openChapterListDialog,
|
||||||
onClickWebView = ::openChapterInWebView,
|
|
||||||
onClickShare = {
|
|
||||||
assistUrl?.let {
|
|
||||||
val intent = it.toUri().toShareIntent(this@ReaderActivity, type = "text/plain")
|
|
||||||
startActivity(Intent.createChooser(intent, getString(R.string.action_share)))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClickPageLayout = {
|
onClickPageLayout = {
|
||||||
if (readerPreferences.pageLayout().get() == PagerConfig.PageLayout.AUTOMATIC) {
|
if (readerPreferences.pageLayout().get() == PagerConfig.PageLayout.AUTOMATIC) {
|
||||||
(viewModel.state.value.viewer as? PagerViewer)?.config?.let { config ->
|
(viewModel.state.value.viewer as? PagerViewer)?.config?.let { config ->
|
||||||
@ -682,188 +566,154 @@ class ReaderActivity : BaseActivity() {
|
|||||||
state.dateRelativeTime
|
state.dateRelativeTime
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
// SY -->
|
||||||
|
ReaderViewModel.Dialog.AutoScrollHelp -> AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(R.string.action_ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = { Text(text = stringResource(R.string.eh_autoscroll_help)) },
|
||||||
|
text = { Text(text = stringResource(R.string.eh_autoscroll_help_message)) },
|
||||||
|
)
|
||||||
|
ReaderViewModel.Dialog.BoostPageHelp -> AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(R.string.action_ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = { Text(text = stringResource(R.string.eh_boost_page_help)) },
|
||||||
|
text = { Text(text = stringResource(R.string.eh_boost_page_help_message)) },
|
||||||
|
)
|
||||||
|
ReaderViewModel.Dialog.RetryAllHelp -> AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(R.string.action_ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = { Text(text = stringResource(R.string.eh_retry_all_help)) },
|
||||||
|
text = { Text(text = stringResource(R.string.eh_retry_all_help_message)) },
|
||||||
|
)
|
||||||
|
// SY <--
|
||||||
null -> {}
|
null -> {}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SY -->
|
|
||||||
initDropdownMenu()
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
val toolbarBackground = (binding.toolbar.background as MaterialShapeDrawable).apply {
|
|
||||||
elevation = resources.getDimension(R.dimen.m3_sys_elevation_level2)
|
|
||||||
alpha = if (isNightMode()) 230 else 242 // 90% dark 95% light
|
|
||||||
}
|
|
||||||
val toolbarColor = ColorUtils.setAlphaComponent(
|
val toolbarColor = ColorUtils.setAlphaComponent(
|
||||||
toolbarBackground.resolvedTintColor,
|
SurfaceColors.SURFACE_2.getColor(this),
|
||||||
toolbarBackground.alpha,
|
if (isNightMode()) 230 else 242, // 90% dark 95% light
|
||||||
)
|
)
|
||||||
window.statusBarColor = toolbarColor
|
window.statusBarColor = toolbarColor
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||||
window.navigationBarColor = toolbarColor
|
window.navigationBarColor = toolbarColor
|
||||||
}
|
}
|
||||||
// SY -->
|
|
||||||
binding.toolbar.background.alpha = 0
|
|
||||||
(binding.header.background as MaterialShapeDrawable).fillColor = ColorStateList.valueOf(toolbarColor)
|
|
||||||
// SY <--
|
|
||||||
|
|
||||||
// Set initial visibility
|
// Set initial visibility
|
||||||
setMenuVisibility(viewModel.state.value.menuVisible)
|
setMenuVisibility(viewModel.state.value.menuVisible)
|
||||||
|
|
||||||
// --> EH
|
enableExhAutoScroll()
|
||||||
setEhUtilsVisibility(viewModel.state.value.ehUtilsVisible)
|
|
||||||
// <-- EH
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXH -->
|
private fun enableExhAutoScroll() {
|
||||||
fun initDropdownMenu() {
|
readerPreferences.autoscrollInterval().changes()
|
||||||
binding.expandEhButton.setOnClickListener {
|
.combine(viewModel.state.map { it.autoScroll }.distinctUntilChanged()) { interval, enabled ->
|
||||||
val newValue = !viewModel.state.value.ehUtilsVisible
|
interval.toDouble() to enabled
|
||||||
viewModel.showEhUtils(newValue)
|
}.mapLatest { (intervalFloat, enabled) ->
|
||||||
setEhUtilsVisibility(newValue)
|
if (enabled) {
|
||||||
}
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
|
val interval = intervalFloat.seconds
|
||||||
binding.ehAutoscrollFreq.setText(
|
while (true) {
|
||||||
readerPreferences.autoscrollInterval().get().let {
|
if (!viewModel.state.value.menuVisible) {
|
||||||
if (it == -1f) {
|
viewModel.state.value.viewer.let { v ->
|
||||||
""
|
when (v) {
|
||||||
} else {
|
is PagerViewer -> v.moveToNext()
|
||||||
it.toString()
|
is WebtoonViewer -> {
|
||||||
}
|
if (readerPreferences.smoothAutoScroll().get()) {
|
||||||
},
|
v.linearScroll(interval)
|
||||||
)
|
} else {
|
||||||
|
v.scrollDown()
|
||||||
binding.ehAutoscroll.checkedChanges()
|
|
||||||
.combine(binding.ehAutoscrollFreq.textChanges()) { checked, text ->
|
|
||||||
checked to text
|
|
||||||
}
|
|
||||||
.mapLatest { (checked, text) ->
|
|
||||||
val parsed = text.toString().toDoubleOrNull()
|
|
||||||
|
|
||||||
if (parsed == null || parsed <= 0 || parsed > 9999) {
|
|
||||||
binding.ehAutoscrollFreq.error = getString(R.string.eh_autoscroll_freq_invalid)
|
|
||||||
readerPreferences.autoscrollInterval().set(-1f)
|
|
||||||
binding.ehAutoscroll.isEnabled = false
|
|
||||||
} else {
|
|
||||||
binding.ehAutoscrollFreq.error = null
|
|
||||||
readerPreferences.autoscrollInterval().set(parsed.toFloat())
|
|
||||||
binding.ehAutoscroll.isEnabled = true
|
|
||||||
if (checked) {
|
|
||||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
|
||||||
val interval = parsed.seconds
|
|
||||||
while (true) {
|
|
||||||
if (!binding.readerMenu.isVisible) {
|
|
||||||
viewModel.state.value.viewer.let { v ->
|
|
||||||
when (v) {
|
|
||||||
is PagerViewer -> v.moveToNext()
|
|
||||||
is WebtoonViewer -> {
|
|
||||||
if (readerPreferences.smoothAutoScroll().get()) {
|
|
||||||
v.linearScroll(interval)
|
|
||||||
} else {
|
|
||||||
v.scrollDown()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delay(interval)
|
|
||||||
} else {
|
|
||||||
delay(100)
|
|
||||||
}
|
}
|
||||||
|
delay(interval)
|
||||||
|
} else {
|
||||||
|
delay(100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.launchIn(lifecycleScope)
|
.launchIn(lifecycleScope)
|
||||||
|
}
|
||||||
|
|
||||||
binding.ehAutoscrollHelp.setOnClickListener {
|
private fun exhRetryAll() {
|
||||||
MaterialAlertDialogBuilder(this)
|
var retried = 0
|
||||||
.setTitle(R.string.eh_autoscroll_help)
|
|
||||||
.setMessage(R.string.eh_autoscroll_help_message)
|
|
||||||
.setPositiveButton(R.string.action_ok, null)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.ehRetryAll.setOnClickListener {
|
viewModel.state.value.viewerChapters
|
||||||
var retried = 0
|
?.currChapter
|
||||||
|
?.pages
|
||||||
|
?.forEachIndexed { _, page ->
|
||||||
|
var shouldQueuePage = false
|
||||||
|
if (page.status == Page.State.ERROR) {
|
||||||
|
shouldQueuePage = true
|
||||||
|
} /*else if (page.status == Page.LOAD_PAGE ||
|
||||||
|
page.status == Page.DOWNLOAD_IMAGE) {
|
||||||
|
// Do nothing
|
||||||
|
}*/
|
||||||
|
|
||||||
viewModel.state.value.viewerChapters
|
if (shouldQueuePage) {
|
||||||
?.currChapter
|
page.status = Page.State.QUEUE
|
||||||
?.pages
|
|
||||||
?.forEachIndexed { _, page ->
|
|
||||||
var shouldQueuePage = false
|
|
||||||
if (page.status == Page.State.ERROR) {
|
|
||||||
shouldQueuePage = true
|
|
||||||
} /*else if (page.status == Page.LOAD_PAGE ||
|
|
||||||
page.status == Page.DOWNLOAD_IMAGE) {
|
|
||||||
// Do nothing
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (shouldQueuePage) {
|
|
||||||
page.status = Page.State.QUEUE
|
|
||||||
} else {
|
|
||||||
return@forEachIndexed
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are using EHentai/ExHentai, get a new image URL
|
|
||||||
viewModel.manga?.let { m ->
|
|
||||||
val src = sourceManager.get(m.source)
|
|
||||||
if (src?.isEhBasedSource() == true) {
|
|
||||||
page.imageUrl = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val loader = page.chapter.pageLoader
|
|
||||||
if (page.index == exhCurrentpage()?.index && loader is HttpPageLoader) {
|
|
||||||
loader.boostPage(page)
|
|
||||||
} else {
|
|
||||||
loader?.retryPage(page)
|
|
||||||
}
|
|
||||||
|
|
||||||
retried++
|
|
||||||
}
|
|
||||||
|
|
||||||
toast(resources.getQuantityString(R.plurals.eh_retry_toast, retried, retried))
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.ehRetryAllHelp.setOnClickListener {
|
|
||||||
MaterialAlertDialogBuilder(this)
|
|
||||||
.setTitle(R.string.eh_retry_all_help)
|
|
||||||
.setMessage(R.string.eh_retry_all_help_message)
|
|
||||||
.setPositiveButton(R.string.action_ok, null)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.ehBoostPage.setOnClickListener {
|
|
||||||
viewModel.state.value.viewer ?: return@setOnClickListener
|
|
||||||
val curPage = exhCurrentpage() ?: run {
|
|
||||||
toast(R.string.eh_boost_page_invalid)
|
|
||||||
return@setOnClickListener
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curPage.status == Page.State.ERROR) {
|
|
||||||
toast(R.string.eh_boost_page_errored)
|
|
||||||
} else if (curPage.status == Page.State.LOAD_PAGE || curPage.status == Page.State.DOWNLOAD_IMAGE) {
|
|
||||||
toast(R.string.eh_boost_page_downloading)
|
|
||||||
} else if (curPage.status == Page.State.READY) {
|
|
||||||
toast(R.string.eh_boost_page_downloaded)
|
|
||||||
} else {
|
|
||||||
val loader = (viewModel.state.value.viewerChapters?.currChapter?.pageLoader as? HttpPageLoader)
|
|
||||||
if (loader != null) {
|
|
||||||
loader.boostPage(curPage)
|
|
||||||
toast(R.string.eh_boost_boosted)
|
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.eh_boost_invalid_loader)
|
return@forEachIndexed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we are using EHentai/ExHentai, get a new image URL
|
||||||
|
viewModel.manga?.let { m ->
|
||||||
|
val src = sourceManager.get(m.source)
|
||||||
|
if (src?.isEhBasedSource() == true) {
|
||||||
|
page.imageUrl = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val loader = page.chapter.pageLoader
|
||||||
|
if (page.index == exhCurrentpage()?.index && loader is HttpPageLoader) {
|
||||||
|
loader.boostPage(page)
|
||||||
|
} else {
|
||||||
|
loader?.retryPage(page)
|
||||||
|
}
|
||||||
|
|
||||||
|
retried++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toast(resources.getQuantityString(R.plurals.eh_retry_toast, retried, retried))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exhBoostPage() {
|
||||||
|
viewModel.state.value.viewer ?: return
|
||||||
|
val curPage = exhCurrentpage() ?: run {
|
||||||
|
toast(R.string.eh_boost_page_invalid)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.ehBoostPageHelp.setOnClickListener {
|
if (curPage.status == Page.State.ERROR) {
|
||||||
MaterialAlertDialogBuilder(this)
|
toast(R.string.eh_boost_page_errored)
|
||||||
.setTitle(R.string.eh_boost_page_help)
|
} else if (curPage.status == Page.State.LOAD_PAGE || curPage.status == Page.State.DOWNLOAD_IMAGE) {
|
||||||
.setMessage(R.string.eh_boost_page_help_message)
|
toast(R.string.eh_boost_page_downloading)
|
||||||
.setPositiveButton(R.string.action_ok, null)
|
} else if (curPage.status == Page.State.READY) {
|
||||||
.show()
|
toast(R.string.eh_boost_page_downloaded)
|
||||||
|
} else {
|
||||||
|
val loader = (viewModel.state.value.viewerChapters?.currChapter?.pageLoader as? HttpPageLoader)
|
||||||
|
if (loader != null) {
|
||||||
|
loader.boostPage(curPage)
|
||||||
|
toast(R.string.eh_boost_boosted)
|
||||||
|
} else {
|
||||||
|
toast(R.string.eh_boost_invalid_loader)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -882,7 +732,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
viewer.config.doublePages = doublePages
|
viewer.config.doublePages = doublePages
|
||||||
viewModel.setDoublePages(viewer.config.doublePages)
|
viewModel.setDoublePages(viewer.config.doublePages)
|
||||||
}
|
}
|
||||||
val currentChapter = viewModel.getCurrentChapter()
|
val currentChapter = viewModel.state.value.currentChapter
|
||||||
if (doublePages) {
|
if (doublePages) {
|
||||||
// If we're moving from singe to double, we want the current page to be the first page
|
// If we're moving from singe to double, we want the current page to be the first page
|
||||||
val currentPage = viewModel.state.value.currentPage
|
val currentPage = viewModel.state.value.currentPage
|
||||||
@ -921,40 +771,12 @@ class ReaderActivity : BaseActivity() {
|
|||||||
viewModel.showMenus(visible)
|
viewModel.showMenus(visible)
|
||||||
if (visible) {
|
if (visible) {
|
||||||
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||||
binding.readerMenu.isVisible = true
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
||||||
|
|
||||||
val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top)
|
|
||||||
toolbarAnimation.applySystemAnimatorScale(this)
|
|
||||||
toolbarAnimation.setAnimationListener(
|
|
||||||
object : SimpleAnimationListener() {
|
|
||||||
override fun onAnimationStart(animation: Animation) {
|
|
||||||
// Fix status bar being translucent the first time it's opened.
|
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
// EXH -->
|
|
||||||
binding.header.startAnimation(toolbarAnimation)
|
|
||||||
// EXH <--
|
|
||||||
} else {
|
} else {
|
||||||
if (readerPreferences.fullscreen().get()) {
|
if (readerPreferences.fullscreen().get()) {
|
||||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
}
|
}
|
||||||
|
|
||||||
val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_top)
|
|
||||||
toolbarAnimation.applySystemAnimatorScale(this)
|
|
||||||
toolbarAnimation.setAnimationListener(
|
|
||||||
object : SimpleAnimationListener() {
|
|
||||||
override fun onAnimationEnd(animation: Animation) {
|
|
||||||
binding.readerMenu.isVisible = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
// EXH -->
|
|
||||||
binding.header.startAnimation(toolbarAnimation)
|
|
||||||
// EXH <--
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1001,14 +823,24 @@ class ReaderActivity : BaseActivity() {
|
|||||||
showReadingModeToast(viewModel.getMangaReadingMode())
|
showReadingModeToast(viewModel.getMangaReadingMode())
|
||||||
}
|
}
|
||||||
|
|
||||||
supportActionBar?.title = manga.title
|
|
||||||
|
|
||||||
loadingIndicator = ReaderProgressIndicator(this)
|
loadingIndicator = ReaderProgressIndicator(this)
|
||||||
binding.readerContainer.addView(loadingIndicator)
|
binding.readerContainer.addView(loadingIndicator)
|
||||||
|
|
||||||
startPostponedEnterTransition()
|
startPostponedEnterTransition()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun openMangaScreen() {
|
||||||
|
viewModel.manga?.id?.let { id ->
|
||||||
|
startActivity(
|
||||||
|
Intent(this, MainActivity::class.java).apply {
|
||||||
|
action = Constants.SHORTCUT_MANGA
|
||||||
|
putExtra(Constants.MANGA_EXTRA, id)
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun openChapterInWebView() {
|
private fun openChapterInWebView() {
|
||||||
val manga = viewModel.manga ?: return
|
val manga = viewModel.manga ?: return
|
||||||
val source = viewModel.getSource() ?: return
|
val source = viewModel.getSource() ?: return
|
||||||
@ -1018,6 +850,13 @@ class ReaderActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun shareChapter() {
|
||||||
|
assistUrl?.let {
|
||||||
|
val intent = it.toUri().toShareIntent(this, type = "text/plain")
|
||||||
|
startActivity(Intent.createChooser(intent, getString(R.string.action_share)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun showReadingModeToast(mode: Int) {
|
private fun showReadingModeToast(mode: Int) {
|
||||||
try {
|
try {
|
||||||
readingModeToast?.cancel()
|
readingModeToast?.cancel()
|
||||||
@ -1057,15 +896,6 @@ class ReaderActivity : BaseActivity() {
|
|||||||
|
|
||||||
viewModel.state.value.viewer?.setChapters(viewerChapters)
|
viewModel.state.value.viewer?.setChapters(viewerChapters)
|
||||||
|
|
||||||
binding.toolbar.subtitle = viewerChapters.currChapter.chapter.name
|
|
||||||
ToolbarUtils.getSubtitleTextView(binding.toolbar)?.let {
|
|
||||||
it.ellipsize = TextUtils.TruncateAt.MARQUEE
|
|
||||||
it.isSelected = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invalidate menu to show proper chapter bookmark state
|
|
||||||
invalidateOptionsMenu()
|
|
||||||
|
|
||||||
lifecycleScope.launchIO {
|
lifecycleScope.launchIO {
|
||||||
viewModel.getChapterUrl()?.let { url ->
|
viewModel.getChapterUrl()?.let { url ->
|
||||||
assistUrl = url
|
assistUrl = url
|
||||||
@ -1103,7 +933,7 @@ class ReaderActivity : BaseActivity() {
|
|||||||
*/
|
*/
|
||||||
private fun moveToPageIndex(index: Int) {
|
private fun moveToPageIndex(index: Int) {
|
||||||
val viewer = viewModel.state.value.viewer ?: return
|
val viewer = viewModel.state.value.viewer ?: return
|
||||||
val currentChapter = viewModel.getCurrentChapter() ?: return
|
val currentChapter = viewModel.state.value.currentChapter ?: return
|
||||||
val page = currentChapter.pages?.getOrNull(index) ?: return
|
val page = currentChapter.pages?.getOrNull(index) ?: return
|
||||||
viewer.moveToPage(page)
|
viewer.moveToPage(page)
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,7 @@ import kotlinx.coroutines.flow.drop
|
|||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.mapLatest
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
@ -271,6 +272,24 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||||||
chapterId = currentChapter.chapter.id!!
|
chapterId = currentChapter.chapter.id!!
|
||||||
}
|
}
|
||||||
.launchIn(viewModelScope)
|
.launchIn(viewModelScope)
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
state.mapLatest { it.ehAutoscrollFreq }
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.drop(1)
|
||||||
|
.onEach { text ->
|
||||||
|
val parsed = text.toDoubleOrNull()
|
||||||
|
|
||||||
|
if (parsed == null || parsed <= 0 || parsed > 9999) {
|
||||||
|
readerPreferences.autoscrollInterval().set(-1f)
|
||||||
|
mutableState.update { it.copy(isAutoScrollEnabled = false) }
|
||||||
|
} else {
|
||||||
|
readerPreferences.autoscrollInterval().set(parsed.toFloat())
|
||||||
|
mutableState.update { it.copy(isAutoScrollEnabled = true) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.launchIn(viewModelScope)
|
||||||
|
// SY <--
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
@ -319,8 +338,24 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||||||
val mergedReferences = if (source is MergedSource) runBlocking { getMergedReferencesById.await(manga.id) } else emptyList()
|
val mergedReferences = if (source is MergedSource) runBlocking { getMergedReferencesById.await(manga.id) } else emptyList()
|
||||||
val mergedManga = if (source is MergedSource) runBlocking { getMergedMangaById.await(manga.id) }.associateBy { it.id } else emptyMap()
|
val mergedManga = if (source is MergedSource) runBlocking { getMergedMangaById.await(manga.id) }.associateBy { it.id } else emptyMap()
|
||||||
val relativeTime = uiPreferences.relativeTime().get()
|
val relativeTime = uiPreferences.relativeTime().get()
|
||||||
|
val autoScrollFreq = readerPreferences.autoscrollInterval().get()
|
||||||
// SY <--
|
// SY <--
|
||||||
mutableState.update { it.copy(manga = manga /* SY --> */, meta = metadata, mergedManga = mergedManga, dateRelativeTime = relativeTime/* SY <-- */) }
|
mutableState.update {
|
||||||
|
it.copy(
|
||||||
|
manga = manga,
|
||||||
|
/* SY --> */
|
||||||
|
meta = metadata,
|
||||||
|
mergedManga = mergedManga,
|
||||||
|
dateRelativeTime = relativeTime,
|
||||||
|
ehAutoscrollFreq = if (autoScrollFreq == -1f) {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
autoScrollFreq.toString()
|
||||||
|
},
|
||||||
|
isAutoScrollEnabled = autoScrollFreq != -1f
|
||||||
|
/* SY <-- */
|
||||||
|
)
|
||||||
|
}
|
||||||
if (chapterId == -1L) chapterId = initialChapterId
|
if (chapterId == -1L) chapterId = initialChapterId
|
||||||
|
|
||||||
val context = Injekt.get<Application>()
|
val context = Injekt.get<Application>()
|
||||||
@ -384,7 +419,10 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||||||
it.viewerChapters?.unref()
|
it.viewerChapters?.unref()
|
||||||
|
|
||||||
chapterToDownload = cancelQueuedDownloads(newChapters.currChapter)
|
chapterToDownload = cancelQueuedDownloads(newChapters.currChapter)
|
||||||
it.copy(viewerChapters = newChapters)
|
it.copy(
|
||||||
|
viewerChapters = newChapters,
|
||||||
|
bookmarked = newChapters.currChapter.chapter.bookmark,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newChapters
|
return newChapters
|
||||||
@ -686,8 +724,8 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* Returns the currently active chapter.
|
* Returns the currently active chapter.
|
||||||
*/
|
*/
|
||||||
fun getCurrentChapter(): ReaderChapter? {
|
private fun getCurrentChapter(): ReaderChapter? {
|
||||||
return state.value.viewerChapters?.currChapter
|
return state.value.currentChapter
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSource() = manga?.source?.let { sourceManager.getOrStub(it) } as? HttpSource
|
fun getSource() = manga?.source?.let { sourceManager.getOrStub(it) } as? HttpSource
|
||||||
@ -707,9 +745,11 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* Bookmarks the currently active chapter.
|
* Bookmarks the currently active chapter.
|
||||||
*/
|
*/
|
||||||
fun bookmarkCurrentChapter(bookmarked: Boolean) {
|
fun toggleChapterBookmark() {
|
||||||
val chapter = getCurrentChapter()?.chapter ?: return
|
val chapter = getCurrentChapter()?.chapter ?: return
|
||||||
chapter.bookmark = bookmarked // Otherwise the bookmark icon doesn't update
|
val bookmarked = !chapter.bookmark
|
||||||
|
chapter.bookmark = bookmarked
|
||||||
|
|
||||||
viewModelScope.launchNonCancellable {
|
viewModelScope.launchNonCancellable {
|
||||||
updateChapter.await(
|
updateChapter.await(
|
||||||
ChapterUpdate(
|
ChapterUpdate(
|
||||||
@ -718,6 +758,12 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutableState.update {
|
||||||
|
it.copy(
|
||||||
|
bookmarked = bookmarked,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
@ -868,6 +914,26 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||||||
fun setDoublePages(doublePages: Boolean) {
|
fun setDoublePages(doublePages: Boolean) {
|
||||||
mutableState.update { it.copy(doublePages = doublePages) }
|
mutableState.update { it.copy(doublePages = doublePages) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun openAutoScrollHelpDialog() {
|
||||||
|
mutableState.update { it.copy(dialog = Dialog.AutoScrollHelp) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openBoostPageHelp() {
|
||||||
|
mutableState.update { it.copy(dialog = Dialog.BoostPageHelp) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openRetryAllHelp() {
|
||||||
|
mutableState.update { it.copy(dialog = Dialog.RetryAllHelp) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toggleAutoScroll(enabled: Boolean) {
|
||||||
|
mutableState.update { it.copy(autoScroll = enabled) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setAutoScrollFrequency(frequency: String) {
|
||||||
|
mutableState.update { it.copy(ehAutoscrollFreq = frequency) }
|
||||||
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
fun showLoadingDialog() {
|
fun showLoadingDialog() {
|
||||||
@ -1168,6 +1234,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||||||
data class State(
|
data class State(
|
||||||
val manga: Manga? = null,
|
val manga: Manga? = null,
|
||||||
val viewerChapters: ViewerChapters? = null,
|
val viewerChapters: ViewerChapters? = null,
|
||||||
|
val bookmarked: Boolean = false,
|
||||||
val isLoadingAdjacentChapter: Boolean = false,
|
val isLoadingAdjacentChapter: Boolean = false,
|
||||||
val currentPage: Int = -1,
|
val currentPage: Int = -1,
|
||||||
|
|
||||||
@ -1188,10 +1255,16 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||||||
val indexChapterToShift: Long? = null,
|
val indexChapterToShift: Long? = null,
|
||||||
val doublePages: Boolean = false,
|
val doublePages: Boolean = false,
|
||||||
val dateRelativeTime: Boolean = true,
|
val dateRelativeTime: Boolean = true,
|
||||||
|
val autoScroll: Boolean = false,
|
||||||
|
val isAutoScrollEnabled: Boolean = false,
|
||||||
|
val ehAutoscrollFreq: String = "",
|
||||||
// SY <--
|
// SY <--
|
||||||
) {
|
) {
|
||||||
|
val currentChapter: ReaderChapter?
|
||||||
|
get() = viewerChapters?.currChapter
|
||||||
|
|
||||||
val totalPages: Int
|
val totalPages: Int
|
||||||
get() = viewerChapters?.currChapter?.pages?.size ?: -1
|
get() = currentChapter?.pages?.size ?: -1
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface Dialog {
|
sealed interface Dialog {
|
||||||
@ -1205,6 +1278,12 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
data class PageActions(val page: ReaderPage/* SY --> */, val extraPage: ReaderPage? = null /* SY <-- */) : Dialog
|
data class PageActions(val page: ReaderPage/* SY --> */, val extraPage: ReaderPage? = null /* SY <-- */) : Dialog
|
||||||
|
|
||||||
|
// SY -->
|
||||||
|
data object AutoScrollHelp : Dialog
|
||||||
|
data object RetryAllHelp : Dialog
|
||||||
|
data object BoostPageHelp : Dialog
|
||||||
|
// SY <--
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface Event {
|
sealed interface Event {
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.widget.listener
|
|
||||||
|
|
||||||
import android.view.animation.Animation
|
|
||||||
|
|
||||||
open class SimpleAnimationListener : Animation.AnimationListener {
|
|
||||||
override fun onAnimationRepeat(animation: Animation) {}
|
|
||||||
|
|
||||||
override fun onAnimationEnd(animation: Animation) {}
|
|
||||||
|
|
||||||
override fun onAnimationStart(animation: Animation) {}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shareInterpolator="false">
|
|
||||||
<translate
|
|
||||||
android:duration="200"
|
|
||||||
android:fromYDelta="-100%"
|
|
||||||
android:toYDelta="0%" />
|
|
||||||
</set>
|
|
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shareInterpolator="false">
|
|
||||||
<translate
|
|
||||||
android:duration="200"
|
|
||||||
android:fromYDelta="0%"
|
|
||||||
android:toYDelta="-100%" />
|
|
||||||
</set>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="#000"
|
|
||||||
android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z" />
|
|
||||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="#000"
|
|
||||||
android:pathData="M17,3L7,3c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3L19,5c0,-1.1 -0.9,-2 -2,-2zM17,18l-5,-2.18L7,18L7,5h10v13z" />
|
|
||||||
</vector>
|
|
@ -1,7 +1,4 @@
|
|||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/reader_layout"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
@ -44,145 +41,6 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:id="@+id/reader_menu"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:theme="?attr/actionBarTheme"
|
|
||||||
android:visibility="invisible"
|
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
|
||||||
android:id="@+id/header"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:animateLayoutChanges="true"
|
|
||||||
app:elevation="0dp"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="?attr/actionBarSize" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/eh_utils"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<com.google.android.material.materialswitch.MaterialSwitch
|
|
||||||
android:id="@+id/eh_autoscroll"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center_horizontal|center_vertical"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:paddingVertical="16dp"
|
|
||||||
android:text="@string/eh_autoscroll"
|
|
||||||
android:textColor="?attr/colorOnSurface"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/eh_autoscroll_freq"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:backgroundTint="?attr/colorAccent"
|
|
||||||
android:gravity="center_horizontal|center_vertical"
|
|
||||||
android:importantForAutofill="no"
|
|
||||||
android:inputType="numberDecimal"
|
|
||||||
android:maxLength="10"
|
|
||||||
android:singleLine="true" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/eh_autoscroll_help"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
|
||||||
android:layout_width="50dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:text="\?"
|
|
||||||
android:textColor="?attr/colorOnSurface"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
tools:ignore="HardcodedText" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/eh_retry_all"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:fontFamily="sans-serif"
|
|
||||||
android:text="@string/eh_retry_all"
|
|
||||||
android:textColor="?attr/colorOnSurface"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/eh_retry_all_help"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
|
||||||
android:layout_width="50dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:text="\?"
|
|
||||||
android:textColor="?attr/colorOnSurface"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
tools:ignore="HardcodedText" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/eh_boost_page"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:fontFamily="sans-serif"
|
|
||||||
android:text="@string/eh_boost_page"
|
|
||||||
android:textColor="?attr/colorOnSurface"
|
|
||||||
android:textSize="13sp" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/eh_boost_page_help"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
|
||||||
android:layout_width="50dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:text="\?"
|
|
||||||
android:textColor="?attr/colorOnSurface"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
tools:ignore="HardcodedText" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/expand_eh_button"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="0dp"
|
|
||||||
app:srcCompat="@drawable/ic_keyboard_arrow_down_white_32dp"
|
|
||||||
app:tint="?attr/colorOnSurface" />
|
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<androidx.compose.ui.platform.ComposeView
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/dialog_root"
|
android:id="@+id/dialog_root"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/reader_chapter_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="60dp"
|
|
||||||
android:background="@android:color/transparent">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/chapter_title"
|
|
||||||
style="@style/TextAppearance.MaterialComponents.Body2"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/chapter_scanlator"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/bookmark_layout"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="Chapter 123 - The Real One" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/chapter_scanlator"
|
|
||||||
style="@style/TextAppearance.MaterialComponents.Caption"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginBottom="12dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/bookmark_layout"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/chapter_title"
|
|
||||||
tools:text="3 days ago • On page 45 • Scanlator" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/bookmark_layout"
|
|
||||||
android:layout_width="50dp"
|
|
||||||
android:layout_height="50dp"
|
|
||||||
android:layout_marginEnd="12dp"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:src="@drawable/ic_bookmark_24dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/bookmark_image"
|
|
||||||
android:layout_width="30dp"
|
|
||||||
android:layout_height="30dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:src="@drawable/ic_bookmark_border_24dp"
|
|
||||||
app:tint="?attr/colorOnSurface" />
|
|
||||||
</FrameLayout>
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingTop="8dp">
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/chapter_recycler"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:clipToPadding="false"
|
|
||||||
tools:listitem="@layout/reader_chapter_item" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -1,29 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<!--<item
|
|
||||||
android:id="@+id/action_bookmark"
|
|
||||||
android:icon="@drawable/ic_bookmark_border_24dp"
|
|
||||||
android:title="@string/action_bookmark"
|
|
||||||
app:iconTint="?attr/colorOnSurface"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_remove_bookmark"
|
|
||||||
android:icon="@drawable/ic_bookmark_24dp"
|
|
||||||
android:title="@string/action_remove_bookmark"
|
|
||||||
app:iconTint="?attr/colorOnSurface"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_open_in_web_view"
|
|
||||||
android:title="@string/action_open_in_web_view"
|
|
||||||
app:showAsAction="never" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_share"
|
|
||||||
android:title="@string/action_share"
|
|
||||||
app:showAsAction="never" />-->
|
|
||||||
|
|
||||||
</menu>
|
|
Loading…
x
Reference in New Issue
Block a user