Make reader edge-to-edge (#1908)
(cherry picked from commit 5f0c4606681cd59b38ae0855c7827e149fa5488c) # Conflicts: # CHANGELOG.md # app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt # app/src/main/java/eu/kanade/presentation/reader/ReaderPageIndicator.kt # app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt # app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderBottomBar.kt # app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt
This commit is contained in:
@@ -256,7 +256,6 @@ dependencies {
|
||||
implementation(libs.directionalviewpager) {
|
||||
exclude(group = "androidx.viewpager", module = "viewpager")
|
||||
}
|
||||
implementation(libs.insetter)
|
||||
implementation(libs.richeditor.compose)
|
||||
implementation(libs.aboutLibraries.compose)
|
||||
implementation(libs.bundles.voyager)
|
||||
|
||||
+2
-4
@@ -1,6 +1,5 @@
|
||||
package eu.kanade.presentation.more.settings.screen
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -12,6 +11,7 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
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.persistentMapOf
|
||||
import kotlinx.collections.immutable.toImmutableMap
|
||||
@@ -137,9 +137,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.cutoutShort(),
|
||||
title = stringResource(MR.strings.pref_cutout_short),
|
||||
enabled = fullscreen &&
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&
|
||||
LocalView.current.rootWindowInsets?.displayCutout != null, // has cutout
|
||||
enabled = LocalView.current.hasDisplayCutout() && fullscreen,
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.keepScreenOn(),
|
||||
|
||||
+8
-7
@@ -6,6 +6,7 @@ import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
@@ -15,13 +16,12 @@ import androidx.compose.ui.unit.sp
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
|
||||
@Composable
|
||||
fun PageIndicatorText(
|
||||
// SY -->
|
||||
currentPage: String,
|
||||
// SY <--
|
||||
fun ReaderPageIndicator(
|
||||
currentPage: Int,
|
||||
totalPages: Int,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (currentPage.isEmpty() || totalPages <= 0) return
|
||||
if (currentPage <= 0 || totalPages <= 0) return
|
||||
|
||||
val text = "$currentPage / $totalPages"
|
||||
|
||||
@@ -38,6 +38,7 @@ fun PageIndicatorText(
|
||||
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = modifier,
|
||||
) {
|
||||
Text(
|
||||
text = text,
|
||||
@@ -52,10 +53,10 @@ fun PageIndicatorText(
|
||||
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun PageIndicatorTextPreview() {
|
||||
private fun ReaderPageIndicatorPreview() {
|
||||
TachiyomiPreviewTheme {
|
||||
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.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -13,10 +16,13 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.surfaceColorAtElevation
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -36,7 +42,8 @@ import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
|
||||
import kotlinx.collections.immutable.ImmutableSet
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
|
||||
private val animationSpec = tween<IntOffset>(200)
|
||||
private val readerBarsSlideAnimationSpec = tween<IntOffset>(200)
|
||||
private val readerBarsFadeAnimationSpec = tween<Float>(150)
|
||||
|
||||
// SY -->
|
||||
enum class NavBarType {
|
||||
@@ -65,7 +72,6 @@ fun BoxIgnoreLayoutDirection(modifier: Modifier, content: @Composable BoxScope.(
|
||||
@Composable
|
||||
fun ReaderAppBars(
|
||||
visible: Boolean,
|
||||
fullscreen: Boolean,
|
||||
|
||||
mangaTitle: String?,
|
||||
chapterTitle: String?,
|
||||
@@ -122,11 +128,7 @@ fun ReaderAppBars(
|
||||
.surfaceColorAtElevation(3.dp)
|
||||
.copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f)
|
||||
|
||||
val modifierWithInsetsPadding = if (fullscreen) {
|
||||
Modifier.systemBarsPadding()
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
val modifierWithInsetsPadding = Modifier.systemBarsPadding()
|
||||
|
||||
// SY -->
|
||||
BoxIgnoreLayoutDirection(
|
||||
@@ -136,11 +138,11 @@ fun ReaderAppBars(
|
||||
visible = visible && navBarType == NavBarType.VerticalLeft,
|
||||
enter = slideInHorizontally(
|
||||
initialOffsetX = { -it },
|
||||
animationSpec = animationSpec,
|
||||
animationSpec = readerBarsSlideAnimationSpec,
|
||||
),
|
||||
exit = slideOutHorizontally(
|
||||
targetOffsetX = { -it },
|
||||
animationSpec = animationSpec,
|
||||
animationSpec = readerBarsSlideAnimationSpec,
|
||||
),
|
||||
modifier = modifierWithInsetsPadding
|
||||
.padding(bottom = 48.dp, top = 120.dp)
|
||||
@@ -164,11 +166,11 @@ fun ReaderAppBars(
|
||||
visible = visible && navBarType == NavBarType.VerticalRight,
|
||||
enter = slideInHorizontally(
|
||||
initialOffsetX = { it },
|
||||
animationSpec = animationSpec,
|
||||
animationSpec = readerBarsSlideAnimationSpec,
|
||||
),
|
||||
exit = slideOutHorizontally(
|
||||
targetOffsetX = { it },
|
||||
animationSpec = animationSpec,
|
||||
animationSpec = readerBarsSlideAnimationSpec,
|
||||
),
|
||||
modifier = modifierWithInsetsPadding
|
||||
.padding(bottom = 48.dp, top = 120.dp)
|
||||
@@ -196,16 +198,17 @@ fun ReaderAppBars(
|
||||
visible = visible,
|
||||
enter = slideInVertically(
|
||||
initialOffsetY = { -it },
|
||||
animationSpec = animationSpec,
|
||||
),
|
||||
animationSpec = readerBarsSlideAnimationSpec,
|
||||
) + fadeIn(animationSpec = readerBarsFadeAnimationSpec),
|
||||
exit = slideOutVertically(
|
||||
targetOffsetY = { -it },
|
||||
animationSpec = animationSpec,
|
||||
),
|
||||
animationSpec = readerBarsSlideAnimationSpec,
|
||||
) + fadeOut(animationSpec = readerBarsFadeAnimationSpec),
|
||||
) {
|
||||
// SY -->
|
||||
Column(modifierWithInsetsPadding) {
|
||||
// SY <--
|
||||
// TODO: Use ReaderTopBar
|
||||
AppBar(
|
||||
modifier = /*SY --> */ Modifier /*SY <-- */
|
||||
.clickable(onClick = onClickTopAppBar),
|
||||
@@ -265,12 +268,12 @@ fun ReaderAppBars(
|
||||
visible = visible,
|
||||
enter = slideInVertically(
|
||||
initialOffsetY = { it },
|
||||
animationSpec = animationSpec,
|
||||
),
|
||||
animationSpec = readerBarsSlideAnimationSpec,
|
||||
) + fadeIn(animationSpec = readerBarsFadeAnimationSpec),
|
||||
exit = slideOutVertically(
|
||||
targetOffsetY = { it },
|
||||
animationSpec = animationSpec,
|
||||
),
|
||||
animationSpec = readerBarsSlideAnimationSpec,
|
||||
) + fadeOut(animationSpec = readerBarsFadeAnimationSpec),
|
||||
) {
|
||||
Column(
|
||||
modifier = modifierWithInsetsPadding,
|
||||
@@ -291,11 +294,10 @@ fun ReaderAppBars(
|
||||
)
|
||||
}
|
||||
|
||||
BottomReaderBar(
|
||||
ReaderBottomBar(
|
||||
// SY -->
|
||||
enabledButtons = enabledButtons,
|
||||
// SY <--
|
||||
backgroundColor = backgroundColor,
|
||||
readingMode = readingMode,
|
||||
onClickReadingMode = onClickReadingMode,
|
||||
orientation = orientation,
|
||||
@@ -313,6 +315,12 @@ fun ReaderAppBars(
|
||||
onClickShare = onShare,
|
||||
onClickPageLayout = onClickPageLayout,
|
||||
onClickShiftPage = onClickShiftPage,
|
||||
// <-- SY
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor)
|
||||
.padding(horizontal = MaterialTheme.padding.small)
|
||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-10
@@ -1,10 +1,7 @@
|
||||
package eu.kanade.presentation.reader.appbars
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
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.outlined.FormatListNumbered
|
||||
import androidx.compose.material.icons.outlined.Public
|
||||
@@ -16,8 +13,8 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderBottomButton
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
@@ -28,11 +25,10 @@ import tachiyomi.i18n.sy.SYMR
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
||||
@Composable
|
||||
fun BottomReaderBar(
|
||||
fun ReaderBottomBar(
|
||||
// SY -->
|
||||
enabledButtons: ImmutableSet<String>,
|
||||
// SY <--
|
||||
backgroundColor: Color,
|
||||
readingMode: ReadingMode,
|
||||
onClickReadingMode: () -> Unit,
|
||||
orientation: ReaderOrientation,
|
||||
@@ -51,12 +47,11 @@ fun BottomReaderBar(
|
||||
onClickPageLayout: () -> Unit,
|
||||
onClickShiftPage: () -> Unit,
|
||||
// SY <--
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(backgroundColor)
|
||||
.padding(8.dp),
|
||||
modifier = modifier
|
||||
.pointerInput(Unit) {},
|
||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||
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(),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -6,8 +6,10 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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.ReaderSettingsScreenModel
|
||||
import eu.kanade.tachiyomi.util.system.hasDisplayCutout
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
import tachiyomi.presentation.core.components.CheckboxItem
|
||||
@@ -85,7 +87,8 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
|
||||
pref = screenModel.preferences.fullscreen(),
|
||||
)
|
||||
|
||||
if (screenModel.hasDisplayCutout && screenModel.preferences.fullscreen().get()) {
|
||||
val isFullscreen by screenModel.preferences.fullscreen().collectAsState()
|
||||
if (LocalView.current.hasDisplayCutout() && isFullscreen) {
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_cutout_short),
|
||||
pref = screenModel.preferences.cutoutShort(),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package eu.kanade.tachiyomi.ui.reader
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.assist.AssistContent
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
@@ -21,25 +20,33 @@ import android.view.View
|
||||
import android.view.View.LAYER_TYPE_HARDWARE
|
||||
import android.view.WindowManager
|
||||
import android.widget.Toast
|
||||
import androidx.activity.SystemBarStyle
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
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.CircularProgressIndicator
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
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.platform.LocalConfiguration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.transition.doOnEnd
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
@@ -47,18 +54,16 @@ import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
import com.google.android.material.elevation.SurfaceColors
|
||||
import com.google.android.material.transition.platform.MaterialContainerTransform
|
||||
import com.hippo.unifile.UniFile
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.manga.model.readingMode
|
||||
import eu.kanade.presentation.reader.ChapterListDialog
|
||||
import eu.kanade.presentation.reader.DisplayRefreshHost
|
||||
import eu.kanade.presentation.reader.OrientationSelectDialog
|
||||
import eu.kanade.presentation.reader.PageIndicatorText
|
||||
import eu.kanade.presentation.reader.ReaderContentOverlay
|
||||
import eu.kanade.presentation.reader.ReaderPageActionsDialog
|
||||
import eu.kanade.presentation.reader.ReaderPageIndicator
|
||||
import eu.kanade.presentation.reader.ReadingModeSelectDialog
|
||||
import eu.kanade.presentation.reader.appbars.NavBarType
|
||||
import eu.kanade.presentation.reader.appbars.ReaderAppBars
|
||||
@@ -135,7 +140,12 @@ class ReaderActivity : BaseActivity() {
|
||||
|
||||
companion object {
|
||||
|
||||
fun newIntent(context: Context, mangaId: Long?, chapterId: Long?/* SY --> */, page: Int? = null/* SY <-- */): Intent {
|
||||
fun newIntent(
|
||||
context: Context,
|
||||
mangaId: Long?,
|
||||
chapterId: Long?,
|
||||
/* SY --> */ page: Int? = null, /* SY <-- */
|
||||
): Intent {
|
||||
return Intent(context, ReaderActivity::class.java).apply {
|
||||
putExtra("manga", mangaId)
|
||||
putExtra("chapter", chapterId)
|
||||
@@ -159,8 +169,6 @@ class ReaderActivity : BaseActivity() {
|
||||
val viewModel by viewModels<ReaderViewModel>()
|
||||
private var assistUrl: String? = null
|
||||
|
||||
private val hasCutout by lazy { hasDisplayCutout() }
|
||||
|
||||
// SY -->
|
||||
private val sourceManager = Injekt.get<SourceManager>()
|
||||
// SY <--
|
||||
@@ -174,7 +182,7 @@ class ReaderActivity : BaseActivity() {
|
||||
private var readingModeToast: Toast? = null
|
||||
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
|
||||
|
||||
@@ -188,7 +196,7 @@ class ReaderActivity : BaseActivity() {
|
||||
registerSecureActivity(this)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
overrideActivityTransition(
|
||||
Activity.OVERRIDE_TRANSITION_OPEN,
|
||||
OVERRIDE_TRANSITION_OPEN,
|
||||
R.anim.shared_axis_x_push_enter,
|
||||
R.anim.shared_axis_x_push_exit,
|
||||
)
|
||||
@@ -197,10 +205,17 @@ class ReaderActivity : BaseActivity() {
|
||||
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)
|
||||
|
||||
binding = ReaderActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
binding.setComposeOverlay()
|
||||
|
||||
if (viewModel.needsInit()) {
|
||||
val manga = intent.extras?.getLong("manga", -1) ?: -1L
|
||||
@@ -226,7 +241,8 @@ class ReaderActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
config = ReaderConfig()
|
||||
initializeMenu()
|
||||
setMenuVisibility(viewModel.state.value.menuVisible)
|
||||
enableExhAutoScroll()
|
||||
|
||||
// Finish when incognito mode is disabled
|
||||
preferences.incognitoMode().changes()
|
||||
@@ -260,21 +276,27 @@ class ReaderActivity : BaseActivity() {
|
||||
ReaderViewModel.Event.ReloadViewerChapters -> {
|
||||
viewModel.state.value.viewerChapters?.let(::setChapters)
|
||||
}
|
||||
|
||||
ReaderViewModel.Event.PageChanged -> {
|
||||
displayRefreshHost.flash()
|
||||
}
|
||||
|
||||
is ReaderViewModel.Event.SetOrientation -> {
|
||||
setOrientation(event.orientation)
|
||||
}
|
||||
|
||||
is ReaderViewModel.Event.SavedImage -> {
|
||||
onSaveImageResult(event.result)
|
||||
}
|
||||
|
||||
is ReaderViewModel.Event.ShareImage -> {
|
||||
onShareImageResult(event.uri, event.page /* SY --> */, event.secondPage /* SY <-- */)
|
||||
}
|
||||
|
||||
is ReaderViewModel.Event.CopyImage -> {
|
||||
onCopyImageResult(event.uri)
|
||||
}
|
||||
|
||||
is ReaderViewModel.Event.SetCoverResult -> {
|
||||
onSetAsCoverResult(event.result)
|
||||
}
|
||||
@@ -283,6 +305,160 @@ class ReaderActivity : BaseActivity() {
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
|
||||
private fun ReaderActivityBinding.setComposeOverlay(): Unit = composeOverlay.setComposeContent {
|
||||
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(
|
||||
currentPage = state.currentPage,
|
||||
totalPages = state.totalPages,
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.then(if (isFullscreen) Modifier else Modifier.navigationBarsPadding()),
|
||||
)
|
||||
}
|
||||
|
||||
ContentOverlay(state = state)
|
||||
|
||||
AppBars(state = state)
|
||||
}
|
||||
|
||||
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()
|
||||
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 = viewModel::saveImage,
|
||||
onShareCombined = viewModel::shareImages,
|
||||
onSaveCombined = 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,
|
||||
)
|
||||
}
|
||||
// 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 -> {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity is destroyed. Cleans up the viewer, configuration and any view.
|
||||
*/
|
||||
@@ -334,7 +510,7 @@ class ReaderActivity : BaseActivity() {
|
||||
super.finish()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
overrideActivityTransition(
|
||||
Activity.OVERRIDE_TRANSITION_CLOSE,
|
||||
OVERRIDE_TRANSITION_CLOSE,
|
||||
R.anim.shared_axis_x_pop_enter,
|
||||
R.anim.shared_axis_x_pop_exit,
|
||||
)
|
||||
@@ -372,41 +548,8 @@ class ReaderActivity : BaseActivity() {
|
||||
return handled || super.dispatchGenericMotionEvent(event)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the reader menu. It sets up click listeners and the initial visibility.
|
||||
*/
|
||||
private fun initializeMenu() {
|
||||
binding.pageNumber.setComposeContent {
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
binding.dialogRoot.setComposeContent {
|
||||
val state by viewModel.state.collectAsState()
|
||||
val settingsScreenModel = remember {
|
||||
ReaderSettingsScreenModel(
|
||||
readerState = viewModel.state,
|
||||
hasDisplayCutout = hasCutout,
|
||||
onChangeReadingMode = viewModel::setMangaReadingMode,
|
||||
onChangeOrientation = viewModel::setMangaOrientationType,
|
||||
)
|
||||
}
|
||||
|
||||
if (!ifSourcesLoaded()) {
|
||||
return@setComposeContent
|
||||
}
|
||||
|
||||
val isHttpSource = viewModel.getSource() is HttpSource
|
||||
val isFullscreen by readerPreferences.fullscreen().collectAsState()
|
||||
@Composable
|
||||
private fun ContentOverlay(state: ReaderViewModel.State) {
|
||||
val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState()
|
||||
|
||||
val colorOverlayEnabled by readerPreferences.colorFilter().collectAsState()
|
||||
@@ -416,11 +559,31 @@ class ReaderActivity : BaseActivity() {
|
||||
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 cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState()
|
||||
val isPagerType = ReadingMode.isPagerType(viewModel.getMangaReadingMode())
|
||||
|
||||
// SY -->
|
||||
val readingMode = viewModel.getMangaReadingMode()
|
||||
val isPagerType = ReadingMode.isPagerType(readingMode)
|
||||
val isWebtoon = ReadingMode.WEBTOON.flagValue == readingMode
|
||||
val cropBorderContinuousVertical by readerPreferences.cropBordersContinuousVertical().collectAsState()
|
||||
val cropEnabled = if (isPagerType) {
|
||||
@@ -451,15 +614,8 @@ class ReaderActivity : BaseActivity() {
|
||||
}
|
||||
// SY <--
|
||||
|
||||
ReaderContentOverlay(
|
||||
brightness = state.brightnessOverlayValue,
|
||||
color = colorOverlay.takeIf { colorOverlayEnabled },
|
||||
colorBlendMode = colorOverlayBlendMode,
|
||||
)
|
||||
|
||||
ReaderAppBars(
|
||||
visible = state.menuVisible,
|
||||
fullscreen = isFullscreen,
|
||||
|
||||
mangaTitle = state.manga?.title,
|
||||
chapterTitle = state.currentChapter?.chapter?.name,
|
||||
@@ -533,147 +689,6 @@ class ReaderActivity : BaseActivity() {
|
||||
onClickShiftPage = ::shiftDoublePages,
|
||||
// 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()
|
||||
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 = viewModel::saveImage,
|
||||
onShareCombined = viewModel::shareImages,
|
||||
onSaveCombined = 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,
|
||||
)
|
||||
}
|
||||
// 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 -> {}
|
||||
}
|
||||
}
|
||||
|
||||
val toolbarColor = ColorUtils.setAlphaComponent(
|
||||
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()
|
||||
}
|
||||
|
||||
private fun enableExhAutoScroll() {
|
||||
@@ -777,7 +792,8 @@ class ReaderActivity : BaseActivity() {
|
||||
|
||||
private fun exhCurrentpage(): ReaderPage? {
|
||||
val viewer = viewModel.state.value.viewer
|
||||
val currentPage = (((viewer as? PagerViewer)?.currentPage ?: (viewer as? WebtoonViewer)?.currentPage) as? ReaderPage)?.index
|
||||
val currentPage =
|
||||
(((viewer as? PagerViewer)?.currentPage ?: (viewer as? WebtoonViewer)?.currentPage) as? ReaderPage)?.index
|
||||
return currentPage?.let { viewModel.state.value.viewerChapters?.currChapter?.pages?.getOrNull(it) }
|
||||
}
|
||||
|
||||
@@ -829,13 +845,8 @@ class ReaderActivity : BaseActivity() {
|
||||
viewModel.showMenus(visible)
|
||||
if (visible) {
|
||||
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.systemBarsBehavior =
|
||||
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -933,7 +944,7 @@ class ReaderActivity : BaseActivity() {
|
||||
try {
|
||||
readingModeToast?.cancel()
|
||||
readingModeToast = toast(ReadingMode.fromPreference(mode).stringRes)
|
||||
} catch (e: ArrayIndexOutOfBoundsException) {
|
||||
} catch (_: ArrayIndexOutOfBoundsException) {
|
||||
logcat(LogPriority.ERROR) { "Unknown reading mode: $mode" }
|
||||
}
|
||||
}
|
||||
@@ -1148,6 +1159,7 @@ class ReaderActivity : BaseActivity() {
|
||||
is ReaderViewModel.SaveImageResult.Success -> {
|
||||
toast(MR.strings.picture_saved)
|
||||
}
|
||||
|
||||
is ReaderViewModel.SaveImageResult.Error -> {
|
||||
logcat(LogPriority.ERROR, result.error)
|
||||
}
|
||||
@@ -1182,13 +1194,22 @@ class ReaderActivity : BaseActivity() {
|
||||
* Updates viewer inset depending on fullscreen reader preferences.
|
||||
*/
|
||||
private fun updateViewerInset(fullscreen: Boolean) {
|
||||
viewModel.state.value.viewer?.getView()?.applyInsetter {
|
||||
if (!fullscreen) {
|
||||
type(navigationBars = true, statusBars = true) {
|
||||
padding()
|
||||
val view = viewModel.state.value.viewer?.getView() ?: return
|
||||
|
||||
view.applyInsetsPadding(ViewCompat.getRootWindowInsets(view), fullscreen)
|
||||
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)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1290,6 +1311,7 @@ class ReaderActivity : BaseActivity() {
|
||||
PagerConfig.PageLayout.AUTOMATIC ->
|
||||
resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE
|
||||
|
||||
else -> false
|
||||
},
|
||||
true,
|
||||
@@ -1331,14 +1353,12 @@ class ReaderActivity : BaseActivity() {
|
||||
|
||||
private fun setCutoutShort(enabled: Boolean) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P ) return
|
||||
if (!window.decorView.hasDisplayCutout()) return
|
||||
|
||||
window.attributes.layoutInDisplayCutoutMode = when (enabled) {
|
||||
true -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||
false -> WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
|
||||
}
|
||||
|
||||
// Trigger relayout
|
||||
setMenuVisibility(viewModel.state.value.menuVisible)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1378,15 +1398,18 @@ class ReaderActivity : BaseActivity() {
|
||||
value > 0 -> {
|
||||
value / 100f
|
||||
}
|
||||
|
||||
value < 0 -> {
|
||||
0.01f
|
||||
}
|
||||
|
||||
else -> WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
|
||||
}
|
||||
window.attributes = window.attributes.apply { screenBrightness = readerBrightness }
|
||||
|
||||
viewModel.setBrightnessOverlayValue(value)
|
||||
}
|
||||
|
||||
private fun setLayerPaint(grayscale: Boolean, invertedColors: Boolean) {
|
||||
val paint = if (grayscale || invertedColors) getCombinedPaint(grayscale, invertedColors) else null
|
||||
binding.viewerContainer.setLayerType(LAYER_TYPE_HARDWARE, paint)
|
||||
|
||||
@@ -13,7 +13,6 @@ import uy.kohesive.injekt.api.get
|
||||
|
||||
class ReaderSettingsScreenModel(
|
||||
readerState: StateFlow<ReaderViewModel.State>,
|
||||
val hasDisplayCutout: Boolean,
|
||||
val onChangeReadingMode: (ReadingMode) -> Unit,
|
||||
val onChangeOrientation: (ReaderOrientation) -> Unit,
|
||||
val preferences: ReaderPreferences = Injekt.get(),
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package eu.kanade.tachiyomi.util.system
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import eu.kanade.domain.ui.model.TabletUiMode
|
||||
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.).
|
||||
*
|
||||
* Only works in Android 9+.
|
||||
* Only relevant from Android 9 to Android 14.
|
||||
*/
|
||||
fun Activity.hasDisplayCutout(): Boolean {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P &&
|
||||
window.decorView.rootWindowInsets?.displayCutout != null
|
||||
fun View.hasDisplayCutout(): Boolean {
|
||||
return Build.VERSION.SDK_INT in Build.VERSION_CODES.P..Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
|
||||
rootWindowInsets?.displayCutout != null
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,12 +13,6 @@
|
||||
android:layout_height="match_parent"
|
||||
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>
|
||||
|
||||
<eu.kanade.tachiyomi.ui.reader.ReaderNavigationOverlayView
|
||||
@@ -30,7 +24,7 @@
|
||||
android:visibility="gone" />
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/dialog_root"
|
||||
android:id="@+id/compose_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ material = "com.google.android.material:material:1.12.0"
|
||||
flexible-adapter-core = "com.github.arkon.FlexibleAdapter:flexible-adapter:c8013533"
|
||||
photoview = "com.github.chrisbanes:PhotoView:2.3.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-webview = "io.github.kevinnzou:compose-webview:0.33.6"
|
||||
compose-grid = "io.woong.compose.grid:grid:1.2.2"
|
||||
|
||||
Reference in New Issue
Block a user