Make reader edge-to-edge (mihonapp/mihon#1908)
(cherry picked from commit 5f0c4606681cd59b38ae0855c7827e149fa5488c)
This commit is contained in:
parent
5aa67ebf34
commit
77ecb97535
12 changed files with 568 additions and 592 deletions
|
|
@ -280,7 +280,6 @@ dependencies {
|
||||||
implementation(libs.directionalviewpager) {
|
implementation(libs.directionalviewpager) {
|
||||||
exclude(group = "androidx.viewpager", module = "viewpager")
|
exclude(group = "androidx.viewpager", module = "viewpager")
|
||||||
}
|
}
|
||||||
implementation(libs.insetter)
|
|
||||||
implementation(libs.richeditor.compose)
|
implementation(libs.richeditor.compose)
|
||||||
implementation(libs.aboutLibraries.compose)
|
implementation(libs.aboutLibraries.compose)
|
||||||
implementation(libs.bundles.voyager)
|
implementation(libs.bundles.voyager)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package eu.kanade.presentation.more.settings.screen
|
package eu.kanade.presentation.more.settings.screen
|
||||||
|
|
||||||
import android.os.Build
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
|
@ -14,6 +13,7 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences.Companion.zoomWid
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences.WebtoonScaleType
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences.WebtoonScaleType
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig
|
||||||
|
import eu.kanade.tachiyomi.util.system.hasDisplayCutout
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.persistentMapOf
|
import kotlinx.collections.immutable.persistentMapOf
|
||||||
import kotlinx.collections.immutable.toImmutableMap
|
import kotlinx.collections.immutable.toImmutableMap
|
||||||
|
|
@ -148,9 +148,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
preference = readerPreferences.cutoutShort(),
|
preference = readerPreferences.cutoutShort(),
|
||||||
title = stringResource(MR.strings.pref_cutout_short),
|
title = stringResource(MR.strings.pref_cutout_short),
|
||||||
enabled = fullscreen &&
|
enabled = LocalView.current.hasDisplayCutout() && fullscreen,
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&
|
|
||||||
LocalView.current.rootWindowInsets?.displayCutout != null, // has cutout
|
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.SwitchPreference(
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
preference = readerPreferences.keepScreenOn(),
|
preference = readerPreferences.keepScreenOn(),
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
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.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
|
@ -15,11 +16,12 @@ import androidx.compose.ui.unit.sp
|
||||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PageIndicatorText(
|
fun ReaderPageIndicator(
|
||||||
// SY -->
|
// SY -->
|
||||||
currentPage: String,
|
currentPage: String,
|
||||||
// SY <--
|
// SY <--
|
||||||
totalPages: Int,
|
totalPages: Int,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
if (currentPage.isEmpty() || totalPages <= 0) return
|
if (currentPage.isEmpty() || totalPages <= 0) return
|
||||||
|
|
||||||
|
|
@ -40,6 +42,7 @@ fun PageIndicatorText(
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
|
modifier = modifier,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
||||||
|
|
@ -54,10 +57,10 @@ fun PageIndicatorText(
|
||||||
|
|
||||||
@PreviewLightDark
|
@PreviewLightDark
|
||||||
@Composable
|
@Composable
|
||||||
private fun PageIndicatorTextPreview() {
|
private fun ReaderPageIndicatorPreview() {
|
||||||
TachiyomiPreviewTheme {
|
TachiyomiPreviewTheme {
|
||||||
Surface {
|
Surface {
|
||||||
PageIndicatorText(currentPage = "10", totalPages = 69)
|
ReaderPageIndicator(currentPage = "10", totalPages = 69)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,10 +2,13 @@ package eu.kanade.presentation.reader.appbars
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.animation.slideInHorizontally
|
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.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
|
@ -13,13 +16,12 @@ 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.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.systemBarsPadding
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.outlined.Bookmark
|
|
||||||
import androidx.compose.material.icons.outlined.BookmarkBorder
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.surfaceColorAtElevation
|
import androidx.compose.material3.surfaceColorAtElevation
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
@ -30,20 +32,16 @@ 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.presentation.components.AppBarActions
|
|
||||||
import eu.kanade.presentation.reader.components.ChapterNavigator
|
import eu.kanade.presentation.reader.components.ChapterNavigator
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
|
import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
|
||||||
import kotlinx.collections.immutable.ImmutableSet
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
|
||||||
import tachiyomi.i18n.MR
|
|
||||||
import tachiyomi.presentation.core.components.material.padding
|
import tachiyomi.presentation.core.components.material.padding
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
|
||||||
|
|
||||||
private val animationSpec = tween<IntOffset>(200)
|
private val readerBarsSlideAnimationSpec = tween<IntOffset>(200)
|
||||||
|
private val readerBarsFadeAnimationSpec = tween<Float>(150)
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
enum class NavBarType {
|
enum class NavBarType {
|
||||||
|
|
@ -72,7 +70,6 @@ fun BoxIgnoreLayoutDirection(modifier: Modifier, content: @Composable BoxScope.(
|
||||||
@Composable
|
@Composable
|
||||||
fun ReaderAppBars(
|
fun ReaderAppBars(
|
||||||
visible: Boolean,
|
visible: Boolean,
|
||||||
fullscreen: Boolean,
|
|
||||||
|
|
||||||
mangaTitle: String?,
|
mangaTitle: String?,
|
||||||
chapterTitle: String?,
|
chapterTitle: String?,
|
||||||
|
|
@ -129,28 +126,18 @@ fun ReaderAppBars(
|
||||||
.surfaceColorAtElevation(3.dp)
|
.surfaceColorAtElevation(3.dp)
|
||||||
.copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f)
|
.copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f)
|
||||||
|
|
||||||
val modifierWithInsetsPadding = if (fullscreen) {
|
|
||||||
Modifier.systemBarsPadding()
|
|
||||||
} else {
|
|
||||||
Modifier
|
|
||||||
}
|
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
BoxIgnoreLayoutDirection(
|
BoxIgnoreLayoutDirection(
|
||||||
Modifier.fillMaxWidth(),
|
Modifier.fillMaxWidth(),
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = visible && navBarType == NavBarType.VerticalLeft,
|
visible = visible && navBarType == NavBarType.VerticalLeft,
|
||||||
enter = slideInHorizontally(
|
enter = slideInHorizontally(initialOffsetX = { -it }, animationSpec = readerBarsSlideAnimationSpec) +
|
||||||
initialOffsetX = { -it },
|
fadeIn(animationSpec = readerBarsFadeAnimationSpec),
|
||||||
animationSpec = animationSpec,
|
exit = slideOutHorizontally(targetOffsetX = { -it }, animationSpec = readerBarsSlideAnimationSpec) +
|
||||||
),
|
fadeOut(animationSpec = readerBarsFadeAnimationSpec),
|
||||||
exit = slideOutHorizontally(
|
modifier = Modifier
|
||||||
targetOffsetX = { -it },
|
.padding(top = 164.dp, bottom = 70.dp)
|
||||||
animationSpec = animationSpec,
|
|
||||||
),
|
|
||||||
modifier = modifierWithInsetsPadding
|
|
||||||
.padding(bottom = 64.dp, top = 112.dp)
|
|
||||||
.align(Alignment.TopStart),
|
.align(Alignment.TopStart),
|
||||||
) {
|
) {
|
||||||
ChapterNavigator(
|
ChapterNavigator(
|
||||||
|
|
@ -162,23 +149,21 @@ fun ReaderAppBars(
|
||||||
currentPage = currentPage,
|
currentPage = currentPage,
|
||||||
totalPages = totalPages,
|
totalPages = totalPages,
|
||||||
onPageIndexChange = onPageIndexChange,
|
onPageIndexChange = onPageIndexChange,
|
||||||
|
// SY -->
|
||||||
isVerticalSlider = true,
|
isVerticalSlider = true,
|
||||||
currentPageText = currentPageText,
|
currentPageText = currentPageText,
|
||||||
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = visible && navBarType == NavBarType.VerticalRight,
|
visible = visible && navBarType == NavBarType.VerticalRight,
|
||||||
enter = slideInHorizontally(
|
enter = slideInHorizontally(initialOffsetX = { it }, animationSpec = readerBarsSlideAnimationSpec) +
|
||||||
initialOffsetX = { it },
|
fadeIn(animationSpec = readerBarsFadeAnimationSpec),
|
||||||
animationSpec = animationSpec,
|
exit = slideOutHorizontally(targetOffsetX = { it }, animationSpec = readerBarsSlideAnimationSpec) +
|
||||||
),
|
fadeOut(animationSpec = readerBarsFadeAnimationSpec),
|
||||||
exit = slideOutHorizontally(
|
modifier = Modifier
|
||||||
targetOffsetX = { it },
|
.padding(top = 164.dp, bottom = 70.dp)
|
||||||
animationSpec = animationSpec,
|
|
||||||
),
|
|
||||||
modifier = modifierWithInsetsPadding
|
|
||||||
.padding(bottom = 64.dp, top = 112.dp)
|
|
||||||
.align(Alignment.TopEnd),
|
.align(Alignment.TopEnd),
|
||||||
) {
|
) {
|
||||||
ChapterNavigator(
|
ChapterNavigator(
|
||||||
|
|
@ -190,87 +175,38 @@ fun ReaderAppBars(
|
||||||
currentPage = currentPage,
|
currentPage = currentPage,
|
||||||
totalPages = totalPages,
|
totalPages = totalPages,
|
||||||
onPageIndexChange = onPageIndexChange,
|
onPageIndexChange = onPageIndexChange,
|
||||||
|
// SY -->
|
||||||
isVerticalSlider = true,
|
isVerticalSlider = true,
|
||||||
currentPageText = currentPageText,
|
currentPageText = currentPageText,
|
||||||
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
Column(
|
Column(modifier = Modifier.fillMaxHeight()) {
|
||||||
modifier = Modifier.fillMaxHeight(),
|
|
||||||
verticalArrangement = Arrangement.SpaceBetween,
|
|
||||||
) {
|
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = visible,
|
visible = visible,
|
||||||
enter = slideInVertically(
|
enter = slideInVertically(initialOffsetY = { -it }, animationSpec = readerBarsSlideAnimationSpec) +
|
||||||
initialOffsetY = { -it },
|
fadeIn(animationSpec = readerBarsFadeAnimationSpec),
|
||||||
animationSpec = animationSpec,
|
exit = slideOutVertically(targetOffsetY = { -it }, animationSpec = readerBarsSlideAnimationSpec) +
|
||||||
),
|
fadeOut(animationSpec = readerBarsFadeAnimationSpec),
|
||||||
exit = slideOutVertically(
|
|
||||||
targetOffsetY = { -it },
|
|
||||||
animationSpec = animationSpec,
|
|
||||||
),
|
|
||||||
) {
|
) {
|
||||||
// SY -->
|
// SY -->
|
||||||
Column(modifierWithInsetsPadding) {
|
Column {
|
||||||
// SY <--
|
// SY <--
|
||||||
AppBar(
|
ReaderTopBar(
|
||||||
modifier = /*SY --> */ Modifier /*SY <-- */
|
modifier = Modifier
|
||||||
|
.background(backgroundColor)
|
||||||
.clickable(onClick = onClickTopAppBar),
|
.clickable(onClick = onClickTopAppBar),
|
||||||
backgroundColor = backgroundColor,
|
mangaTitle = mangaTitle,
|
||||||
title = mangaTitle,
|
chapterTitle = chapterTitle,
|
||||||
subtitle = chapterTitle,
|
|
||||||
navigateUp = navigateUp,
|
navigateUp = navigateUp,
|
||||||
actions = {
|
bookmarked = bookmarked,
|
||||||
AppBarActions(
|
onToggleBookmarked = onToggleBookmarked,
|
||||||
actions = persistentListOf<AppBar.AppBarAction>().builder()
|
// SY -->
|
||||||
.apply {
|
onOpenInWebView = null, // onOpenInWebView,
|
||||||
add(
|
onOpenInBrowser = null, // onOpenInBrowser,
|
||||||
AppBar.Action(
|
onShare = null, // onShare,
|
||||||
title = stringResource(
|
// SY <--
|
||||||
if (bookmarked) {
|
|
||||||
MR.strings.action_remove_bookmark
|
|
||||||
} else {
|
|
||||||
MR.strings.action_bookmark
|
|
||||||
},
|
|
||||||
),
|
|
||||||
icon = if (bookmarked) {
|
|
||||||
Icons.Outlined.Bookmark
|
|
||||||
} else {
|
|
||||||
Icons.Outlined.BookmarkBorder
|
|
||||||
},
|
|
||||||
onClick = onToggleBookmarked,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
/* SY -->
|
|
||||||
onOpenInWebView?.let {
|
|
||||||
add(
|
|
||||||
AppBar.OverflowAction(
|
|
||||||
title = stringResource(MR.strings.action_open_in_web_view),
|
|
||||||
onClick = it,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onOpenInBrowser?.let {
|
|
||||||
add(
|
|
||||||
AppBar.OverflowAction(
|
|
||||||
title = stringResource(MR.strings.action_open_in_browser),
|
|
||||||
onClick = it,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onShare?.let {
|
|
||||||
add(
|
|
||||||
AppBar.OverflowAction(
|
|
||||||
title = stringResource(MR.strings.action_share),
|
|
||||||
onClick = it,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
SY <-- */
|
|
||||||
}
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
// SY -->
|
// SY -->
|
||||||
ExhUtils(
|
ExhUtils(
|
||||||
|
|
@ -288,28 +224,23 @@ fun ReaderAppBars(
|
||||||
onClickBoostPage = onClickBoostPage,
|
onClickBoostPage = onClickBoostPage,
|
||||||
onClickBoostPageHelp = onClickBoostPageHelp,
|
onClickBoostPageHelp = onClickBoostPageHelp,
|
||||||
)
|
)
|
||||||
// SY <--
|
|
||||||
}
|
}
|
||||||
|
// SY <--
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = visible,
|
visible = visible,
|
||||||
enter = slideInVertically(
|
enter = slideInVertically(initialOffsetY = { it }, animationSpec = readerBarsSlideAnimationSpec) +
|
||||||
initialOffsetY = { it },
|
fadeIn(animationSpec = readerBarsFadeAnimationSpec),
|
||||||
animationSpec = animationSpec,
|
exit = slideOutVertically(targetOffsetY = { it }, animationSpec = readerBarsSlideAnimationSpec) +
|
||||||
),
|
fadeOut(animationSpec = readerBarsFadeAnimationSpec),
|
||||||
exit = slideOutVertically(
|
|
||||||
targetOffsetY = { it },
|
|
||||||
animationSpec = animationSpec,
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = modifierWithInsetsPadding,
|
|
||||||
verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
|
||||||
) {
|
) {
|
||||||
|
Column(verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small)) {
|
||||||
|
// SY -->
|
||||||
if (navBarType == NavBarType.Bottom) {
|
if (navBarType == NavBarType.Bottom) {
|
||||||
|
// SY <--
|
||||||
ChapterNavigator(
|
ChapterNavigator(
|
||||||
isRtl = isRtl,
|
isRtl = isRtl,
|
||||||
onNextChapter = onNextChapter,
|
onNextChapter = onNextChapter,
|
||||||
|
|
@ -319,15 +250,18 @@ fun ReaderAppBars(
|
||||||
currentPage = currentPage,
|
currentPage = currentPage,
|
||||||
totalPages = totalPages,
|
totalPages = totalPages,
|
||||||
onPageIndexChange = onPageIndexChange,
|
onPageIndexChange = onPageIndexChange,
|
||||||
|
// SY -->
|
||||||
isVerticalSlider = false,
|
isVerticalSlider = false,
|
||||||
currentPageText = currentPageText,
|
currentPageText = currentPageText,
|
||||||
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
BottomReaderBar(
|
ReaderBottomBar(
|
||||||
// SY -->
|
modifier = Modifier
|
||||||
enabledButtons = enabledButtons,
|
.fillMaxWidth()
|
||||||
// SY <--
|
.background(backgroundColor)
|
||||||
backgroundColor = backgroundColor,
|
.padding(horizontal = MaterialTheme.padding.small)
|
||||||
|
.windowInsetsPadding(WindowInsets.navigationBars),
|
||||||
readingMode = readingMode,
|
readingMode = readingMode,
|
||||||
onClickReadingMode = onClickReadingMode,
|
onClickReadingMode = onClickReadingMode,
|
||||||
orientation = orientation,
|
orientation = orientation,
|
||||||
|
|
@ -336,6 +270,7 @@ fun ReaderAppBars(
|
||||||
onClickCropBorder = onClickCropBorder,
|
onClickCropBorder = onClickCropBorder,
|
||||||
onClickSettings = onClickSettings,
|
onClickSettings = onClickSettings,
|
||||||
// SY -->
|
// SY -->
|
||||||
|
enabledButtons = enabledButtons,
|
||||||
currentReadingMode = currentReadingMode,
|
currentReadingMode = currentReadingMode,
|
||||||
dualPageSplitEnabled = dualPageSplitEnabled,
|
dualPageSplitEnabled = dualPageSplitEnabled,
|
||||||
doublePages = doublePages,
|
doublePages = doublePages,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
package eu.kanade.presentation.reader.appbars
|
package eu.kanade.presentation.reader.appbars
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
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.padding
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.Explore
|
import androidx.compose.material.icons.outlined.Explore
|
||||||
import androidx.compose.material.icons.outlined.FormatListNumbered
|
import androidx.compose.material.icons.outlined.FormatListNumbered
|
||||||
|
|
@ -17,9 +14,8 @@ import androidx.compose.material3.MaterialTheme
|
||||||
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.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderBottomButton
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderBottomButton
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||||
|
|
@ -30,11 +26,10 @@ import tachiyomi.i18n.sy.SYMR
|
||||||
import tachiyomi.presentation.core.i18n.stringResource
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BottomReaderBar(
|
fun ReaderBottomBar(
|
||||||
// SY -->
|
// SY -->
|
||||||
enabledButtons: ImmutableSet<String>,
|
enabledButtons: ImmutableSet<String>,
|
||||||
// SY <--
|
// SY <--
|
||||||
backgroundColor: Color,
|
|
||||||
readingMode: ReadingMode,
|
readingMode: ReadingMode,
|
||||||
onClickReadingMode: () -> Unit,
|
onClickReadingMode: () -> Unit,
|
||||||
orientation: ReaderOrientation,
|
orientation: ReaderOrientation,
|
||||||
|
|
@ -53,15 +48,14 @@ fun BottomReaderBar(
|
||||||
onClickPageLayout: () -> Unit,
|
onClickPageLayout: () -> Unit,
|
||||||
onClickShiftPage: () -> Unit,
|
onClickShiftPage: () -> Unit,
|
||||||
// SY <--
|
// SY <--
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
// KMK -->
|
// KMK -->
|
||||||
val iconColor = MaterialTheme.colorScheme.primary
|
val iconColor = MaterialTheme.colorScheme.primary
|
||||||
// KMK <--
|
// KMK <--
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.pointerInput(Unit) {},
|
||||||
.background(backgroundColor)
|
|
||||||
.padding(8.dp),
|
|
||||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
package eu.kanade.presentation.reader.appbars
|
||||||
|
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Bookmark
|
||||||
|
import androidx.compose.material.icons.outlined.BookmarkBorder
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import eu.kanade.presentation.components.AppBar
|
||||||
|
import eu.kanade.presentation.components.AppBarActions
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import tachiyomi.i18n.MR
|
||||||
|
import tachiyomi.presentation.core.i18n.stringResource
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReaderTopBar(
|
||||||
|
mangaTitle: String?,
|
||||||
|
chapterTitle: String?,
|
||||||
|
navigateUp: () -> Unit,
|
||||||
|
bookmarked: Boolean,
|
||||||
|
onToggleBookmarked: () -> Unit,
|
||||||
|
onOpenInWebView: (() -> Unit)?,
|
||||||
|
onOpenInBrowser: (() -> Unit)?,
|
||||||
|
onShare: (() -> Unit)?,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
AppBar(
|
||||||
|
modifier = modifier,
|
||||||
|
backgroundColor = Color.Transparent,
|
||||||
|
title = mangaTitle,
|
||||||
|
subtitle = chapterTitle,
|
||||||
|
navigateUp = navigateUp,
|
||||||
|
actions = {
|
||||||
|
AppBarActions(
|
||||||
|
actions = persistentListOf<AppBar.AppBarAction>().builder()
|
||||||
|
.apply {
|
||||||
|
add(
|
||||||
|
AppBar.Action(
|
||||||
|
title = stringResource(
|
||||||
|
if (bookmarked) {
|
||||||
|
MR.strings.action_remove_bookmark
|
||||||
|
} else {
|
||||||
|
MR.strings.action_bookmark
|
||||||
|
},
|
||||||
|
),
|
||||||
|
icon = if (bookmarked) {
|
||||||
|
Icons.Outlined.Bookmark
|
||||||
|
} else {
|
||||||
|
Icons.Outlined.BookmarkBorder
|
||||||
|
},
|
||||||
|
onClick = onToggleBookmarked,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
onOpenInWebView?.let {
|
||||||
|
add(
|
||||||
|
AppBar.OverflowAction(
|
||||||
|
title = stringResource(MR.strings.action_open_in_web_view),
|
||||||
|
onClick = it,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onOpenInBrowser?.let {
|
||||||
|
add(
|
||||||
|
AppBar.OverflowAction(
|
||||||
|
title = stringResource(MR.strings.action_open_in_browser),
|
||||||
|
onClick = it,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onShare?.let {
|
||||||
|
add(
|
||||||
|
AppBar.OverflowAction(
|
||||||
|
title = stringResource(MR.strings.action_share),
|
||||||
|
onClick = it,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -5,8 +5,10 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
||||||
|
import eu.kanade.tachiyomi.util.system.hasDisplayCutout
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import tachiyomi.i18n.sy.SYMR
|
import tachiyomi.i18n.sy.SYMR
|
||||||
import tachiyomi.presentation.core.components.CheckboxItem
|
import tachiyomi.presentation.core.components.CheckboxItem
|
||||||
|
|
@ -84,7 +86,8 @@ internal fun GeneralPage(screenModel: ReaderSettingsScreenModel) {
|
||||||
pref = screenModel.preferences.fullscreen(),
|
pref = screenModel.preferences.fullscreen(),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (screenModel.hasDisplayCutout && screenModel.preferences.fullscreen().get()) {
|
val isFullscreen by screenModel.preferences.fullscreen().collectAsState()
|
||||||
|
if (LocalView.current.hasDisplayCutout() && isFullscreen) {
|
||||||
CheckboxItem(
|
CheckboxItem(
|
||||||
label = stringResource(MR.strings.pref_cutout_short),
|
label = stringResource(MR.strings.pref_cutout_short),
|
||||||
pref = screenModel.preferences.cutoutShort(),
|
pref = screenModel.preferences.cutoutShort(),
|
||||||
|
|
|
||||||
|
|
@ -22,17 +22,21 @@ 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.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.SystemBarStyle
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.surfaceColorAtElevation
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
|
@ -40,14 +44,16 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.Insets
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.transition.doOnEnd
|
import androidx.core.transition.doOnEnd
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
|
|
@ -55,12 +61,8 @@ 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.elevation.SurfaceColors
|
|
||||||
import com.google.android.material.transition.platform.MaterialContainerTransform
|
import com.google.android.material.transition.platform.MaterialContainerTransform
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
import com.materialkolor.dynamicColorScheme
|
|
||||||
import com.materialkolor.dynamiccolor.ColorSpec
|
|
||||||
import dev.chrisbanes.insetter.applyInsetter
|
|
||||||
import eu.kanade.core.util.ifSourcesLoaded
|
import eu.kanade.core.util.ifSourcesLoaded
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.domain.connections.service.ConnectionsPreferences
|
import eu.kanade.domain.connections.service.ConnectionsPreferences
|
||||||
|
|
@ -69,9 +71,9 @@ import eu.kanade.domain.ui.UiPreferences
|
||||||
import eu.kanade.presentation.reader.ChapterListDialog
|
import eu.kanade.presentation.reader.ChapterListDialog
|
||||||
import eu.kanade.presentation.reader.DisplayRefreshHost
|
import eu.kanade.presentation.reader.DisplayRefreshHost
|
||||||
import eu.kanade.presentation.reader.OrientationSelectDialog
|
import eu.kanade.presentation.reader.OrientationSelectDialog
|
||||||
import eu.kanade.presentation.reader.PageIndicatorText
|
|
||||||
import eu.kanade.presentation.reader.ReaderContentOverlay
|
import eu.kanade.presentation.reader.ReaderContentOverlay
|
||||||
import eu.kanade.presentation.reader.ReaderPageActionsDialog
|
import eu.kanade.presentation.reader.ReaderPageActionsDialog
|
||||||
|
import eu.kanade.presentation.reader.ReaderPageIndicator
|
||||||
import eu.kanade.presentation.reader.ReadingModeSelectDialog
|
import eu.kanade.presentation.reader.ReadingModeSelectDialog
|
||||||
import eu.kanade.presentation.reader.appbars.NavBarType
|
import eu.kanade.presentation.reader.appbars.NavBarType
|
||||||
import eu.kanade.presentation.reader.appbars.ReaderAppBars
|
import eu.kanade.presentation.reader.appbars.ReaderAppBars
|
||||||
|
|
@ -171,10 +173,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
private val preferences = Injekt.get<BasePreferences>()
|
private val preferences = Injekt.get<BasePreferences>()
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
private val uiPreferences = Injekt.get<UiPreferences>()
|
val themeCoverBased = Injekt.get<UiPreferences>().themeCoverBased().get()
|
||||||
private val themeCoverBased = uiPreferences.themeCoverBased().get()
|
|
||||||
private val themeDarkAmoled = uiPreferences.themeDarkAmoled().get()
|
|
||||||
private val themeCoverBasedStyle = uiPreferences.themeCoverBasedStyle().get()
|
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
||||||
// AM (CONNECTIONS) -->
|
// AM (CONNECTIONS) -->
|
||||||
|
|
@ -186,8 +185,6 @@ class ReaderActivity : BaseActivity() {
|
||||||
val viewModel by viewModels<ReaderViewModel>()
|
val viewModel by viewModels<ReaderViewModel>()
|
||||||
private var assistUrl: String? = null
|
private var assistUrl: String? = null
|
||||||
|
|
||||||
private val hasCutout by lazy { hasDisplayCutout() }
|
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
private val sourceManager = Injekt.get<SourceManager>()
|
private val sourceManager = Injekt.get<SourceManager>()
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
@ -201,7 +198,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
private var readingModeToast: Toast? = null
|
private var readingModeToast: Toast? = null
|
||||||
private val displayRefreshHost = DisplayRefreshHost()
|
private val displayRefreshHost = DisplayRefreshHost()
|
||||||
|
|
||||||
private val windowInsetsController by lazy { WindowInsetsControllerCompat(window, binding.root) }
|
private val windowInsetsController by lazy { WindowInsetsControllerCompat(window, window.decorView) }
|
||||||
|
|
||||||
private var loadingIndicator: ReaderProgressIndicator? = null
|
private var loadingIndicator: ReaderProgressIndicator? = null
|
||||||
|
|
||||||
|
|
@ -224,10 +221,17 @@ class ReaderActivity : BaseActivity() {
|
||||||
overridePendingTransition(R.anim.shared_axis_x_push_enter, R.anim.shared_axis_x_push_exit)
|
overridePendingTransition(R.anim.shared_axis_x_push_enter, R.anim.shared_axis_x_push_exit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableEdgeToEdge(navigationBarStyle = SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT))
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
window.isNavigationBarContrastEnforced = false
|
||||||
|
}
|
||||||
|
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
binding = ReaderActivityBinding.inflate(layoutInflater)
|
binding = ReaderActivityBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
binding.setComposeOverlay()
|
||||||
|
|
||||||
if (viewModel.needsInit()) {
|
if (viewModel.needsInit()) {
|
||||||
val manga = intent.extras?.getLong("manga", -1) ?: -1L
|
val manga = intent.extras?.getLong("manga", -1) ?: -1L
|
||||||
|
|
@ -253,7 +257,11 @@ class ReaderActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
config = ReaderConfig()
|
config = ReaderConfig()
|
||||||
initializeMenu()
|
setMenuVisibility(viewModel.state.value.menuVisible)
|
||||||
|
|
||||||
|
// EXH -->
|
||||||
|
enableExhAutoScroll()
|
||||||
|
// EXH <--
|
||||||
|
|
||||||
// Finish when incognito mode is disabled
|
// Finish when incognito mode is disabled
|
||||||
preferences.incognitoMode().changes()
|
preferences.incognitoMode().changes()
|
||||||
|
|
@ -310,6 +318,210 @@ class ReaderActivity : BaseActivity() {
|
||||||
.launchIn(lifecycleScope)
|
.launchIn(lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ReaderActivityBinding.setComposeOverlay(): Unit = composeOverlay.setComposeContent {
|
||||||
|
// KMK -->
|
||||||
|
TachiyomiTheme(
|
||||||
|
seedColor = seedColorState().takeIf { themeCoverBased },
|
||||||
|
typography = MaterialTheme.typography.copy(
|
||||||
|
bodyLarge = MaterialTheme.typography.bodySmall,
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
// KMK <--
|
||||||
|
val state by viewModel.state.collectAsState()
|
||||||
|
val showPageNumber by readerPreferences.showPageNumber().collectAsState()
|
||||||
|
val isFullscreen by readerPreferences.fullscreen().collectAsState()
|
||||||
|
val settingsScreenModel = remember {
|
||||||
|
ReaderSettingsScreenModel(
|
||||||
|
readerState = viewModel.state,
|
||||||
|
onChangeReadingMode = viewModel::setMangaReadingMode,
|
||||||
|
onChangeOrientation = viewModel::setMangaOrientationType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
|
if (!state.menuVisible && showPageNumber) {
|
||||||
|
ReaderPageIndicator(
|
||||||
|
// SY -->
|
||||||
|
currentPage = state.currentPageText,
|
||||||
|
// SY <--
|
||||||
|
totalPages = state.totalPages,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.BottomCenter)
|
||||||
|
.then(if (isFullscreen) Modifier else Modifier.navigationBarsPadding()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentOverlay(state = state)
|
||||||
|
|
||||||
|
AppBars(state = state)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
|
val externalStoragePermissionNotGranted = Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&
|
||||||
|
context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
|
||||||
|
PackageManager.PERMISSION_DENIED
|
||||||
|
val permissionRequester = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.RequestPermission(),
|
||||||
|
onResult = {
|
||||||
|
toast(KMR.strings.permission_writing_external_storage_succeed)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
|
val onDismissRequest = viewModel::closeDialog
|
||||||
|
when (state.dialog) {
|
||||||
|
is ReaderViewModel.Dialog.Loading -> {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = {},
|
||||||
|
confirmButton = {},
|
||||||
|
text = {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
// KMK -->
|
||||||
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
// KMK <--
|
||||||
|
)
|
||||||
|
Text(stringResource(MR.strings.loading))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ReaderViewModel.Dialog.Settings -> {
|
||||||
|
ReaderSettingsDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
onShowMenus = { setMenuVisibility(true) },
|
||||||
|
onHideMenus = { setMenuVisibility(false) },
|
||||||
|
screenModel = settingsScreenModel,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ReaderViewModel.Dialog.ReadingModeSelect -> {
|
||||||
|
ReadingModeSelectDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
screenModel = settingsScreenModel,
|
||||||
|
onChange = { stringRes ->
|
||||||
|
menuToggleToast?.cancel()
|
||||||
|
if (!readerPreferences.showReadingMode().get()) {
|
||||||
|
menuToggleToast = toast(stringRes)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ReaderViewModel.Dialog.OrientationModeSelect -> {
|
||||||
|
OrientationSelectDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
screenModel = settingsScreenModel,
|
||||||
|
onChange = { stringRes ->
|
||||||
|
menuToggleToast?.cancel()
|
||||||
|
menuToggleToast = toast(stringRes)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ReaderViewModel.Dialog.PageActions -> {
|
||||||
|
ReaderPageActionsDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
onSetAsCover = viewModel::setAsCover,
|
||||||
|
onShare = viewModel::shareImage,
|
||||||
|
// SY -->
|
||||||
|
onSave = { extra ->
|
||||||
|
// KMK -->
|
||||||
|
if (externalStoragePermissionNotGranted) {
|
||||||
|
permissionRequester.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
} else {
|
||||||
|
// KMK <--
|
||||||
|
viewModel.saveImage(extra)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onShareCombined = viewModel::shareImages,
|
||||||
|
onSaveCombined = {
|
||||||
|
// KMK -->
|
||||||
|
if (externalStoragePermissionNotGranted) {
|
||||||
|
permissionRequester.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
} else {
|
||||||
|
// KMK <--
|
||||||
|
viewModel.saveImages()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hasExtraPage = (state.dialog as? ReaderViewModel.Dialog.PageActions)?.extraPage != null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ReaderViewModel.Dialog.ChapterList -> {
|
||||||
|
var chapters by remember {
|
||||||
|
mutableStateOf(viewModel.getChapters().toImmutableList())
|
||||||
|
}
|
||||||
|
ChapterListDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
screenModel = settingsScreenModel,
|
||||||
|
chapters = chapters,
|
||||||
|
onClickChapter = {
|
||||||
|
viewModel.loadNewChapterFromDialog(it)
|
||||||
|
onDismissRequest()
|
||||||
|
},
|
||||||
|
onBookmark = { chapter ->
|
||||||
|
viewModel.toggleBookmark(chapter.id, !chapter.bookmark)
|
||||||
|
chapters = chapters.map {
|
||||||
|
if (it.chapter.id == chapter.id) {
|
||||||
|
it.copy(chapter = chapter.copy(bookmark = !chapter.bookmark))
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}.toImmutableList()
|
||||||
|
},
|
||||||
|
state.dateRelativeTime,
|
||||||
|
// KMK -->
|
||||||
|
onDownloadAction = { chapter, action ->
|
||||||
|
viewModel.handleDownloadAction(chapter, action)
|
||||||
|
},
|
||||||
|
// KMK <--
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ReaderViewModel.Dialog.AutoScrollHelp -> AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(MR.strings.action_ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = { Text(text = stringResource(SYMR.strings.eh_autoscroll_help)) },
|
||||||
|
text = { Text(text = stringResource(SYMR.strings.eh_autoscroll_help_message)) },
|
||||||
|
)
|
||||||
|
|
||||||
|
ReaderViewModel.Dialog.BoostPageHelp -> AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(MR.strings.action_ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = { Text(text = stringResource(SYMR.strings.eh_boost_page_help)) },
|
||||||
|
text = { Text(text = stringResource(SYMR.strings.eh_boost_page_help_message)) },
|
||||||
|
)
|
||||||
|
|
||||||
|
ReaderViewModel.Dialog.RetryAllHelp -> AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(MR.strings.action_ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = { Text(text = stringResource(SYMR.strings.eh_retry_all_help)) },
|
||||||
|
text = { Text(text = stringResource(SYMR.strings.eh_retry_all_help_message)) },
|
||||||
|
)
|
||||||
|
// SY <--
|
||||||
|
null -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
@ -411,56 +623,8 @@ class ReaderActivity : BaseActivity() {
|
||||||
return handled || super.dispatchGenericMotionEvent(event)
|
return handled || super.dispatchGenericMotionEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the reader menu. It sets up click listeners and the initial visibility.
|
|
||||||
*/
|
|
||||||
private fun initializeMenu() {
|
|
||||||
// KMK -->
|
|
||||||
@Composable
|
@Composable
|
||||||
fun pageNumberContent() {
|
private fun ContentOverlay(state: ReaderViewModel.State) {
|
||||||
// KMK <--
|
|
||||||
val state by viewModel.state.collectAsState()
|
|
||||||
val showPageNumber by viewModel.readerPreferences.showPageNumber().collectAsState()
|
|
||||||
|
|
||||||
if (!state.menuVisible && showPageNumber) {
|
|
||||||
PageIndicatorText(
|
|
||||||
// SY -->
|
|
||||||
currentPage = state.currentPageText,
|
|
||||||
// SY <--
|
|
||||||
totalPages = state.totalPages,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// KMK -->
|
|
||||||
binding.pageNumber.setComposeContent {
|
|
||||||
TachiyomiTheme(
|
|
||||||
seedColor = seedColorState().takeIf { themeCoverBased },
|
|
||||||
) {
|
|
||||||
pageNumberContent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun dialogRootContent() {
|
|
||||||
val context = LocalContext.current
|
|
||||||
// KMK <--
|
|
||||||
val state by viewModel.state.collectAsState()
|
|
||||||
val settingsScreenModel = remember {
|
|
||||||
ReaderSettingsScreenModel(
|
|
||||||
readerState = viewModel.state,
|
|
||||||
hasDisplayCutout = hasCutout,
|
|
||||||
onChangeReadingMode = viewModel::setMangaReadingMode,
|
|
||||||
onChangeOrientation = viewModel::setMangaOrientationType,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ifSourcesLoaded()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val isHttpSource = viewModel.getSource() is HttpSource
|
|
||||||
val isFullscreen by readerPreferences.fullscreen().collectAsState()
|
|
||||||
val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState()
|
val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState()
|
||||||
|
|
||||||
val colorOverlayEnabled by readerPreferences.colorFilter().collectAsState()
|
val colorOverlayEnabled by readerPreferences.colorFilter().collectAsState()
|
||||||
|
|
@ -470,6 +634,25 @@ class ReaderActivity : BaseActivity() {
|
||||||
ReaderPreferences.ColorFilterMode.getOrNull(colorOverlayMode)?.second
|
ReaderPreferences.ColorFilterMode.getOrNull(colorOverlayMode)?.second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReaderContentOverlay(
|
||||||
|
brightness = state.brightnessOverlayValue,
|
||||||
|
color = colorOverlay.takeIf { colorOverlayEnabled },
|
||||||
|
colorBlendMode = colorOverlayBlendMode,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (flashOnPageChange) {
|
||||||
|
DisplayRefreshHost(hostState = displayRefreshHost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AppBars(state: ReaderViewModel.State) {
|
||||||
|
if (!ifSourcesLoaded()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val isHttpSource = viewModel.getSource() is HttpSource
|
||||||
|
|
||||||
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 -->
|
||||||
|
|
@ -505,27 +688,8 @@ class ReaderActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
// KMK -->
|
|
||||||
val externalStoragePermissionNotGranted = Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&
|
|
||||||
context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ==
|
|
||||||
PackageManager.PERMISSION_DENIED
|
|
||||||
val permissionRequester = rememberLauncherForActivityResult(
|
|
||||||
contract = ActivityResultContracts.RequestPermission(),
|
|
||||||
onResult = {
|
|
||||||
toast(KMR.strings.permission_writing_external_storage_succeed)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
// KMK <--
|
|
||||||
|
|
||||||
ReaderContentOverlay(
|
|
||||||
brightness = state.brightnessOverlayValue,
|
|
||||||
color = colorOverlay.takeIf { colorOverlayEnabled },
|
|
||||||
colorBlendMode = colorOverlayBlendMode,
|
|
||||||
)
|
|
||||||
|
|
||||||
ReaderAppBars(
|
ReaderAppBars(
|
||||||
visible = state.menuVisible,
|
visible = state.menuVisible,
|
||||||
fullscreen = isFullscreen,
|
|
||||||
|
|
||||||
mangaTitle = state.manga?.title,
|
mangaTitle = state.manga?.title,
|
||||||
chapterTitle = state.currentChapter?.chapter?.name,
|
chapterTitle = state.currentChapter?.chapter?.name,
|
||||||
|
|
@ -599,201 +763,6 @@ class ReaderActivity : BaseActivity() {
|
||||||
onClickShiftPage = ::shiftDoublePages,
|
onClickShiftPage = ::shiftDoublePages,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
|
|
||||||
if (flashOnPageChange) {
|
|
||||||
DisplayRefreshHost(
|
|
||||||
hostState = displayRefreshHost,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val onDismissRequest = viewModel::closeDialog
|
|
||||||
when (state.dialog) {
|
|
||||||
is ReaderViewModel.Dialog.Loading -> {
|
|
||||||
AlertDialog(
|
|
||||||
onDismissRequest = {},
|
|
||||||
confirmButton = {},
|
|
||||||
text = {
|
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
) {
|
|
||||||
CircularProgressIndicator(
|
|
||||||
// KMK -->
|
|
||||||
color = MaterialTheme.colorScheme.primary,
|
|
||||||
// KMK <--
|
|
||||||
)
|
|
||||||
Text(stringResource(MR.strings.loading))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is ReaderViewModel.Dialog.Settings -> {
|
|
||||||
ReaderSettingsDialog(
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
onShowMenus = { setMenuVisibility(true) },
|
|
||||||
onHideMenus = { setMenuVisibility(false) },
|
|
||||||
screenModel = settingsScreenModel,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is ReaderViewModel.Dialog.ReadingModeSelect -> {
|
|
||||||
ReadingModeSelectDialog(
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
screenModel = settingsScreenModel,
|
|
||||||
onChange = { stringRes ->
|
|
||||||
menuToggleToast?.cancel()
|
|
||||||
if (!readerPreferences.showReadingMode().get()) {
|
|
||||||
menuToggleToast = toast(stringRes)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is ReaderViewModel.Dialog.OrientationModeSelect -> {
|
|
||||||
OrientationSelectDialog(
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
screenModel = settingsScreenModel,
|
|
||||||
onChange = { stringRes ->
|
|
||||||
menuToggleToast?.cancel()
|
|
||||||
menuToggleToast = toast(stringRes)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is ReaderViewModel.Dialog.PageActions -> {
|
|
||||||
ReaderPageActionsDialog(
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
onSetAsCover = viewModel::setAsCover,
|
|
||||||
onShare = viewModel::shareImage,
|
|
||||||
onSave = { extra ->
|
|
||||||
// KMK -->
|
|
||||||
if (externalStoragePermissionNotGranted) {
|
|
||||||
permissionRequester.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
||||||
} else {
|
|
||||||
// KMK <--
|
|
||||||
viewModel.saveImage(extra)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onShareCombined = viewModel::shareImages,
|
|
||||||
onSaveCombined = {
|
|
||||||
// KMK -->
|
|
||||||
if (externalStoragePermissionNotGranted) {
|
|
||||||
permissionRequester.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
||||||
} else {
|
|
||||||
// KMK <--
|
|
||||||
viewModel.saveImages()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hasExtraPage = (state.dialog as? ReaderViewModel.Dialog.PageActions)?.extraPage != null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is ReaderViewModel.Dialog.ChapterList -> {
|
|
||||||
var chapters by remember {
|
|
||||||
mutableStateOf(viewModel.getChapters().toImmutableList())
|
|
||||||
}
|
|
||||||
ChapterListDialog(
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
screenModel = settingsScreenModel,
|
|
||||||
chapters = chapters,
|
|
||||||
onClickChapter = {
|
|
||||||
viewModel.loadNewChapterFromDialog(it)
|
|
||||||
onDismissRequest()
|
|
||||||
},
|
|
||||||
onBookmark = { chapter ->
|
|
||||||
viewModel.toggleBookmark(chapter.id, !chapter.bookmark)
|
|
||||||
chapters = chapters.map {
|
|
||||||
if (it.chapter.id == chapter.id) {
|
|
||||||
it.copy(chapter = chapter.copy(bookmark = !chapter.bookmark))
|
|
||||||
} else {
|
|
||||||
it
|
|
||||||
}
|
|
||||||
}.toImmutableList()
|
|
||||||
},
|
|
||||||
state.dateRelativeTime,
|
|
||||||
// KMK -->
|
|
||||||
onDownloadAction = { chapter, action ->
|
|
||||||
viewModel.handleDownloadAction(chapter, action)
|
|
||||||
},
|
|
||||||
// KMK <--
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// SY -->
|
|
||||||
ReaderViewModel.Dialog.AutoScrollHelp -> AlertDialog(
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
confirmButton = {
|
|
||||||
TextButton(onClick = onDismissRequest) {
|
|
||||||
Text(text = stringResource(MR.strings.action_ok))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = { Text(text = stringResource(SYMR.strings.eh_autoscroll_help)) },
|
|
||||||
text = { Text(text = stringResource(SYMR.strings.eh_autoscroll_help_message)) },
|
|
||||||
)
|
|
||||||
ReaderViewModel.Dialog.BoostPageHelp -> AlertDialog(
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
confirmButton = {
|
|
||||||
TextButton(onClick = onDismissRequest) {
|
|
||||||
Text(text = stringResource(MR.strings.action_ok))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = { Text(text = stringResource(SYMR.strings.eh_boost_page_help)) },
|
|
||||||
text = { Text(text = stringResource(SYMR.strings.eh_boost_page_help_message)) },
|
|
||||||
)
|
|
||||||
ReaderViewModel.Dialog.RetryAllHelp -> AlertDialog(
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
confirmButton = {
|
|
||||||
TextButton(onClick = onDismissRequest) {
|
|
||||||
Text(text = stringResource(MR.strings.action_ok))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = { Text(text = stringResource(SYMR.strings.eh_retry_all_help)) },
|
|
||||||
text = { Text(text = stringResource(SYMR.strings.eh_retry_all_help_message)) },
|
|
||||||
)
|
|
||||||
// SY <--
|
|
||||||
null -> {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// KMK -->
|
|
||||||
binding.dialogRoot.setComposeContent {
|
|
||||||
TachiyomiTheme(
|
|
||||||
seedColor = seedColorState().takeIf { themeCoverBased },
|
|
||||||
typography = MaterialTheme.typography.copy(
|
|
||||||
bodyLarge = MaterialTheme.typography.bodySmall,
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
dialogRootContent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val colorScheme = seedColorStatic()?.let {
|
|
||||||
dynamicColorScheme(
|
|
||||||
seedColor = it,
|
|
||||||
isDark = isNightMode(),
|
|
||||||
isAmoled = themeDarkAmoled,
|
|
||||||
style = themeCoverBasedStyle,
|
|
||||||
specVersion = ColorSpec.SpecVersion.SPEC_2025,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// KMK <--
|
|
||||||
|
|
||||||
val toolbarColor = ColorUtils.setAlphaComponent(
|
|
||||||
// KMK -->
|
|
||||||
if (themeCoverBased && colorScheme != null) {
|
|
||||||
colorScheme.surfaceColorAtElevation(3.dp).toArgb()
|
|
||||||
} else {
|
|
||||||
// KMK <--
|
|
||||||
SurfaceColors.SURFACE_2.getColor(this)
|
|
||||||
},
|
|
||||||
if (isNightMode()) 230 else 242, // 90% dark 95% light
|
|
||||||
)
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
window.statusBarColor = toolbarColor
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
window.navigationBarColor = toolbarColor
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set initial visibility
|
|
||||||
setMenuVisibility(viewModel.state.value.menuVisible)
|
|
||||||
|
|
||||||
enableExhAutoScroll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
|
@ -812,6 +781,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
// KMK <--
|
// KMK <--
|
||||||
|
|
||||||
|
// EXH -->
|
||||||
private fun enableExhAutoScroll() {
|
private fun enableExhAutoScroll() {
|
||||||
readerPreferences.autoscrollInterval().changes()
|
readerPreferences.autoscrollInterval().changes()
|
||||||
.combine(viewModel.state.map { it.autoScroll }.distinctUntilChanged()) { interval, enabled ->
|
.combine(viewModel.state.map { it.autoScroll }.distinctUntilChanged()) { interval, enabled ->
|
||||||
|
|
@ -965,13 +935,8 @@ class ReaderActivity : BaseActivity() {
|
||||||
viewModel.showMenus(visible)
|
viewModel.showMenus(visible)
|
||||||
if (visible) {
|
if (visible) {
|
||||||
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
|
} else if (readerPreferences.fullscreen().get()) {
|
||||||
} else {
|
|
||||||
if (readerPreferences.fullscreen().get()) {
|
|
||||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
windowInsetsController.systemBarsBehavior =
|
|
||||||
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1189,7 +1154,6 @@ class ReaderActivity : BaseActivity() {
|
||||||
* Called from the viewer whenever a [page] is marked as active. It updates the values of the
|
* Called from the viewer whenever a [page] is marked as active. It updates the values of the
|
||||||
* bottom menu and delegates the change to the presenter.
|
* bottom menu and delegates the change to the presenter.
|
||||||
*/
|
*/
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
fun onPageSelected(page: ReaderPage, hasExtraPage: Boolean = false) {
|
fun onPageSelected(page: ReaderPage, hasExtraPage: Boolean = false) {
|
||||||
// SY -->
|
// SY -->
|
||||||
val currentPageText = if (hasExtraPage) {
|
val currentPageText = if (hasExtraPage) {
|
||||||
|
|
@ -1204,18 +1168,16 @@ class ReaderActivity : BaseActivity() {
|
||||||
} else {
|
} else {
|
||||||
"${page.number}"
|
"${page.number}"
|
||||||
}
|
}
|
||||||
viewModel.onPageSelected(page, currentPageText, hasExtraPage)
|
|
||||||
// SY <--
|
// SY <--
|
||||||
|
viewModel.onPageSelected(page, /* SY --> */ currentPageText, hasExtraPage /* SY <-- */)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called from the viewer whenever a [page] is long clicked. A bottom sheet with a list of
|
* Called from the viewer whenever a [page] is long clicked. A bottom sheet with a list of
|
||||||
* actions to perform is shown.
|
* actions to perform is shown.
|
||||||
*/
|
*/
|
||||||
fun onPageLongTap(page: ReaderPage, extraPage: ReaderPage? = null) {
|
fun onPageLongTap(page: ReaderPage, /* SY --> */ extraPage: ReaderPage? = null /* SY <-- */) {
|
||||||
// SY -->
|
viewModel.openPageDialog(page, /* SY --> */ extraPage /* SY <-- */)
|
||||||
viewModel.openPageDialog(page, extraPage)
|
|
||||||
// SY <--
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1260,8 +1222,10 @@ class ReaderActivity : BaseActivity() {
|
||||||
val manga = viewModel.manga ?: return
|
val manga = viewModel.manga ?: return
|
||||||
val chapter = page.chapter.chapter
|
val chapter = page.chapter.chapter
|
||||||
|
|
||||||
// SY -->
|
val intent = uri.toShareIntent(
|
||||||
val text = if (secondPage != null) {
|
context = applicationContext,
|
||||||
|
message = // SY -->
|
||||||
|
if (secondPage != null) {
|
||||||
stringResource(
|
stringResource(
|
||||||
SYMR.strings.share_pages_info,
|
SYMR.strings.share_pages_info,
|
||||||
manga.title,
|
manga.title,
|
||||||
|
|
@ -1275,13 +1239,9 @@ class ReaderActivity : BaseActivity() {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
stringResource(MR.strings.share_page_info, manga.title, chapter.name, page.number)
|
|
||||||
}
|
|
||||||
// SY <--
|
// SY <--
|
||||||
|
stringResource(MR.strings.share_page_info, manga.title, chapter.name, page.number)
|
||||||
val intent = uri.toShareIntent(
|
},
|
||||||
context = applicationContext,
|
|
||||||
message = /* SY --> */ text, // SY <--
|
|
||||||
)
|
)
|
||||||
startActivity(Intent.createChooser(intent, stringResource(MR.strings.action_share)))
|
startActivity(Intent.createChooser(intent, stringResource(MR.strings.action_share)))
|
||||||
}
|
}
|
||||||
|
|
@ -1335,13 +1295,22 @@ class ReaderActivity : BaseActivity() {
|
||||||
* Updates viewer inset depending on fullscreen reader preferences.
|
* Updates viewer inset depending on fullscreen reader preferences.
|
||||||
*/
|
*/
|
||||||
private fun updateViewerInset(fullscreen: Boolean) {
|
private fun updateViewerInset(fullscreen: Boolean) {
|
||||||
viewModel.state.value.viewer?.getView()?.applyInsetter {
|
val view = viewModel.state.value.viewer?.getView() ?: return
|
||||||
if (!fullscreen) {
|
|
||||||
type(navigationBars = true, statusBars = true) {
|
view.applyInsetsPadding(ViewCompat.getRootWindowInsets(view), fullscreen)
|
||||||
padding()
|
ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets ->
|
||||||
|
view.applyInsetsPadding(windowInsets, fullscreen)
|
||||||
|
windowInsets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun View.applyInsetsPadding(windowInsets: WindowInsetsCompat?, fullscreen: Boolean) {
|
||||||
|
val insets = if (!fullscreen) {
|
||||||
|
windowInsets?.getInsets(WindowInsetsCompat.Type.systemBars()) ?: Insets.NONE
|
||||||
|
} else {
|
||||||
|
Insets.NONE
|
||||||
}
|
}
|
||||||
|
setPadding(insets.left, insets.top, insets.right, insets.bottom)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1483,15 +1452,13 @@ class ReaderActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setCutoutShort(enabled: Boolean) {
|
private fun setCutoutShort(enabled: Boolean) {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) return
|
if (!window.decorView.hasDisplayCutout()) return
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
window.attributes.layoutInDisplayCutoutMode = when (enabled) {
|
window.attributes.layoutInDisplayCutoutMode = when (enabled) {
|
||||||
true -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
true -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||||
false -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
|
false -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger relayout
|
|
||||||
setMenuVisibility(viewModel.state.value.menuVisible)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1546,6 +1513,7 @@ class ReaderActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
/**
|
/**
|
||||||
* Updates the Discord Rich Presence (RPC) status based on the current reader activity.
|
* Updates the Discord Rich Presence (RPC) status based on the current reader activity.
|
||||||
*
|
*
|
||||||
|
|
@ -1587,4 +1555,5 @@ class ReaderActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// KMK <--
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class ReaderSettingsScreenModel(
|
class ReaderSettingsScreenModel(
|
||||||
readerState: StateFlow<ReaderViewModel.State>,
|
readerState: StateFlow<ReaderViewModel.State>,
|
||||||
val hasDisplayCutout: Boolean,
|
|
||||||
val onChangeReadingMode: (ReadingMode) -> Unit,
|
val onChangeReadingMode: (ReadingMode) -> Unit,
|
||||||
val onChangeOrientation: (ReaderOrientation) -> Unit,
|
val onChangeOrientation: (ReaderOrientation) -> Unit,
|
||||||
val preferences: ReaderPreferences = Injekt.get(),
|
val preferences: ReaderPreferences = Injekt.get(),
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package eu.kanade.tachiyomi.util.system
|
package eu.kanade.tachiyomi.util.system
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.view.View
|
||||||
import eu.kanade.domain.ui.UiPreferences
|
import eu.kanade.domain.ui.UiPreferences
|
||||||
import eu.kanade.domain.ui.model.TabletUiMode
|
import eu.kanade.domain.ui.model.TabletUiMode
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
|
|
@ -57,11 +57,11 @@ fun Context.isNightMode(): Boolean {
|
||||||
/**
|
/**
|
||||||
* Checks whether if the device has a display cutout (i.e. notch, camera cutout, etc.).
|
* Checks whether if the device has a display cutout (i.e. notch, camera cutout, etc.).
|
||||||
*
|
*
|
||||||
* Only works in Android 9+.
|
* Only relevant from Android 9 to Android 14.
|
||||||
*/
|
*/
|
||||||
fun Activity.hasDisplayCutout(): Boolean {
|
fun View.hasDisplayCutout(): Boolean {
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&
|
return Build.VERSION.SDK_INT in Build.VERSION_CODES.P..Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
|
||||||
window.decorView.rootWindowInsets?.displayCutout != null
|
rootWindowInsets?.displayCutout != null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,6 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:descendantFocusability="blocksDescendants" />
|
android:descendantFocusability="blocksDescendants" />
|
||||||
|
|
||||||
<androidx.compose.ui.platform.ComposeView
|
|
||||||
android:id="@+id/page_number"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom|center_horizontal" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.ui.reader.ReaderNavigationOverlayView
|
<eu.kanade.tachiyomi.ui.reader.ReaderNavigationOverlayView
|
||||||
|
|
@ -30,7 +24,7 @@
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<androidx.compose.ui.platform.ComposeView
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/dialog_root"
|
android:id="@+id/compose_overlay"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ material = "com.google.android.material:material:1.13.0"
|
||||||
flexible-adapter-core = "com.github.arkon.FlexibleAdapter:flexible-adapter:c8013533"
|
flexible-adapter-core = "com.github.arkon.FlexibleAdapter:flexible-adapter:c8013533"
|
||||||
photoview = "com.github.chrisbanes:PhotoView:2.3.0"
|
photoview = "com.github.chrisbanes:PhotoView:2.3.0"
|
||||||
directionalviewpager = "com.github.tachiyomiorg:DirectionalViewPager:1.0.0"
|
directionalviewpager = "com.github.tachiyomiorg:DirectionalViewPager:1.0.0"
|
||||||
insetter = "dev.chrisbanes.insetter:insetter:0.6.1"
|
|
||||||
compose-materialmotion = "io.github.fornewid:material-motion-compose-core:2.0.1"
|
compose-materialmotion = "io.github.fornewid:material-motion-compose-core:2.0.1"
|
||||||
compose-webview = "io.github.kevinnzou:compose-webview:0.33.6"
|
compose-webview = "io.github.kevinnzou:compose-webview:0.33.6"
|
||||||
compose-grid = "io.woong.compose.grid:grid:1.2.2"
|
compose-grid = "io.woong.compose.grid:grid:1.2.2"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue