diff --git a/app/src/main/java/io/legado/app/ui/book/read/MangaMenu.kt b/app/src/main/java/io/legado/app/ui/book/read/MangaMenu.kt index d1d184626..998d4b2ab 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/MangaMenu.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/MangaMenu.kt @@ -215,6 +215,8 @@ class MangaMenu @JvmOverloads constructor( tvChapterUrl.setOnClickListener(chapterViewClickListener) tvChapterUrl.setOnLongClickListener(chapterViewLongClickListener) tvSourceAction.setOnLongClickListener { + sourceMenu.menu.findItem(R.id.menu_chapter_pay).isVisible = + !ReadManga.bookSource?.getContentRule()?.payAction.isNullOrBlank() sourceMenu.show() true } diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookContract.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookContract.kt index 8a5b18d89..6dc4b5764 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookContract.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookContract.kt @@ -444,6 +444,7 @@ sealed interface ReadBookIntent { ) : ReadBookIntent data object SaveImportedHighlightRules : ReadBookIntent data object ExportHighlightRules : ReadBookIntent + data object ExportHighlightRulesAsUrl : ReadBookIntent data class ExportHighlightRulesToFile(val uri: Uri) : ReadBookIntent // Icon picker — file IO handled by ViewModel diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookMenuBar.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookMenuBar.kt index 51d927ef6..6b3ee4088 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookMenuBar.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookMenuBar.kt @@ -148,6 +148,7 @@ import dev.chrisbanes.haze.HazeState import dev.chrisbanes.haze.hazeEffect import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi import io.legado.app.R +import io.legado.app.data.repository.ReadPreferences import io.legado.app.constant.ReadMenuBlurMode import io.legado.app.constant.ReadMenuBlurStyle import io.legado.app.data.entities.Book @@ -187,6 +188,7 @@ import kotlin.math.tanh @Composable fun ReadBookMenuBar( state: ReadBookUiState, + preferences: ReadPreferences, onIntent: (ReadBookIntent) -> Unit, backdrop: Backdrop? = null, hazeState: HazeState? = null, @@ -371,6 +373,7 @@ fun ReadBookMenuBar( ReadBookMenuSurface( contentTarget = contentTarget, state = state, + preferences = preferences, colors = menuColors, onIntent = onIntent, context = context, @@ -393,6 +396,7 @@ private sealed interface ReadBookMenuContent { private fun ReadBookMenuSurface( contentTarget: ReadBookMenuContent, state: ReadBookUiState, + preferences: ReadPreferences, colors: ReadMenuColors, onIntent: (ReadBookIntent) -> Unit, context: Context, @@ -648,6 +652,7 @@ private fun ReadBookMenuSurface( onPageChanged = onReadStylePageChanged, readMenuCustomIcons = state.menuConfig.readMenuCustomIcons, bottomBarButtons = state.menuConfig.bottomBarButtons, + preferences = preferences, onIntent = onIntent, styleConfig = state.styleConfig, ) @@ -1109,14 +1114,16 @@ private fun MenuTitleBar( }, ) } - RoundDropdownMenuItem( - leadingIcon = { MenuItemIcon(Icons.Default.Payment) }, - text = stringResource(R.string.chapter_pay), - onClick = { - sourceMenuExpanded = false - onIntent(ReadBookIntent.PayAction) - }, - ) + if (!state.bookSource.getContentRule().payAction.isNullOrBlank()) { + RoundDropdownMenuItem( + leadingIcon = { MenuItemIcon(Icons.Default.Payment) }, + text = stringResource(R.string.chapter_pay), + onClick = { + sourceMenuExpanded = false + onIntent(ReadBookIntent.PayAction) + }, + ) + } RoundDropdownMenuItem( leadingIcon = { MenuItemIcon(Icons.Default.Edit) }, text = stringResource(R.string.edit_source), diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookRouteScreen.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookRouteScreen.kt index f2e1f2dce..2622bd920 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookRouteScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookRouteScreen.kt @@ -496,6 +496,7 @@ fun ReadBookRouteScreen( ) { ReadBookMenuBar( state = state, + preferences = readPreferences, onIntent = viewModel::onIntent, backdrop = menuBackdrop, hazeState = if (useMenuHazeSource) menuHazeState else null, diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt index 975539fc4..70db3ad92 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt @@ -687,6 +687,9 @@ class ReadBookViewModel( is ReadBookIntent.ExportHighlightRules -> { _effects.tryEmit(ReadBookEffect.OpenHighlightRuleExportPicker) } + is ReadBookIntent.ExportHighlightRulesAsUrl -> { + exportHighlightRulesAsUrl() + } is ReadBookIntent.ExportHighlightRulesToFile -> { exportHighlightRules(intent.uri) } @@ -3781,6 +3784,20 @@ class ReadBookViewModel( } } + private fun exportHighlightRulesAsUrl() { + val rules = _uiState.value.highlightRuleConfig.rules + execute { + uploadRepository.upload( + fileName = HighlightRuleRepository.backupFileName, + file = GSON.toJson(rules), + contentType = "application/json", + ) + }.onSuccess { url -> + context.sendToClip(url) + _effects.tryEmit(ReadBookEffect.ShowToast(context.getString(R.string.copy_url))) + } + } + private fun loadHighlightRules() { val configName = ReadBookConfig.durConfig.name _uiState.update { diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/HighlightRuleConfigSheet.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/HighlightRuleConfigSheet.kt index aa9591778..9c27ffe7d 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/HighlightRuleConfigSheet.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/HighlightRuleConfigSheet.kt @@ -149,6 +149,13 @@ fun HighlightRuleConfigSheet( onIntent(ReadBookIntent.ExportHighlightRules) }, ) + RoundDropdownMenuItem( + text = stringResource(R.string.copy_url), + onClick = { + expanded = false + onIntent(ReadBookIntent.ExportHighlightRulesAsUrl) + }, + ) } } }, diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadStyleSheet.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadStyleSheet.kt index cfa817544..3cda449da 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadStyleSheet.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadStyleSheet.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import io.legado.app.R +import io.legado.app.data.repository.ReadPreferences import io.legado.app.ui.book.read.ConfigUpdate import io.legado.app.ui.book.read.ReadBookButtonConfigItem import io.legado.app.ui.book.read.ReadBookIntent @@ -49,6 +50,7 @@ fun ReadStyleContent( onPageChanged: (Int) -> Unit = {}, readMenuCustomIcons: Map = emptyMap(), bottomBarButtons: List = emptyList(), + preferences: ReadPreferences, modifier: Modifier = Modifier, onIntent: (ReadBookIntent) -> Unit, styleConfig: ReadBookStyleConfig = ReadBookStyleConfig(), @@ -109,6 +111,7 @@ fun ReadStyleContent( ) 1 -> SystemMenuPage( + preferences = preferences, customIcons = readMenuCustomIcons, bottomBarButtons = bottomBarButtons, onIntent = onIntent, diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/SystemMenuPage.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/SystemMenuPage.kt index 9b9c9fae4..63e708c7f 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/SystemMenuPage.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/SystemMenuPage.kt @@ -57,12 +57,10 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import androidx.lifecycle.compose.collectAsStateWithLifecycle import io.legado.app.R import io.legado.app.constant.ReadMenuBlurMode import io.legado.app.constant.ReadMenuBlurStyle import io.legado.app.data.repository.ReadPreferences -import io.legado.app.data.repository.ReadSettingsRepository import io.legado.app.help.config.ReadBookConfig import io.legado.app.ui.book.read.ConfigUpdate import io.legado.app.ui.book.read.ReadBookButtonConfigItem @@ -83,7 +81,6 @@ import io.legado.app.ui.widget.components.tabRow.CardTabRow import io.legado.app.utils.GSON import io.legado.app.utils.fromJsonObject import kotlinx.coroutines.launch -import org.koin.compose.koinInject private const val COLOR_BG = 5 private const val COLOR_MENU_ACCENT = 6 @@ -97,16 +94,13 @@ private const val COLOR_BLUR_TINT = 13 @Composable internal fun SystemMenuPage( + preferences: ReadPreferences, customIcons: Map, bottomBarButtons: List, modifier: Modifier = Modifier, onIntent: (ReadBookIntent) -> Unit, ) { val context = LocalContext.current - val readSettingsRepository: ReadSettingsRepository = koinInject() - val preferences by readSettingsRepository.preferences.collectAsStateWithLifecycle( - initialValue = ReadPreferences() - ) val scope = rememberCoroutineScope() val pagerState = rememberPagerState(pageCount = { 3 }) var selectedTab by remember { mutableIntStateOf(0) } @@ -180,8 +174,6 @@ internal fun SystemMenuPage( when (page) { 0 -> GlobalMenuTab( preferences = preferences, - readBarStyle = preferences.readBarStyle, - readMenuColorMode = preferences.readMenuColorMode, onIntent = onIntent, onShowColorPicker = { id, initial -> colorPickerId = id @@ -243,15 +235,11 @@ internal fun SystemMenuPage( @Composable private fun GlobalMenuTab( preferences: ReadPreferences, - readBarStyle: Int, - readMenuColorMode: Int, onIntent: (ReadBookIntent) -> Unit, onShowColorPicker: (Int, Int) -> Unit, ) { - var bottomMode by remember(readBarStyle) { mutableIntStateOf(readBarStyle) } - var colorMode by remember(readMenuColorMode) { - mutableIntStateOf(readMenuColorMode.coerceIn(0, 1)) - } + val bottomMode = preferences.readBarStyle + val colorMode = preferences.readMenuColorMode.coerceIn(0, 1) val dayMenuBgColor = preferences.readMenuBgColor .takeIf { it != 0 } ?: ReadBookConfig.durConfig.menuBgColor(isNight = false) @@ -287,8 +275,7 @@ private fun GlobalMenuTab( ), entryValues = arrayOf("0", "1", "2"), onValueChange = { - bottomMode = it.toInt() - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ReadBarStyle(bottomMode))) + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ReadBarStyle(it.toInt()))) }, ) @@ -320,8 +307,7 @@ private fun GlobalMenuTab( ), entryValues = arrayOf("0", "1"), onValueChange = { - colorMode = it.toInt() - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuColorMode(colorMode))) + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuColorMode(it.toInt()))) }, ) @@ -391,10 +377,9 @@ private fun GlobalMenuTab( } } - var iconPosition by remember { mutableIntStateOf(preferences.titleBarIconPosition) } TinyDropdownSettingItem( title = stringResource(R.string.title_bar_icon_position), - selectedValue = iconPosition.toString(), + selectedValue = preferences.titleBarIconPosition.toString(), displayEntries = arrayOf( stringResource(R.string.position_top_start), stringResource(R.string.position_top_end), @@ -403,8 +388,11 @@ private fun GlobalMenuTab( ), entryValues = arrayOf("0", "1", "2", "3"), onValueChange = { - iconPosition = it.toInt() - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TitleBarIconPosition(iconPosition))) + onIntent( + ReadBookIntent.UpdateConfig( + ConfigUpdate.TitleBarIconPosition(it.toInt()) + ) + ) }, ) TinySwitchSettingItem( @@ -442,14 +430,11 @@ private fun GlobalMenuTab( Spacer(Modifier.height(8.dp)) - var borderEnabled by remember { - mutableStateOf(preferences.readMenuBorderWidth > 0) - } + val borderEnabled = preferences.readMenuBorderWidth > 0 TinySwitchSettingItem( title = stringResource(R.string.read_menu_border), checked = borderEnabled, onCheckedChange = { - borderEnabled = it onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.BorderWidth(if (it) 1 else 0))) }, ) @@ -531,12 +516,6 @@ private fun BottomBarTab( onShowIconSheet: () -> Unit, onShowColorPicker: (Int, Int) -> Unit, ) { - var readSliderMode by remember { mutableStateOf(preferences.readSliderMode) } - var showIconText by remember { mutableStateOf(preferences.readMenuIconShowText) } - var iconStyle by remember { mutableIntStateOf(preferences.readMenuIconStyle) } - var iconsPerRow by remember { mutableIntStateOf(preferences.readMenuIconItemsPerRow) } - var iconRowCount by remember { mutableIntStateOf(preferences.readMenuIconRowCount) } - var bottomCornerRadius by remember { mutableIntStateOf(preferences.readMenuBottomCornerRadius) } val floatingBottomBar = preferences.readMenuFloatingBottomBar val bottomBarBlurMode = if ( !floatingBottomBar && @@ -558,11 +537,10 @@ private fun BottomBarTab( TinyDropdownSettingItem( title = stringResource(R.string.read_slider_mode), - selectedValue = readSliderMode, + selectedValue = preferences.readSliderMode, displayEntries = readSliderModeEntries, entryValues = readSliderModeValues, onValueChange = { - readSliderMode = it onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ReadSliderMode(it))) }, ) @@ -571,15 +549,14 @@ private fun BottomBarTab( TinySwitchSettingItem( title = stringResource(R.string.read_menu_show_icon_text), - checked = showIconText, + checked = preferences.readMenuIconShowText, onCheckedChange = { - showIconText = it onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuIconShowText(it))) }, ) TinyDropdownSettingItem( title = stringResource(R.string.read_menu_icon_container_style), - selectedValue = iconStyle.toString(), + selectedValue = preferences.readMenuIconStyle.toString(), displayEntries = arrayOf( stringResource(R.string.read_menu_icon_style_plain), stringResource(R.string.read_menu_icon_style_tonal), @@ -587,28 +564,33 @@ private fun BottomBarTab( ), entryValues = arrayOf("0", "1", "2"), onValueChange = { - iconStyle = it.toInt() - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuIconStyle(iconStyle))) + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuIconStyle(it.toInt()))) }, ) TinySliderSettingItem( title = stringResource(R.string.read_menu_icons_per_row), - value = iconsPerRow.toFloat(), + value = preferences.readMenuIconItemsPerRow.toFloat(), valueRange = 2f..8f, steps = 5, onValueChange = { - iconsPerRow = it.toInt() - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuIconItemsPerRow(iconsPerRow))) + onIntent( + ReadBookIntent.UpdateConfig( + ConfigUpdate.MenuIconItemsPerRow(it.toInt()) + ) + ) }, ) TinySliderSettingItem( title = stringResource(R.string.read_menu_icon_row_count), - value = iconRowCount.toFloat(), + value = preferences.readMenuIconRowCount.toFloat(), valueRange = 1f..2f, steps = 0, onValueChange = { - iconRowCount = it.toInt() - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuIconRowCount(iconRowCount))) + onIntent( + ReadBookIntent.UpdateConfig( + ConfigUpdate.MenuIconRowCount(it.toInt()) + ) + ) }, ) TinyClickableSettingItem( @@ -625,12 +607,15 @@ private fun BottomBarTab( TinySliderSettingItem( title = stringResource(R.string.read_menu_bottom_corner_radius), - value = bottomCornerRadius.toFloat(), + value = preferences.readMenuBottomCornerRadius.toFloat(), valueRange = 0f..32f, steps = 31, onValueChange = { - bottomCornerRadius = it.toInt() - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.MenuBottomCornerRadius(bottomCornerRadius))) + onIntent( + ReadBookIntent.UpdateConfig( + ConfigUpdate.MenuBottomCornerRadius(it.toInt()) + ) + ) }, ) TinySwitchSettingItem(