From 0746938cb997d6d76a50984d35c2ae4c11b76eec Mon Sep 17 00:00:00 2001 From: Vladimir Dostoyevskiy <99822064+VDostoyevskiy@users.noreply.github.com> Date: Sat, 9 Dec 2023 01:23:51 +0800 Subject: [PATCH] Compose bottom reader menu (#479) * Migrate bottom reader menu to Compose * Use Compose to animate bottom reader menu bars * Cleanup unused * Refine * Cleanup to use DropdownMenu * Cleanup unused * Refine BottomReaderBar layout --------- Co-authored-by: GG Bond --- .../kotlin/com/hippo/ehviewer/Settings.kt | 5 + .../tachiyomi/ui/reader/BottomReaderBar.kt | 118 ++++++++++++++ .../tachiyomi/ui/reader/ChapterNavigator.kt | 5 +- .../tachiyomi/ui/reader/ReaderActivity.kt | 151 +++--------------- .../tachiyomi/ui/reader/ReaderAppBars.kt | 47 ++++++ .../util/lang/CoroutinesExtensions.kt | 22 --- .../util/preference/PreferenceExtensions.kt | 5 - .../util/system/AnimationExtensions.kt | 22 --- .../tachiyomi/util/view/ViewExtensions.kt | 100 ------------ .../listener/SimpleAnimationListener.kt | 11 -- app/src/main/res/anim/enter_from_bottom.xml | 8 - app/src/main/res/anim/exit_to_bottom.xml | 8 - .../main/res/drawable/ic_settings_24dp.xml | 9 -- app/src/main/res/layout/info_sheet.xml | 18 --- app/src/main/res/layout/reader_activity.xml | 77 --------- 15 files changed, 193 insertions(+), 413 deletions(-) create mode 100644 app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/BottomReaderBar.kt create mode 100644 app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderAppBars.kt delete mode 100644 app/src/main/kotlin/eu/kanade/tachiyomi/util/system/AnimationExtensions.kt delete mode 100644 app/src/main/kotlin/eu/kanade/tachiyomi/widget/listener/SimpleAnimationListener.kt delete mode 100644 app/src/main/res/anim/enter_from_bottom.xml delete mode 100644 app/src/main/res/anim/exit_to_bottom.xml delete mode 100644 app/src/main/res/drawable/ic_settings_24dp.xml delete mode 100644 app/src/main/res/layout/info_sheet.xml diff --git a/app/src/main/kotlin/com/hippo/ehviewer/Settings.kt b/app/src/main/kotlin/com/hippo/ehviewer/Settings.kt index 06eeb0bbe..73b899242 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/Settings.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/Settings.kt @@ -12,6 +12,8 @@ import androidx.compose.runtime.remember import com.hippo.ehviewer.client.CHROME_USER_AGENT import com.hippo.ehviewer.client.EhUtils import com.hippo.ehviewer.client.data.FavListUrlBuilder +import eu.kanade.tachiyomi.ui.reader.setting.OrientationType +import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType import java.util.Locale import kotlin.reflect.KProperty import kotlinx.coroutines.flow.Flow @@ -177,6 +179,9 @@ object Settings : DataStorePreferences(null) { val colorFilterMode = intPref("color_filter_mode", 0) val customBrightness = boolPref("pref_custom_brightness_key", false) val customBrightnessValue = intPref("custom_brightness_value", 0) + val readingMode = intPref("pref_default_reading_mode_key", ReadingModeType.LEFT_TO_RIGHT.flagValue) + val orientationMode = intPref("pref_default_orientation_type_key", OrientationType.FREE.flagValue) + val showReaderSeekbar = boolPref("pref_show_reader_seekbar", true) init { if ("CN" == Locale.getDefault().country) { diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/BottomReaderBar.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/BottomReaderBar.kt new file mode 100644 index 000000000..e6c7c611c --- /dev/null +++ b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/BottomReaderBar.kt @@ -0,0 +1,118 @@ +package eu.kanade.tachiyomi.ui.reader + +import androidx.compose.foundation.background +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check +import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.surfaceColorAtElevation +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.DpOffset +import androidx.compose.ui.unit.dp +import com.hippo.ehviewer.R +import com.hippo.ehviewer.Settings +import com.hippo.ehviewer.collectAsState +import eu.kanade.tachiyomi.ui.reader.setting.OrientationType +import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType + +@Composable +fun BottomReaderBar(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) + + val readingMode by Settings.readingMode.collectAsState { ReadingModeType.fromPreference(it) } + var readingModeExpanded by remember { mutableStateOf(false) } + Box { + DropdownMenu( + readingModeExpanded, + onDismissRequest = { readingModeExpanded = false }, + ) { + ReadingModeType.entries.forEach { + DropdownMenuItem( + text = { Text(stringResource(it.stringRes)) }, + onClick = { + Settings.readingMode.value = it.flagValue + readingModeExpanded = false + }, + modifier = Modifier.width(192.dp), + leadingIcon = { + if (readingMode == it) { + Icon(imageVector = Icons.Default.Check, contentDescription = null) + } + }, + ) + } + } + } + + val orientationMode by Settings.orientationMode.collectAsState { OrientationType.fromPreference(it) } + var orientationModeExpanded by remember { mutableStateOf(false) } + Box { + DropdownMenu( + orientationModeExpanded, + onDismissRequest = { orientationModeExpanded = false }, + offset = DpOffset(320.dp, 0.dp), + ) { + OrientationType.entries.forEach { + DropdownMenuItem( + text = { Text(stringResource(it.stringRes)) }, + onClick = { + Settings.orientationMode.value = it.flagValue + orientationModeExpanded = false + }, + modifier = Modifier.width(192.dp), + leadingIcon = { + if (orientationMode == it) { + Icon(imageVector = Icons.Default.Check, contentDescription = null) + } + }, + ) + } + } + } + + Row( + modifier = Modifier.fillMaxWidth().background(backgroundColor).padding(8.dp), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically, + ) { + IconButton(onClick = { readingModeExpanded = true }) { + Icon( + painter = painterResource(readingMode.iconRes), + contentDescription = stringResource(R.string.viewer), + ) + } + IconButton(onClick = { orientationModeExpanded = true }) { + Icon( + painter = painterResource(orientationMode.iconRes), + contentDescription = stringResource(R.string.pref_rotation_type), + ) + } + IconButton(onClick = onClickSettings) { + Icon( + imageVector = Icons.Outlined.Settings, + contentDescription = stringResource(R.string.action_settings), + ) + } + } +} diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ChapterNavigator.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ChapterNavigator.kt index 5dbf400da..492ece9b5 100644 --- a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ChapterNavigator.kt +++ b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ChapterNavigator.kt @@ -48,14 +48,15 @@ fun ChapterNavigator( val maxTickCount = configuration.screenWidthDp / 6 val showTicks = totalPages < maxTickCount + // Match with toolbar background color set in ReaderActivity + val backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp).copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f) + // We explicitly handle direction based on the reader viewer rather than the system direction CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) { Row( modifier = Modifier.fillMaxWidth().padding(horizontal = horizontalPadding), verticalAlignment = Alignment.CenterVertically, ) { - // Match with toolbar background color set in ReaderActivity - val backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp).copy(alpha = if (isSystemInDarkTheme()) 0.9f else 0.95f) if (totalPages > 1) { CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { Row( diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index 9b42aa0fc..75b9859c0 100644 --- a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -37,8 +37,6 @@ import android.view.KeyEvent 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.webkit.MimeTypeMap import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts.CreateDocument @@ -102,12 +100,7 @@ import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.withUIContext -import eu.kanade.tachiyomi.util.system.applySystemAnimatorScale import eu.kanade.tachiyomi.util.system.isNightMode -import eu.kanade.tachiyomi.util.view.copy -import eu.kanade.tachiyomi.util.view.popupMenu -import eu.kanade.tachiyomi.util.view.setTooltip -import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener import java.io.File import java.io.IOException import kotlinx.coroutines.FlowPreview @@ -142,8 +135,7 @@ class ReaderActivity : EhActivity() { /** * Whether the menu is currently visible. */ - var menuVisible = false - private set + var menuVisible by mutableStateOf(false) private var saveImageToLauncher = registerForActivityResult( CreateDocument("todo/todo"), @@ -321,6 +313,21 @@ class ReaderActivity : EhActivity() { } } dialogState.Intercept() + + val showSeekbar by Settings.showReaderSeekbar.collectAsState() + ReaderAppBars( + visible = menuVisible, + isRtl = isRtl, + showSeekBar = showSeekbar, + currentPage = currentPage, + totalPages = totalPage, + onSliderValueChange = { + isScrollingThroughPages = true + moveToPageIndex(it) + }, + onClickSettings = { readerSettingSheetDialog?.show() }, + ) + ReaderContentOverlay( brightness = { brightnessValue }.takeIf { brightness && brightnessValue < 0 }, color = { colorOverlay }.takeIf { colorOverlayEnabled }, @@ -351,8 +358,6 @@ class ReaderActivity : EhActivity() { mCurrentIndex = if (mPage >= 0) mPage else mGalleryProvider!!.startPage } totalPage = mGalleryProvider!!.size - val viewerMode = ReadingModeType.fromPreference(ReaderPreferences.defaultReadingMode().get()) - binding.actionReadingMode.setImageResource(viewerMode.iconRes) viewer?.destroy() viewer = ReadingModeType.toViewer(ReaderPreferences.defaultReadingMode().get(), this) isRtl = viewer is R2LPagerViewer @@ -618,17 +623,10 @@ class ReaderActivity : EhActivity() { * Sets the visibility of the menu according to [visible] and with an optional parameter to * [animate] the views. */ - fun setMenuVisibility(visible: Boolean, animate: Boolean = true) { + fun setMenuVisibility(visible: Boolean) { menuVisible = visible if (visible) { windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) - binding.readerMenu.isVisible = true - - if (animate) { - val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_bottom) - bottomAnimation.applySystemAnimatorScale(this) - binding.readerMenuBottom.startAnimation(bottomAnimation) - } if (ReaderPreferences.showPageNumber().get()) { config?.setPageNumberVisibility(false) @@ -640,19 +638,6 @@ class ReaderActivity : EhActivity() { WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } - if (animate) { - val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_bottom) - bottomAnimation.applySystemAnimatorScale(this) - bottomAnimation.setAnimationListener( - object : SimpleAnimationListener() { - override fun onAnimationEnd(animation: Animation) { - binding.readerMenu.isVisible = false - } - }, - ) - binding.readerMenuBottom.startAnimation(bottomAnimation) - } - if (ReaderPreferences.showPageNumber().get()) { config?.setPageNumberVisibility(true) } @@ -668,9 +653,9 @@ class ReaderActivity : EhActivity() { */ @SuppressLint("PrivateResource") private fun initializeMenu() { - binding.readerMenuBottom.applyInsetter { + binding.dialogStub.applyInsetter { type(navigationBars = true) { - margin(bottom = true, horizontal = true) + margin(vertical = true, horizontal = true) } } @@ -686,26 +671,12 @@ class ReaderActivity : EhActivity() { } } - // Init listeners on bottom menu - binding.readerNav.setMD3Content { - ChapterNavigator( - isRtl = isRtl, - currentPage = currentPage, - totalPages = totalPage, - onSliderValueChange = { - isScrollingThroughPages = true - moveToPageIndex(it) - }, - ) - } - - initBottomShortcuts() + readerSettingSheetDialog = ReaderSettingsSheet(this@ReaderActivity) val toolbarBackground = MaterialShapeDrawable.createWithElevationOverlay(this).apply { elevation = resources.getDimension(com.google.android.material.R.dimen.m3_sys_elevation_level2) alpha = if (isNightMode()) 230 else 242 // 90% dark 95% light } - binding.toolbarBottom.background = toolbarBackground.copy(this@ReaderActivity) val toolbarColor = ColorUtils.setAlphaComponent( toolbarBackground.resolvedTintColor, @@ -719,59 +690,6 @@ class ReaderActivity : EhActivity() { setMenuVisibility(menuVisible) } - private fun initBottomShortcuts() { - // Reading mode - with(binding.actionReadingMode) { - setTooltip(R.string.viewer) - - setOnClickListener { - popupMenu( - items = ReadingModeType.entries.map { it.flagValue to it.stringRes }, - selectedItemId = ReaderPreferences.defaultReadingMode().get(), - ) { - val newReadingMode = ReadingModeType.fromPreference(itemId) - ReaderPreferences.defaultReadingMode().set(newReadingMode.flagValue) - } - } - } - - // Rotation - with(binding.actionRotation) { - setTooltip(R.string.rotation_type) - - setOnClickListener { - popupMenu( - items = OrientationType.entries.map { it.flagValue to it.stringRes }, - selectedItemId = ReaderPreferences.defaultOrientationType().get(), - ) { - val newOrientation = OrientationType.fromPreference(itemId) - ReaderPreferences.defaultOrientationType().set(newOrientation.flagValue) - } - } - } - - // Settings sheet - with(binding.actionSettings) { - setTooltip(R.string.action_settings) - readerSettingSheetDialog = ReaderSettingsSheet(this@ReaderActivity) - setOnClickListener { - if (!readerSettingSheetDialog!!.isShowing) { - readerSettingSheetDialog!!.show() - } - } - - setOnLongClickListener { - ReaderSettingsSheet(this@ReaderActivity, showColorFilterSettings = true).show() - true - } - } - } - - private fun updateOrientationShortcut(preference: Int) { - val orientation = OrientationType.fromPreference(preference) - binding.actionRotation.setImageResource(orientation.iconRes) - } - /** * Dispatches a key event. If the viewer doesn't handle it, call the default implementation. */ @@ -828,15 +746,6 @@ class ReaderActivity : EhActivity() { setMenuVisibility(!menuVisible) } - /** - * Called from the viewer to show the menu. - */ - fun showMenu() { - if (!menuVisible) { - setMenuVisibility(true) - } - } - /** * Called from the viewer to hide the menu. */ @@ -854,7 +763,6 @@ class ReaderActivity : EhActivity() { if (newOrientation.flag != requestedOrientation) { requestedOrientation = newOrientation.flag } - updateOrientationShortcut(ReaderPreferences.defaultOrientationType().get()) } /** @@ -930,14 +838,6 @@ class ReaderActivity : EhActivity() { .onEach { setPageNumberVisibility(it) } .launchIn(lifecycleScope) - ReaderPreferences.showReaderSeekbar().changes() - .onEach { setReaderSeekbarVisibility(it) } - .launchIn(lifecycleScope) - - ReaderPreferences.trueColor().changes() - .onEach { setTrueColor(it) } - .launchIn(lifecycleScope) - if (hasCutout) { setCutoutShort(ReaderPreferences.cutoutShort().get()) ReaderPreferences.cutoutShort().changes() @@ -996,17 +896,6 @@ class ReaderActivity : EhActivity() { binding.pageNumber.isVisible = visible } - fun setReaderSeekbarVisibility(visible: Boolean) { - binding.readerNav.isVisible = visible - } - - /** - * Sets the 32-bit color mode according to [enabled]. - */ - private fun setTrueColor(enabled: Boolean) { - // TODO() - } - @RequiresApi(Build.VERSION_CODES.P) private fun setCutoutShort(enabled: Boolean) { window.attributes.layoutInDisplayCutoutMode = when (enabled) { diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderAppBars.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderAppBars.kt new file mode 100644 index 000000000..46bcd7190 --- /dev/null +++ b/app/src/main/kotlin/eu/kanade/tachiyomi/ui/reader/ReaderAppBars.kt @@ -0,0 +1,47 @@ +package eu.kanade.tachiyomi.ui.reader + +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.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.dp + +private val animationSpec = tween(200) + +@Composable +fun ReaderAppBars( + visible: Boolean, + isRtl: Boolean, + showSeekBar: Boolean, + currentPage: Int, + totalPages: Int, + onSliderValueChange: (Int) -> Unit, + onClickSettings: () -> Unit, +) = Column(modifier = Modifier.fillMaxHeight(), verticalArrangement = Arrangement.SpaceBetween) { + Spacer(modifier = Modifier.weight(1f)) + + AnimatedVisibility( + visible = visible, + enter = slideInVertically(initialOffsetY = { it }, animationSpec = animationSpec), + exit = slideOutVertically(targetOffsetY = { it }, animationSpec = animationSpec), + ) { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + if (showSeekBar) { + ChapterNavigator( + isRtl = isRtl, + currentPage = currentPage, + totalPages = totalPages, + onSliderValueChange = onSliderValueChange, + ) + } + BottomReaderBar(onClickSettings = onClickSettings) + } + } +} diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt index 41d697024..3b7cf25e1 100644 --- a/app/src/main/kotlin/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt +++ b/app/src/main/kotlin/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt @@ -10,17 +10,6 @@ import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -/** - * Think twice before using this. This is a delicate API. It is easy to accidentally create resource or memory leaks when GlobalScope is used. - * - * **Possible replacements** - * - suspend function - * - custom scope like view or presenter scope - */ -@DelicateCoroutinesApi -fun launchUI(block: suspend CoroutineScope.() -> Unit): Job = - GlobalScope.launch(Dispatchers.Main, CoroutineStart.DEFAULT, block) - /** * Think twice before using this. This is a delicate API. It is easy to accidentally create resource or memory leaks when GlobalScope is used. * @@ -32,17 +21,6 @@ fun launchUI(block: suspend CoroutineScope.() -> Unit): Job = fun launchIO(block: suspend CoroutineScope.() -> Unit): Job = GlobalScope.launch(Dispatchers.IO, CoroutineStart.DEFAULT, block) -/** - * Think twice before using this. This is a delicate API. It is easy to accidentally create resource or memory leaks when GlobalScope is used. - * - * **Possible replacements** - * - suspend function - * - custom scope like view or presenter scope - */ -@DelicateCoroutinesApi -fun launchNow(block: suspend CoroutineScope.() -> Unit): Job = - GlobalScope.launch(Dispatchers.Main, CoroutineStart.UNDISPATCHED, block) - fun CoroutineScope.launchUI(block: suspend CoroutineScope.() -> Unit): Job = launch(Dispatchers.Main, block = block) diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt index 213c94f27..2bb60b52d 100644 --- a/app/src/main/kotlin/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt +++ b/app/src/main/kotlin/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt @@ -26,8 +26,3 @@ operator fun Preference>.plusAssign(item: T) { operator fun Preference>.minusAssign(item: T) { set(get() - item) } - -fun Preference.toggle(): Boolean { - set(!get()) - return get() -} diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/util/system/AnimationExtensions.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/util/system/AnimationExtensions.kt deleted file mode 100644 index 3136e38c5..000000000 --- a/app/src/main/kotlin/eu/kanade/tachiyomi/util/system/AnimationExtensions.kt +++ /dev/null @@ -1,22 +0,0 @@ -package eu.kanade.tachiyomi.util.system - -import android.content.Context -import android.view.ViewPropertyAnimator -import android.view.animation.Animation -import androidx.constraintlayout.motion.widget.MotionScene.Transition - -/** Scale the duration of this [Animation] by [Context.animatorDurationScale] */ -fun Animation.applySystemAnimatorScale(context: Context) { - this.duration = (this.duration * context.animatorDurationScale).toLong() -} - -/** Scale the duration of this [Transition] by [Context.animatorDurationScale] */ -fun Transition.applySystemAnimatorScale(context: Context) { - // End layout of cover expanding animation tends to break when the transition is less than ~25ms - this.duration = (this.duration * context.animatorDurationScale).toInt().coerceAtLeast(25) -} - -/** Scale the duration of this [ViewPropertyAnimator] by [Context.animatorDurationScale] */ -fun ViewPropertyAnimator.applySystemAnimatorScale(context: Context): ViewPropertyAnimator = apply { - this.duration = (this.duration * context.animatorDurationScale).toLong() -} diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/util/view/ViewExtensions.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/util/view/ViewExtensions.kt index 412f6a13e..a5239a0fb 100644 --- a/app/src/main/kotlin/eu/kanade/tachiyomi/util/view/ViewExtensions.kt +++ b/app/src/main/kotlin/eu/kanade/tachiyomi/util/view/ViewExtensions.kt @@ -1,111 +1,11 @@ -@file:Suppress("NOTHING_TO_INLINE") - package eu.kanade.tachiyomi.util.view -import android.annotation.SuppressLint import android.content.Context import android.content.res.Resources import android.graphics.Rect import android.graphics.drawable.Drawable -import android.view.Gravity -import android.view.Menu -import android.view.MenuItem import android.view.View -import androidx.annotation.MenuRes -import androidx.annotation.StringRes -import androidx.appcompat.content.res.AppCompatResources -import androidx.appcompat.view.menu.MenuBuilder -import androidx.appcompat.widget.PopupMenu -import androidx.appcompat.widget.TooltipCompat -import androidx.core.view.forEach import com.google.android.material.shape.MaterialShapeDrawable -import com.hippo.ehviewer.R -import eu.kanade.tachiyomi.util.system.getResourceColor - -/** - * Adds a tooltip shown on long press. - * - * @param stringRes String resource for tooltip. - */ -inline fun View.setTooltip(@StringRes stringRes: Int) { - setTooltip(context.getString(stringRes)) -} - -/** - * Adds a tooltip shown on long press. - * - * @param text Text for tooltip. - */ -inline fun View.setTooltip(text: String) { - TooltipCompat.setTooltipText(this, text) -} - -/** - * Shows a popup menu on top of this view. - * - * @param menuRes menu items to inflate the menu with. - * @param initMenu function to execute when the menu after is inflated. - * @param onMenuItemClick function to execute when a menu item is clicked. - */ -inline fun View.popupMenu( - @MenuRes menuRes: Int, - noinline initMenu: (Menu.() -> Unit)? = null, - noinline onMenuItemClick: MenuItem.() -> Unit, -): PopupMenu { - val popup = PopupMenu(context, this, Gravity.NO_GRAVITY, androidx.appcompat.R.attr.actionOverflowMenuStyle, 0) - popup.menuInflater.inflate(menuRes, popup.menu) - - if (initMenu != null) { - popup.menu.initMenu() - } - popup.setOnMenuItemClickListener { - it.onMenuItemClick() - true - } - - popup.show() - return popup -} - -/** - * Shows a popup menu on top of this view. - * - * @param items menu item names to inflate the menu with. List of itemId to stringRes pairs. - * @param selectedItemId optionally show a checkmark beside an item with this itemId. - * @param onMenuItemClick function to execute when a menu item is clicked. - */ -@SuppressLint("RestrictedApi") -inline fun View.popupMenu( - items: List>, - selectedItemId: Int? = null, - noinline onMenuItemClick: MenuItem.() -> Unit, -): PopupMenu { - val popup = PopupMenu(context, this, Gravity.NO_GRAVITY, androidx.appcompat.R.attr.actionOverflowMenuStyle, 0) - items.forEach { (id, stringRes) -> - popup.menu.add(0, id, 0, stringRes) - } - - if (selectedItemId != null) { - (popup.menu as? MenuBuilder)?.setOptionalIconsVisible(true) - val emptyIcon = AppCompatResources.getDrawable(context, R.drawable.ic_blank_24dp) - popup.menu.forEach { item -> - item.icon = when (item.itemId) { - selectedItemId -> AppCompatResources.getDrawable(context, R.drawable.ic_check_24dp)?.mutate()?.apply { - setTint(context.getResourceColor(android.R.attr.textColorPrimary)) - } - else -> emptyIcon - } - } - } - - popup.setOnMenuItemClickListener { - it.onMenuItemClick() - true - } - - popup.show() - return popup -} /** * Returns a deep copy of the provided [Drawable] diff --git a/app/src/main/kotlin/eu/kanade/tachiyomi/widget/listener/SimpleAnimationListener.kt b/app/src/main/kotlin/eu/kanade/tachiyomi/widget/listener/SimpleAnimationListener.kt deleted file mode 100644 index d06ef6443..000000000 --- a/app/src/main/kotlin/eu/kanade/tachiyomi/widget/listener/SimpleAnimationListener.kt +++ /dev/null @@ -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) {} -} diff --git a/app/src/main/res/anim/enter_from_bottom.xml b/app/src/main/res/anim/enter_from_bottom.xml deleted file mode 100644 index c9bd492a5..000000000 --- a/app/src/main/res/anim/enter_from_bottom.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/anim/exit_to_bottom.xml b/app/src/main/res/anim/exit_to_bottom.xml deleted file mode 100644 index d5d94c795..000000000 --- a/app/src/main/res/anim/exit_to_bottom.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_settings_24dp.xml b/app/src/main/res/drawable/ic_settings_24dp.xml deleted file mode 100644 index df54c6b13..000000000 --- a/app/src/main/res/drawable/ic_settings_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout/info_sheet.xml b/app/src/main/res/layout/info_sheet.xml deleted file mode 100644 index 5ece04503..000000000 --- a/app/src/main/res/layout/info_sheet.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/layout/reader_activity.xml b/app/src/main/res/layout/reader_activity.xml index 8ea129634..cd96cb0c2 100644 --- a/app/src/main/res/layout/reader_activity.xml +++ b/app/src/main/res/layout/reader_activity.xml @@ -1,6 +1,4 @@ @@ -37,79 +35,4 @@ android:layout_width="match_parent" android:layout_height="match_parent" /> - - - - - - - - - - - - - - - - - - - -