fix(read): 修复阅读设置状态与规则操作

This commit is contained in:
HapeLee
2026-07-02 22:13:09 +08:00
parent 14a35b8f12
commit 040f92d4f2
8 changed files with 80 additions and 57 deletions
@@ -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
}
@@ -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
@@ -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),
@@ -496,6 +496,7 @@ fun ReadBookRouteScreen(
) {
ReadBookMenuBar(
state = state,
preferences = readPreferences,
onIntent = viewModel::onIntent,
backdrop = menuBackdrop,
hazeState = if (useMenuHazeSource) menuHazeState else null,
@@ -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 {
@@ -149,6 +149,13 @@ fun HighlightRuleConfigSheet(
onIntent(ReadBookIntent.ExportHighlightRules)
},
)
RoundDropdownMenuItem(
text = stringResource(R.string.copy_url),
onClick = {
expanded = false
onIntent(ReadBookIntent.ExportHighlightRulesAsUrl)
},
)
}
}
},
@@ -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<String, String> = emptyMap(),
bottomBarButtons: List<ReadBookButtonConfigItem> = 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,
@@ -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<String, String>,
bottomBarButtons: List<ReadBookButtonConfigItem>,
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(