mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Migrate top reader app bar to Compose
This commit is contained in:
		@@ -1,5 +1,6 @@
 | 
			
		||||
package eu.kanade.presentation.components
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.basicMarquee
 | 
			
		||||
import androidx.compose.foundation.interaction.MutableInteractionSource
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.RowScope
 | 
			
		||||
@@ -60,6 +61,7 @@ const val SEARCH_DEBOUNCE_MILLIS = 250L
 | 
			
		||||
@Composable
 | 
			
		||||
fun AppBar(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    backgroundColor: Color? = null,
 | 
			
		||||
    // Text
 | 
			
		||||
    title: String?,
 | 
			
		||||
    subtitle: String? = null,
 | 
			
		||||
@@ -81,6 +83,7 @@ fun AppBar(
 | 
			
		||||
 | 
			
		||||
    AppBar(
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        backgroundColor = backgroundColor,
 | 
			
		||||
        titleContent = {
 | 
			
		||||
            if (isActionMode) {
 | 
			
		||||
                AppBarTitle(actionModeCounter.toString())
 | 
			
		||||
@@ -106,6 +109,7 @@ fun AppBar(
 | 
			
		||||
@Composable
 | 
			
		||||
fun AppBar(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    backgroundColor: Color? = null,
 | 
			
		||||
    // Title
 | 
			
		||||
    titleContent: @Composable () -> Unit,
 | 
			
		||||
    // Up button
 | 
			
		||||
@@ -142,7 +146,7 @@ fun AppBar(
 | 
			
		||||
            title = titleContent,
 | 
			
		||||
            actions = actions,
 | 
			
		||||
            colors = TopAppBarDefaults.topAppBarColors(
 | 
			
		||||
                containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
 | 
			
		||||
                containerColor = backgroundColor ?: MaterialTheme.colorScheme.surfaceColorAtElevation(
 | 
			
		||||
                    elevation = if (isActionMode) 3.dp else 0.dp,
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
@@ -170,6 +174,9 @@ fun AppBarTitle(
 | 
			
		||||
                style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
                maxLines = 1,
 | 
			
		||||
                overflow = TextOverflow.Ellipsis,
 | 
			
		||||
                modifier = Modifier.basicMarquee(
 | 
			
		||||
                    delayMillis = 2_000,
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
package eu.kanade.presentation.reader.appbars
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.background
 | 
			
		||||
import androidx.compose.foundation.isSystemInDarkTheme
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Row
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
			
		||||
@@ -10,11 +9,10 @@ import androidx.compose.material.icons.Icons
 | 
			
		||||
import androidx.compose.material.icons.outlined.Settings
 | 
			
		||||
import androidx.compose.material3.Icon
 | 
			
		||||
import androidx.compose.material3.IconButton
 | 
			
		||||
import androidx.compose.material3.MaterialTheme
 | 
			
		||||
import androidx.compose.material3.surfaceColorAtElevation
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.ui.Alignment
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.graphics.Color
 | 
			
		||||
import androidx.compose.ui.res.painterResource
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
@@ -24,6 +22,7 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun BottomReaderBar(
 | 
			
		||||
    backgroundColor: Color,
 | 
			
		||||
    readingMode: ReadingModeType,
 | 
			
		||||
    onClickReadingMode: () -> Unit,
 | 
			
		||||
    orientationMode: OrientationType,
 | 
			
		||||
@@ -32,11 +31,6 @@ fun BottomReaderBar(
 | 
			
		||||
    onClickCropBorder: () -> Unit,
 | 
			
		||||
    onClickSettings: () -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    // Match with toolbar background color set in ReaderActivity
 | 
			
		||||
    val backgroundColor = MaterialTheme.colorScheme
 | 
			
		||||
        .surfaceColorAtElevation(3.dp)
 | 
			
		||||
        .copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f)
 | 
			
		||||
 | 
			
		||||
    Row(
 | 
			
		||||
        modifier = Modifier
 | 
			
		||||
            .fillMaxWidth()
 | 
			
		||||
 
 | 
			
		||||
@@ -4,14 +4,28 @@ import androidx.compose.animation.AnimatedVisibility
 | 
			
		||||
import androidx.compose.animation.core.tween
 | 
			
		||||
import androidx.compose.animation.slideInVertically
 | 
			
		||||
import androidx.compose.animation.slideOutVertically
 | 
			
		||||
import androidx.compose.foundation.clickable
 | 
			
		||||
import androidx.compose.foundation.isSystemInDarkTheme
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.layout.Spacer
 | 
			
		||||
import androidx.compose.foundation.layout.WindowInsets
 | 
			
		||||
import androidx.compose.foundation.layout.fillMaxHeight
 | 
			
		||||
import androidx.compose.foundation.layout.systemBars
 | 
			
		||||
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.surfaceColorAtElevation
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.ui.Modifier
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.unit.IntOffset
 | 
			
		||||
import androidx.compose.ui.unit.dp
 | 
			
		||||
import eu.kanade.presentation.components.AppBar
 | 
			
		||||
import eu.kanade.presentation.components.AppBarActions
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
 | 
			
		||||
@@ -22,8 +36,18 @@ private val animationSpec = tween<IntOffset>(200)
 | 
			
		||||
@Composable
 | 
			
		||||
fun ReaderAppBars(
 | 
			
		||||
    visible: Boolean,
 | 
			
		||||
    viewer: Viewer?,
 | 
			
		||||
    fullscreen: Boolean,
 | 
			
		||||
 | 
			
		||||
    mangaTitle: String?,
 | 
			
		||||
    chapterTitle: String?,
 | 
			
		||||
    navigateUp: () -> Unit,
 | 
			
		||||
    onClickTopAppBar: () -> Unit,
 | 
			
		||||
    bookmarked: Boolean,
 | 
			
		||||
    onToggleBookmarked: () -> Unit,
 | 
			
		||||
    onOpenInWebView: (() -> Unit)?,
 | 
			
		||||
    onShare: (() -> Unit)?,
 | 
			
		||||
 | 
			
		||||
    viewer: Viewer?,
 | 
			
		||||
    onNextChapter: () -> Unit,
 | 
			
		||||
    enabledNext: Boolean,
 | 
			
		||||
    onPreviousChapter: () -> Unit,
 | 
			
		||||
@@ -41,11 +65,64 @@ fun ReaderAppBars(
 | 
			
		||||
    onClickSettings: () -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    val isRtl = viewer is R2LPagerViewer
 | 
			
		||||
    val backgroundColor = MaterialTheme.colorScheme
 | 
			
		||||
        .surfaceColorAtElevation(3.dp)
 | 
			
		||||
        .copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f)
 | 
			
		||||
 | 
			
		||||
    val appBarModifier = if (fullscreen) {
 | 
			
		||||
        Modifier.windowInsetsPadding(WindowInsets.systemBars)
 | 
			
		||||
    } else {
 | 
			
		||||
        Modifier
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Column(
 | 
			
		||||
        modifier = Modifier.fillMaxHeight(),
 | 
			
		||||
        verticalArrangement = Arrangement.SpaceBetween,
 | 
			
		||||
    ) {
 | 
			
		||||
        AnimatedVisibility(
 | 
			
		||||
            visible = visible,
 | 
			
		||||
            enter = slideInVertically(
 | 
			
		||||
                initialOffsetY = { -it },
 | 
			
		||||
                animationSpec = animationSpec,
 | 
			
		||||
            ),
 | 
			
		||||
            exit = slideOutVertically(
 | 
			
		||||
                targetOffsetY = { -it },
 | 
			
		||||
                animationSpec = animationSpec,
 | 
			
		||||
            ),
 | 
			
		||||
        ) {
 | 
			
		||||
            AppBar(
 | 
			
		||||
                modifier = appBarModifier
 | 
			
		||||
                    .clickable(onClick = onClickTopAppBar),
 | 
			
		||||
                backgroundColor = backgroundColor,
 | 
			
		||||
                title = mangaTitle,
 | 
			
		||||
                subtitle = chapterTitle,
 | 
			
		||||
                navigateUp = navigateUp,
 | 
			
		||||
                actions = {
 | 
			
		||||
                    AppBarActions(
 | 
			
		||||
                        listOfNotNull(
 | 
			
		||||
                            AppBar.Action(
 | 
			
		||||
                                title = stringResource(if (bookmarked) R.string.action_remove_bookmark else R.string.action_bookmark),
 | 
			
		||||
                                icon = if (bookmarked) Icons.Outlined.Bookmark else Icons.Outlined.BookmarkBorder,
 | 
			
		||||
                                onClick = onToggleBookmarked,
 | 
			
		||||
                            ),
 | 
			
		||||
                            onOpenInWebView?.let {
 | 
			
		||||
                                AppBar.OverflowAction(
 | 
			
		||||
                                    title = stringResource(R.string.action_open_in_web_view),
 | 
			
		||||
                                    onClick = it,
 | 
			
		||||
                                )
 | 
			
		||||
                            },
 | 
			
		||||
                            onShare?.let {
 | 
			
		||||
                                AppBar.OverflowAction(
 | 
			
		||||
                                    title = stringResource(R.string.action_share),
 | 
			
		||||
                                    onClick = it,
 | 
			
		||||
                                )
 | 
			
		||||
                            },
 | 
			
		||||
                        ),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Spacer(modifier = Modifier.weight(1f))
 | 
			
		||||
 | 
			
		||||
        AnimatedVisibility(
 | 
			
		||||
@@ -74,6 +151,7 @@ fun ReaderAppBars(
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                BottomReaderBar(
 | 
			
		||||
                    backgroundColor = backgroundColor,
 | 
			
		||||
                    readingMode = readingMode,
 | 
			
		||||
                    onClickReadingMode = onClickReadingMode,
 | 
			
		||||
                    orientationMode = orientationMode,
 | 
			
		||||
 
 | 
			
		||||
@@ -13,15 +13,10 @@ import android.graphics.Paint
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.text.TextUtils
 | 
			
		||||
import android.view.KeyEvent
 | 
			
		||||
import android.view.Menu
 | 
			
		||||
import android.view.MenuItem
 | 
			
		||||
import android.view.MotionEvent
 | 
			
		||||
import android.view.View.LAYER_TYPE_HARDWARE
 | 
			
		||||
import android.view.WindowManager
 | 
			
		||||
import android.view.animation.Animation
 | 
			
		||||
import android.view.animation.AnimationUtils
 | 
			
		||||
import android.widget.Toast
 | 
			
		||||
import androidx.activity.viewModels
 | 
			
		||||
import androidx.compose.foundation.layout.Arrangement
 | 
			
		||||
@@ -44,8 +39,7 @@ import androidx.core.view.WindowInsetsControllerCompat
 | 
			
		||||
import androidx.core.view.isVisible
 | 
			
		||||
import androidx.lifecycle.lifecycleScope
 | 
			
		||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
 | 
			
		||||
import com.google.android.material.internal.ToolbarUtils
 | 
			
		||||
import com.google.android.material.shape.MaterialShapeDrawable
 | 
			
		||||
import com.google.android.material.elevation.SurfaceColors
 | 
			
		||||
import com.google.android.material.transition.platform.MaterialContainerTransform
 | 
			
		||||
import dev.chrisbanes.insetter.applyInsetter
 | 
			
		||||
import eu.kanade.domain.base.BasePreferences
 | 
			
		||||
@@ -74,13 +68,11 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressIndicator
 | 
			
		||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.applySystemAnimatorScale
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.hasDisplayCutout
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.isNightMode
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.toShareIntent
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.toast
 | 
			
		||||
import eu.kanade.tachiyomi.util.view.setComposeContent
 | 
			
		||||
import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener
 | 
			
		||||
import kotlinx.coroutines.flow.distinctUntilChanged
 | 
			
		||||
import kotlinx.coroutines.flow.drop
 | 
			
		||||
import kotlinx.coroutines.flow.filterNotNull
 | 
			
		||||
@@ -265,47 +257,6 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
        assistUrl?.let { outContent.webUri = it.toUri() }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
 | 
			
		||||
        menuInflater.inflate(R.menu.reader, menu)
 | 
			
		||||
 | 
			
		||||
        val isChapterBookmarked = viewModel.getCurrentChapter()?.chapter?.bookmark ?: false
 | 
			
		||||
        menu.findItem(R.id.action_bookmark).isVisible = !isChapterBookmarked
 | 
			
		||||
        menu.findItem(R.id.action_remove_bookmark).isVisible = isChapterBookmarked
 | 
			
		||||
 | 
			
		||||
        val isHttpSource = viewModel.getSource() is HttpSource
 | 
			
		||||
        menu.findItem(R.id.action_open_in_web_view).isVisible = isHttpSource
 | 
			
		||||
        menu.findItem(R.id.action_share).isVisible = isHttpSource
 | 
			
		||||
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when an item of the options menu was clicked. Used to handle clicks on our menu
 | 
			
		||||
     * entries.
 | 
			
		||||
     */
 | 
			
		||||
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
 | 
			
		||||
        when (item.itemId) {
 | 
			
		||||
            R.id.action_open_in_web_view -> {
 | 
			
		||||
                openChapterInWebView()
 | 
			
		||||
            }
 | 
			
		||||
            R.id.action_bookmark -> {
 | 
			
		||||
                viewModel.bookmarkCurrentChapter(true)
 | 
			
		||||
                invalidateOptionsMenu()
 | 
			
		||||
            }
 | 
			
		||||
            R.id.action_remove_bookmark -> {
 | 
			
		||||
                viewModel.bookmarkCurrentChapter(false)
 | 
			
		||||
                invalidateOptionsMenu()
 | 
			
		||||
            }
 | 
			
		||||
            R.id.action_share -> {
 | 
			
		||||
                assistUrl?.let {
 | 
			
		||||
                    val intent = it.toUri().toShareIntent(this, type = "text/plain")
 | 
			
		||||
                    startActivity(Intent.createChooser(intent, getString(R.string.action_share)))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return super.onOptionsItemSelected(item)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when the user clicks the back key or the button on the toolbar. The call is
 | 
			
		||||
     * delegated to the presenter.
 | 
			
		||||
@@ -348,35 +299,12 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
     * Initializes the reader menu. It sets up click listeners and the initial visibility.
 | 
			
		||||
     */
 | 
			
		||||
    private fun initializeMenu() {
 | 
			
		||||
        setSupportActionBar(binding.toolbar)
 | 
			
		||||
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
 | 
			
		||||
        binding.toolbar.setNavigationOnClickListener {
 | 
			
		||||
            onBackPressedDispatcher.onBackPressed()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        binding.toolbar.applyInsetter {
 | 
			
		||||
            type(navigationBars = true, statusBars = true) {
 | 
			
		||||
                margin(top = true, horizontal = true)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        binding.dialogRoot.applyInsetter {
 | 
			
		||||
            type(navigationBars = true) {
 | 
			
		||||
                margin(vertical = true, horizontal = true)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        binding.toolbar.setOnClickListener {
 | 
			
		||||
            viewModel.manga?.id?.let { id ->
 | 
			
		||||
                startActivity(
 | 
			
		||||
                    Intent(this, MainActivity::class.java).apply {
 | 
			
		||||
                        action = Constants.SHORTCUT_MANGA
 | 
			
		||||
                        putExtra(Constants.MANGA_EXTRA, id)
 | 
			
		||||
                        addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
 | 
			
		||||
                    },
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        binding.pageNumber.setComposeContent {
 | 
			
		||||
            val state by viewModel.state.collectAsState()
 | 
			
		||||
            val showPageNumber by viewModel.readerPreferences.showPageNumber().collectAsState()
 | 
			
		||||
@@ -400,6 +328,9 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val isHttpSource = viewModel.getSource() is HttpSource
 | 
			
		||||
            val isFullscreen by readerPreferences.fullscreen().collectAsState()
 | 
			
		||||
 | 
			
		||||
            val cropBorderPaged by readerPreferences.cropBorders().collectAsState()
 | 
			
		||||
            val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState()
 | 
			
		||||
            val isPagerType = ReadingModeType.isPagerType(viewModel.getMangaReadingMode())
 | 
			
		||||
@@ -407,8 +338,18 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
 | 
			
		||||
            ReaderAppBars(
 | 
			
		||||
                visible = state.menuVisible,
 | 
			
		||||
                viewer = state.viewer,
 | 
			
		||||
                fullscreen = isFullscreen,
 | 
			
		||||
 | 
			
		||||
                mangaTitle = state.manga?.title,
 | 
			
		||||
                chapterTitle = state.currentChapter?.chapter?.name,
 | 
			
		||||
                navigateUp = onBackPressedDispatcher::onBackPressed,
 | 
			
		||||
                onClickTopAppBar = ::openMangaScreen,
 | 
			
		||||
                bookmarked = state.bookmarked,
 | 
			
		||||
                onToggleBookmarked = viewModel::toggleChapterBookmark,
 | 
			
		||||
                onOpenInWebView = ::openChapterInWebView.takeIf { isHttpSource },
 | 
			
		||||
                onShare = ::shareChapter.takeIf { isHttpSource },
 | 
			
		||||
 | 
			
		||||
                viewer = state.viewer,
 | 
			
		||||
                onNextChapter = ::loadNextChapter,
 | 
			
		||||
                enabledNext = state.viewerChapters?.nextChapter != null,
 | 
			
		||||
                onPreviousChapter = ::loadPreviousChapter,
 | 
			
		||||
@@ -435,15 +376,8 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
                cropEnabled = cropEnabled,
 | 
			
		||||
                onClickCropBorder = {
 | 
			
		||||
                    val enabled = viewModel.toggleCropBorders()
 | 
			
		||||
 | 
			
		||||
                    menuToggleToast?.cancel()
 | 
			
		||||
                    menuToggleToast = toast(
 | 
			
		||||
                        if (enabled) {
 | 
			
		||||
                            R.string.on
 | 
			
		||||
                        } else {
 | 
			
		||||
                            R.string.off
 | 
			
		||||
                        },
 | 
			
		||||
                    )
 | 
			
		||||
                    menuToggleToast = toast(if (enabled) R.string.on else R.string.off)
 | 
			
		||||
                },
 | 
			
		||||
                onClickSettings = viewModel::openSettingsDialog,
 | 
			
		||||
            )
 | 
			
		||||
@@ -507,13 +441,9 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val toolbarBackground = (binding.toolbar.background as MaterialShapeDrawable).apply {
 | 
			
		||||
            elevation = resources.getDimension(R.dimen.m3_sys_elevation_level2)
 | 
			
		||||
            alpha = if (isNightMode()) 230 else 242 // 90% dark 95% light
 | 
			
		||||
        }
 | 
			
		||||
        val toolbarColor = ColorUtils.setAlphaComponent(
 | 
			
		||||
            toolbarBackground.resolvedTintColor,
 | 
			
		||||
            toolbarBackground.alpha,
 | 
			
		||||
            SurfaceColors.SURFACE_2.getColor(this),
 | 
			
		||||
            if (isNightMode()) 230 else 242, // 90% dark 95% light
 | 
			
		||||
        )
 | 
			
		||||
        window.statusBarColor = toolbarColor
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
 | 
			
		||||
@@ -531,35 +461,12 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
        viewModel.showMenus(visible)
 | 
			
		||||
        if (visible) {
 | 
			
		||||
            windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
 | 
			
		||||
            binding.readerMenu.isVisible = true
 | 
			
		||||
 | 
			
		||||
            val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top)
 | 
			
		||||
            toolbarAnimation.applySystemAnimatorScale(this)
 | 
			
		||||
            toolbarAnimation.setAnimationListener(
 | 
			
		||||
                object : SimpleAnimationListener() {
 | 
			
		||||
                    override fun onAnimationStart(animation: Animation) {
 | 
			
		||||
                        // Fix status bar being translucent the first time it's opened.
 | 
			
		||||
                        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
            )
 | 
			
		||||
            binding.toolbar.startAnimation(toolbarAnimation)
 | 
			
		||||
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
 | 
			
		||||
        } else {
 | 
			
		||||
            if (readerPreferences.fullscreen().get()) {
 | 
			
		||||
                windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
 | 
			
		||||
                windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_top)
 | 
			
		||||
            toolbarAnimation.applySystemAnimatorScale(this)
 | 
			
		||||
            toolbarAnimation.setAnimationListener(
 | 
			
		||||
                object : SimpleAnimationListener() {
 | 
			
		||||
                    override fun onAnimationEnd(animation: Animation) {
 | 
			
		||||
                        binding.readerMenu.isVisible = false
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
            )
 | 
			
		||||
            binding.toolbar.startAnimation(toolbarAnimation)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -593,14 +500,24 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
            showReadingModeToast(viewModel.getMangaReadingMode())
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        supportActionBar?.title = manga.title
 | 
			
		||||
 | 
			
		||||
        loadingIndicator = ReaderProgressIndicator(this)
 | 
			
		||||
        binding.readerContainer.addView(loadingIndicator)
 | 
			
		||||
 | 
			
		||||
        startPostponedEnterTransition()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun openMangaScreen() {
 | 
			
		||||
        viewModel.manga?.id?.let { id ->
 | 
			
		||||
            startActivity(
 | 
			
		||||
                Intent(this, MainActivity::class.java).apply {
 | 
			
		||||
                    action = Constants.SHORTCUT_MANGA
 | 
			
		||||
                    putExtra(Constants.MANGA_EXTRA, id)
 | 
			
		||||
                    addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
 | 
			
		||||
                },
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun openChapterInWebView() {
 | 
			
		||||
        val manga = viewModel.manga ?: return
 | 
			
		||||
        val source = viewModel.getSource() ?: return
 | 
			
		||||
@@ -610,6 +527,13 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun shareChapter() {
 | 
			
		||||
        assistUrl?.let {
 | 
			
		||||
            val intent = it.toUri().toShareIntent(this, type = "text/plain")
 | 
			
		||||
            startActivity(Intent.createChooser(intent, getString(R.string.action_share)))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun showReadingModeToast(mode: Int) {
 | 
			
		||||
        try {
 | 
			
		||||
            readingModeToast?.cancel()
 | 
			
		||||
@@ -629,15 +553,6 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
        binding.readerContainer.removeView(loadingIndicator)
 | 
			
		||||
        viewModel.state.value.viewer?.setChapters(viewerChapters)
 | 
			
		||||
 | 
			
		||||
        binding.toolbar.subtitle = viewerChapters.currChapter.chapter.name
 | 
			
		||||
        ToolbarUtils.getSubtitleTextView(binding.toolbar)?.let {
 | 
			
		||||
            it.ellipsize = TextUtils.TruncateAt.MARQUEE
 | 
			
		||||
            it.isSelected = true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Invalidate menu to show proper chapter bookmark state
 | 
			
		||||
        invalidateOptionsMenu()
 | 
			
		||||
 | 
			
		||||
        lifecycleScope.launchIO {
 | 
			
		||||
            viewModel.getChapterUrl()?.let { url ->
 | 
			
		||||
                assistUrl = url
 | 
			
		||||
@@ -675,7 +590,7 @@ class ReaderActivity : BaseActivity() {
 | 
			
		||||
     */
 | 
			
		||||
    private fun moveToPageIndex(index: Int) {
 | 
			
		||||
        val viewer = viewModel.state.value.viewer ?: return
 | 
			
		||||
        val currentChapter = viewModel.getCurrentChapter() ?: return
 | 
			
		||||
        val currentChapter = viewModel.state.value.currentChapter ?: return
 | 
			
		||||
        val page = currentChapter.pages?.getOrNull(index) ?: return
 | 
			
		||||
        viewer.moveToPage(page)
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -298,7 +298,10 @@ class ReaderViewModel @JvmOverloads constructor(
 | 
			
		||||
                it.viewerChapters?.unref()
 | 
			
		||||
 | 
			
		||||
                chapterToDownload = cancelQueuedDownloads(newChapters.currChapter)
 | 
			
		||||
                it.copy(viewerChapters = newChapters)
 | 
			
		||||
                it.copy(
 | 
			
		||||
                    viewerChapters = newChapters,
 | 
			
		||||
                    bookmarked = newChapters.currChapter.chapter.bookmark,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return newChapters
 | 
			
		||||
@@ -567,8 +570,8 @@ class ReaderViewModel @JvmOverloads constructor(
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the currently active chapter.
 | 
			
		||||
     */
 | 
			
		||||
    fun getCurrentChapter(): ReaderChapter? {
 | 
			
		||||
        return state.value.viewerChapters?.currChapter
 | 
			
		||||
    private fun getCurrentChapter(): ReaderChapter? {
 | 
			
		||||
        return state.value.currentChapter
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getSource() = manga?.source?.let { sourceManager.getOrStub(it) } as? HttpSource
 | 
			
		||||
@@ -588,9 +591,11 @@ class ReaderViewModel @JvmOverloads constructor(
 | 
			
		||||
    /**
 | 
			
		||||
     * Bookmarks the currently active chapter.
 | 
			
		||||
     */
 | 
			
		||||
    fun bookmarkCurrentChapter(bookmarked: Boolean) {
 | 
			
		||||
    fun toggleChapterBookmark() {
 | 
			
		||||
        val chapter = getCurrentChapter()?.chapter ?: return
 | 
			
		||||
        chapter.bookmark = bookmarked // Otherwise the bookmark icon doesn't update
 | 
			
		||||
        val bookmarked = !chapter.bookmark
 | 
			
		||||
        chapter.bookmark = bookmarked
 | 
			
		||||
 | 
			
		||||
        viewModelScope.launchNonCancellable {
 | 
			
		||||
            updateChapter.await(
 | 
			
		||||
                ChapterUpdate(
 | 
			
		||||
@@ -599,6 +604,12 @@ class ReaderViewModel @JvmOverloads constructor(
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mutableState.update {
 | 
			
		||||
            it.copy(
 | 
			
		||||
                bookmarked = bookmarked,
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -873,6 +884,7 @@ class ReaderViewModel @JvmOverloads constructor(
 | 
			
		||||
    data class State(
 | 
			
		||||
        val manga: Manga? = null,
 | 
			
		||||
        val viewerChapters: ViewerChapters? = null,
 | 
			
		||||
        val bookmarked: Boolean = false,
 | 
			
		||||
        val isLoadingAdjacentChapter: Boolean = false,
 | 
			
		||||
        val currentPage: Int = -1,
 | 
			
		||||
 | 
			
		||||
@@ -883,8 +895,11 @@ class ReaderViewModel @JvmOverloads constructor(
 | 
			
		||||
        val dialog: Dialog? = null,
 | 
			
		||||
        val menuVisible: Boolean = false,
 | 
			
		||||
    ) {
 | 
			
		||||
        val currentChapter: ReaderChapter?
 | 
			
		||||
            get() = viewerChapters?.currChapter
 | 
			
		||||
 | 
			
		||||
        val totalPages: Int
 | 
			
		||||
            get() = viewerChapters?.currChapter?.pages?.size ?: -1
 | 
			
		||||
            get() = currentChapter?.pages?.size ?: -1
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sealed interface Dialog {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
package eu.kanade.tachiyomi.widget.listener
 | 
			
		||||
 | 
			
		||||
import android.view.animation.Animation
 | 
			
		||||
 | 
			
		||||
open class SimpleAnimationListener : Animation.AnimationListener {
 | 
			
		||||
    override fun onAnimationRepeat(animation: Animation) {}
 | 
			
		||||
 | 
			
		||||
    override fun onAnimationEnd(animation: Animation) {}
 | 
			
		||||
 | 
			
		||||
    override fun onAnimationStart(animation: Animation) {}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user