From 73080902885c9d219f5534002ccf5d16a07a678f Mon Sep 17 00:00:00 2001 From: arkon Date: Fri, 4 Aug 2023 17:34:08 -0400 Subject: [PATCH] Migrate reader shortcut menus to Compose Contents' UIs should probably be improved, but that can happen separately. --- .../reader/OrientationModeSelectDialog.kt | 56 +++++++++++++++++ .../reader/ReaderPageActionsDialog.kt | 2 +- .../reader/ReadingModeSelectDialog.kt | 56 +++++++++++++++++ .../reader/settings/GeneralSettingsPage.kt | 11 ++-- .../tachiyomi/ui/reader/ReaderActivity.kt | 61 ++++++++++--------- .../tachiyomi/ui/reader/ReaderViewModel.kt | 10 +++ .../setting/ReaderSettingsScreenModel.kt | 1 + .../util/system/ContextExtensions.kt | 27 -------- .../tachiyomi/util/view/ViewExtensions.kt | 45 -------------- app/src/main/res/drawable/ic_check_24dp.xml | 9 --- 10 files changed, 161 insertions(+), 117 deletions(-) create mode 100644 app/src/main/java/eu/kanade/presentation/reader/OrientationModeSelectDialog.kt rename app/src/main/java/eu/kanade/{tachiyomi/ui => presentation}/reader/ReaderPageActionsDialog.kt (98%) create mode 100644 app/src/main/java/eu/kanade/presentation/reader/ReadingModeSelectDialog.kt delete mode 100644 app/src/main/res/drawable/ic_check_24dp.xml diff --git a/app/src/main/java/eu/kanade/presentation/reader/OrientationModeSelectDialog.kt b/app/src/main/java/eu/kanade/presentation/reader/OrientationModeSelectDialog.kt new file mode 100644 index 0000000000..9e277b7571 --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/reader/OrientationModeSelectDialog.kt @@ -0,0 +1,56 @@ +package eu.kanade.presentation.reader + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.FilterChip +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import eu.kanade.domain.manga.model.orientationType +import eu.kanade.presentation.components.AdaptiveSheet +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.ui.reader.setting.OrientationType +import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel +import tachiyomi.presentation.core.components.SettingsChipRow +import tachiyomi.presentation.core.components.material.padding + +private val orientationTypeOptions = OrientationType.entries.map { it.stringRes to it } + +@Composable +fun OrientationModeSelectDialog( + onDismissRequest: () -> Unit, + screenModel: ReaderSettingsScreenModel, + onChange: (Int) -> Unit, +) { + val manga by screenModel.mangaFlow.collectAsState() + val orientationType = remember(manga) { OrientationType.fromPreference(manga?.orientationType?.toInt()) } + + AdaptiveSheet( + onDismissRequest = onDismissRequest, + ) { + Row( + modifier = Modifier.padding(vertical = 16.dp), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), + ) { + SettingsChipRow(R.string.rotation_type) { + orientationTypeOptions.map { (stringRes, it) -> + FilterChip( + selected = it == orientationType, + onClick = { + screenModel.onChangeOrientation(it) + onChange(stringRes) + }, + label = { Text(stringResource(stringRes)) }, + ) + } + } + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageActionsDialog.kt b/app/src/main/java/eu/kanade/presentation/reader/ReaderPageActionsDialog.kt similarity index 98% rename from app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageActionsDialog.kt rename to app/src/main/java/eu/kanade/presentation/reader/ReaderPageActionsDialog.kt index 486339ebae..4c488cf91c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageActionsDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/ReaderPageActionsDialog.kt @@ -1,4 +1,4 @@ -package eu.kanade.tachiyomi.ui.reader +package eu.kanade.presentation.reader import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row diff --git a/app/src/main/java/eu/kanade/presentation/reader/ReadingModeSelectDialog.kt b/app/src/main/java/eu/kanade/presentation/reader/ReadingModeSelectDialog.kt new file mode 100644 index 0000000000..91920d2ec8 --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/reader/ReadingModeSelectDialog.kt @@ -0,0 +1,56 @@ +package eu.kanade.presentation.reader + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.FilterChip +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import eu.kanade.domain.manga.model.readingModeType +import eu.kanade.presentation.components.AdaptiveSheet +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel +import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType +import tachiyomi.presentation.core.components.SettingsChipRow +import tachiyomi.presentation.core.components.material.padding + +private val readingModeOptions = ReadingModeType.entries.map { it.stringRes to it } + +@Composable +fun ReadingModeSelectDialog( + onDismissRequest: () -> Unit, + screenModel: ReaderSettingsScreenModel, + onChange: (Int) -> Unit, +) { + val manga by screenModel.mangaFlow.collectAsState() + val readingMode = remember(manga) { ReadingModeType.fromPreference(manga?.readingModeType?.toInt()) } + + AdaptiveSheet( + onDismissRequest = onDismissRequest, + ) { + Row( + modifier = Modifier.padding(vertical = 16.dp), + horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), + ) { + SettingsChipRow(R.string.pref_category_reading_mode) { + readingModeOptions.map { (stringRes, it) -> + FilterChip( + selected = it == readingMode, + onClick = { + screenModel.onChangeReadingMode(it) + onChange(stringRes) + }, + label = { Text(stringResource(stringRes)) }, + ) + } + } + } + } +} diff --git a/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt b/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt index 884570dfa1..8d165ec766 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt @@ -42,11 +42,12 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) { pref = screenModel.preferences.fullscreen(), ) - // TODO: hide if there's no cutout - CheckboxItem( - label = stringResource(R.string.pref_cutout_short), - pref = screenModel.preferences.cutoutShort(), - ) + if (screenModel.hasDisplayCutout) { + CheckboxItem( + label = stringResource(R.string.pref_cutout_short), + pref = screenModel.preferences.cutoutShort(), + ) + } CheckboxItem( label = stringResource(R.string.pref_keep_screen_on), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index fdc22cbc95..5c21fb6fb7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -49,9 +49,11 @@ import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.transition.platform.MaterialContainerTransform import dev.chrisbanes.insetter.applyInsetter import eu.kanade.domain.base.BasePreferences -import eu.kanade.domain.manga.model.orientationType import eu.kanade.presentation.reader.ChapterNavigator +import eu.kanade.presentation.reader.OrientationModeSelectDialog import eu.kanade.presentation.reader.PageIndicatorText +import eu.kanade.presentation.reader.ReaderPageActionsDialog +import eu.kanade.presentation.reader.ReadingModeSelectDialog import eu.kanade.presentation.reader.settings.ReaderSettingsDialog import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.notification.NotificationReceiver @@ -79,7 +81,6 @@ 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.copy -import eu.kanade.tachiyomi.util.view.popupMenu import eu.kanade.tachiyomi.util.view.setComposeContent import eu.kanade.tachiyomi.util.view.setTooltip import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener @@ -124,7 +125,7 @@ class ReaderActivity : BaseActivity() { val viewModel by viewModels() private var assistUrl: String? = null - val hasCutout by lazy { hasDisplayCutout() } + private val hasCutout by lazy { hasDisplayCutout() } /** * Configuration at reader level, like background color or forced orientation. @@ -393,6 +394,7 @@ class ReaderActivity : BaseActivity() { val settingsScreenModel = remember { ReaderSettingsScreenModel( readerState = viewModel.state, + hasDisplayCutout = hasCutout, onChangeReadingMode = viewModel::setMangaReadingMode, onChangeOrientation = viewModel::setMangaOrientationType, ) @@ -423,6 +425,30 @@ class ReaderActivity : BaseActivity() { screenModel = settingsScreenModel, ) } + is ReaderViewModel.Dialog.ReadingModeSelect -> { + ReadingModeSelectDialog( + onDismissRequest = onDismissRequest, + screenModel = settingsScreenModel, + onChange = { stringRes -> + menuToggleToast?.cancel() + if (!readerPreferences.showReadingMode().get()) { + menuToggleToast = toast(stringRes) + } + + updateCropBordersShortcut() + }, + ) + } + is ReaderViewModel.Dialog.OrientationModeSelect -> { + OrientationModeSelectDialog( + onDismissRequest = onDismissRequest, + screenModel = settingsScreenModel, + onChange = { stringRes -> + menuToggleToast?.cancel() + menuToggleToast = toast(stringRes) + }, + ) + } is ReaderViewModel.Dialog.PageActions -> { ReaderPageActionsDialog( onDismissRequest = onDismissRequest, @@ -484,21 +510,7 @@ class ReaderActivity : BaseActivity() { setTooltip(R.string.viewer) setOnClickListener { - popupMenu( - items = ReadingModeType.entries.map { it.flagValue to it.stringRes }, - selectedItemId = viewModel.getMangaReadingMode(resolveDefault = false), - ) { - val newReadingMode = ReadingModeType.fromPreference(itemId) - - viewModel.setMangaReadingMode(newReadingMode) - - menuToggleToast?.cancel() - if (!readerPreferences.showReadingMode().get()) { - menuToggleToast = toast(newReadingMode.stringRes) - } - - updateCropBordersShortcut() - } + viewModel.openReadingModeSelectDialog() } } @@ -537,18 +549,7 @@ class ReaderActivity : BaseActivity() { setTooltip(R.string.rotation_type) setOnClickListener { - popupMenu( - items = OrientationType.entries.map { it.flagValue to it.stringRes }, - selectedItemId = viewModel.manga?.orientationType?.toInt() - ?: readerPreferences.defaultOrientationType().get(), - ) { - val newOrientation = OrientationType.fromPreference(itemId) - - viewModel.setMangaOrientationType(newOrientation) - - menuToggleToast?.cancel() - menuToggleToast = toast(newOrientation.stringRes) - } + viewModel.openOrientationModeSelectDialog() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt index 7da721c58f..e6c5666906 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt @@ -683,6 +683,14 @@ class ReaderViewModel( mutableState.update { it.copy(dialog = Dialog.Loading) } } + fun openReadingModeSelectDialog() { + mutableState.update { it.copy(dialog = Dialog.ReadingModeSelect) } + } + + fun openOrientationModeSelectDialog() { + mutableState.update { it.copy(dialog = Dialog.OrientationModeSelect) } + } + fun openPageDialog(page: ReaderPage) { mutableState.update { it.copy(dialog = Dialog.PageActions(page)) } } @@ -863,6 +871,8 @@ class ReaderViewModel( sealed interface Dialog { data object Loading : Dialog data object Settings : Dialog + data object ReadingModeSelect : Dialog + data object OrientationModeSelect : Dialog data class PageActions(val page: ReaderPage) : Dialog } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderSettingsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderSettingsScreenModel.kt index 6aad277108..5014ba2043 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderSettingsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderSettingsScreenModel.kt @@ -13,6 +13,7 @@ import uy.kohesive.injekt.api.get class ReaderSettingsScreenModel( readerState: StateFlow, + val hasDisplayCutout: Boolean, val onChangeReadingMode: (ReadingModeType) -> Unit, val onChangeOrientation: (OrientationType) -> Unit, val preferences: ReaderPreferences = Injekt.get(), diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt index 8cc74445b6..c9924e2978 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt @@ -7,20 +7,13 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.content.res.Configuration -import android.graphics.Color import android.graphics.drawable.Drawable import android.net.Uri import android.os.Build import android.os.PowerManager -import androidx.annotation.AttrRes -import androidx.annotation.ColorInt import androidx.appcompat.view.ContextThemeWrapper import androidx.core.content.PermissionChecker import androidx.core.content.getSystemService -import androidx.core.graphics.alpha -import androidx.core.graphics.blue -import androidx.core.graphics.green -import androidx.core.graphics.red import androidx.core.net.toUri import com.hippo.unifile.UniFile import eu.kanade.domain.ui.UiPreferences @@ -35,7 +28,6 @@ import tachiyomi.core.util.system.logcat import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.io.File -import kotlin.math.roundToInt /** * Copies a string to clipboard @@ -69,25 +61,6 @@ fun Context.copyToClipboard(label: String, content: String) { */ fun Context.hasPermission(permission: String) = PermissionChecker.checkSelfPermission(this, permission) == PermissionChecker.PERMISSION_GRANTED -/** - * Returns the color for the given attribute. - * - * @param resource the attribute. - * @param alphaFactor the alpha number [0,1]. - */ -@ColorInt fun Context.getResourceColor(@AttrRes resource: Int, alphaFactor: Float = 1f): Int { - val typedArray = obtainStyledAttributes(intArrayOf(resource)) - val color = typedArray.getColor(0, 0) - typedArray.recycle() - - if (alphaFactor < 1f) { - val alpha = (color.alpha * alphaFactor).roundToInt() - return Color.argb(alpha, color.red, color.green, color.blue) - } - - return color -} - val Context.powerManager: PowerManager get() = getSystemService()!! diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt index 60eaacbe93..44012376a2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.util.view -import android.annotation.SuppressLint import android.content.Context import android.content.res.Resources import android.graphics.Rect @@ -15,8 +14,6 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent 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.compose.material3.LocalContentColor @@ -27,11 +24,9 @@ import androidx.compose.runtime.CompositionContext import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy -import androidx.core.view.forEach import com.google.android.material.shape.MaterialShapeDrawable import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.util.system.getResourceColor inline fun ComponentActivity.setComposeContent( parent: CompositionContext? = null, @@ -110,46 +105,6 @@ inline fun View.popupMenu( 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, 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/res/drawable/ic_check_24dp.xml b/app/src/main/res/drawable/ic_check_24dp.xml deleted file mode 100644 index 6c1b167711..0000000000 --- a/app/src/main/res/drawable/ic_check_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - -