Migrate top reader app bar to Compose
This commit is contained in:
parent
5619a4c0d9
commit
d18022c259
@ -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) {}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
<translate
|
||||
android:duration="200"
|
||||
android:fromYDelta="-100%"
|
||||
android:toYDelta="0%" />
|
||||
</set>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
<translate
|
||||
android:duration="200"
|
||||
android:fromYDelta="0%"
|
||||
android:toYDelta="-100%" />
|
||||
</set>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z" />
|
||||
</vector>
|
@ -1,9 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M17,3L7,3c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3L19,5c0,-1.1 -0.9,-2 -2,-2zM17,18l-5,-2.18L7,18L7,5h10v13z" />
|
||||
</vector>
|
@ -1,5 +1,4 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@ -42,22 +41,6 @@
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/reader_menu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:theme="?attr/actionBarTheme"
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?attr/actionBarSize" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/dialog_root"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_bookmark"
|
||||
android:icon="@drawable/ic_bookmark_border_24dp"
|
||||
android:title="@string/action_bookmark"
|
||||
app:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_remove_bookmark"
|
||||
android:icon="@drawable/ic_bookmark_24dp"
|
||||
android:title="@string/action_remove_bookmark"
|
||||
app:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_open_in_web_view"
|
||||
android:title="@string/action_open_in_web_view"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_share"
|
||||
android:title="@string/action_share"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
Loading…
Reference in New Issue
Block a user