fix: 高亮逻辑问题

This commit is contained in:
HapeLee
2026-06-12 12:55:47 +08:00
parent 35875f7dd3
commit d25568d99a
2 changed files with 54 additions and 38 deletions
@@ -32,13 +32,13 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.res.stringArrayResource
import androidx.core.net.toUri
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import io.legado.app.R
@@ -73,53 +73,67 @@ fun HighlightRuleEditSheet(
onSave: (HighlightRule) -> Unit,
) {
val isNew = rule == null
val initial = rule ?: HighlightRule()
val initial = remember(show, rule) { rule ?: HighlightRule() }
val context = LocalContext.current
// Rule info state
var pattern by remember { mutableStateOf(initial.pattern) }
var name by remember { mutableStateOf(initial.name) }
var targetScope by remember { mutableIntStateOf(initial.targetScope) }
var enabled by remember { mutableStateOf(initial.enabled) }
var sampleText by remember {
var pattern by remember(show, rule) { mutableStateOf(initial.pattern) }
var name by remember(show, rule) { mutableStateOf(initial.name) }
var targetScope by remember(show, rule) { mutableIntStateOf(initial.targetScope) }
var enabled by remember(show, rule) { mutableStateOf(initial.enabled) }
var sampleText by remember(show, rule) {
mutableStateOf(initial.sampleText.ifBlank { "她轻声说:今晚就出发。" })
}
// Style state
var textColor by remember { mutableIntStateOf(initial.textColor ?: 0xFF63C37D.toInt()) }
var hasTextColor by remember { mutableStateOf(initial.textColor != null) }
var bgColor by remember { mutableIntStateOf(initial.bgColor ?: 0x20FFEB3B) }
var hasBgColor by remember { mutableStateOf(initial.bgColor != null) }
var hasUnderline by remember { mutableStateOf(initial.underlineMode > 0) }
var underlineMode by remember { mutableIntStateOf(if (initial.underlineMode > 0) initial.underlineMode else 1) }
var underlineColor by remember { mutableIntStateOf(initial.underlineColor ?: 0xFF63C37D.toInt()) }
var hasUnderlineColor by remember { mutableStateOf(initial.underlineColor != null) }
var underlineWidth by remember { mutableFloatStateOf(initial.underlineWidth) }
var underlineOffset by remember { mutableFloatStateOf(initial.underlineOffset) }
var underlineSvgPath by remember { mutableStateOf(initial.underlineSvgPath.orEmpty()) }
var bgImage by remember { mutableStateOf(initial.bgImage.orEmpty()) }
var bgImageFit by remember { mutableIntStateOf(initial.bgImageFit) }
var bgImageScale by remember { mutableFloatStateOf(initial.bgImageScale) }
var hasBgImage by remember { mutableStateOf(initial.bgImage?.isNotBlank() == true) }
var textColor by remember(show, rule) {
mutableIntStateOf(
initial.textColor ?: 0xFF63C37D.toInt()
)
}
var hasTextColor by remember(show, rule) { mutableStateOf(initial.textColor != null) }
var bgColor by remember(show, rule) { mutableIntStateOf(initial.bgColor ?: 0x20FFEB3B) }
var hasBgColor by remember(show, rule) { mutableStateOf(initial.bgColor != null) }
var hasUnderline by remember(show, rule) { mutableStateOf(initial.underlineMode > 0) }
var underlineMode by remember(
show,
rule
) { mutableIntStateOf(if (initial.underlineMode > 0) initial.underlineMode else 1) }
var underlineColor by remember(show, rule) {
mutableIntStateOf(
initial.underlineColor ?: 0xFF63C37D.toInt()
)
}
var hasUnderlineColor by remember(show, rule) { mutableStateOf(initial.underlineColor != null) }
var underlineWidth by remember(show, rule) { mutableFloatStateOf(initial.underlineWidth) }
var underlineOffset by remember(show, rule) { mutableFloatStateOf(initial.underlineOffset) }
var underlineSvgPath by remember(
show,
rule
) { mutableStateOf(initial.underlineSvgPath.orEmpty()) }
var bgImage by remember(show, rule) { mutableStateOf(initial.bgImage.orEmpty()) }
var bgImageFit by remember(show, rule) { mutableIntStateOf(initial.bgImageFit) }
var bgImageScale by remember(show, rule) { mutableFloatStateOf(initial.bgImageScale) }
var hasBgImage by remember(show, rule) { mutableStateOf(initial.bgImage?.isNotBlank() == true) }
// Config binding state — empty set = global (applies to all configs)
val allConfigNames = remember { ReadBookConfig.configList.map { it.name }.filter { it.isNotBlank() } }
var configNames by remember {
var configNames by remember(show, rule) {
mutableStateOf(initial.configName.orEmpty().configNames().toSet())
}
// Font state
var hasFont by remember { mutableStateOf(initial.fontPath?.isNotBlank() == true) }
var fontPath by remember { mutableStateOf(initial.fontPath.orEmpty()) }
var hasFont by remember(show, rule) { mutableStateOf(initial.fontPath?.isNotBlank() == true) }
var fontPath by remember(show, rule) { mutableStateOf(initial.fontPath.orEmpty()) }
// Color picker state
var showTextColorPicker by remember { mutableStateOf(false) }
var showBgColorPicker by remember { mutableStateOf(false) }
var showUnderlineColorPicker by remember { mutableStateOf(false) }
var showFontSelect by remember { mutableStateOf(false) }
var showTextColorPicker by remember(show, rule) { mutableStateOf(false) }
var showBgColorPicker by remember(show, rule) { mutableStateOf(false) }
var showUnderlineColorPicker by remember(show, rule) { mutableStateOf(false) }
var showFontSelect by remember(show, rule) { mutableStateOf(false) }
// Validation
var patternError by remember { mutableStateOf<String?>(null) }
var patternError by remember(show, rule) { mutableStateOf<String?>(null) }
// SAF image picker
val imagePicker = rememberLauncherForActivityResult(
@@ -154,22 +154,22 @@ fun SpeakEngineConfigSheet(
) {
val items = state.ttsEngineItems
val selectedValue = state.selectedTtsEngine
var pendingEngineValue by remember { mutableStateOf<String?>(null) }
var pendingEngineSelection by remember { mutableStateOf<PendingSpeakEngineSelection?>(null) }
AppAlertDialog(
show = pendingEngineValue != null,
onDismissRequest = { pendingEngineValue = null },
show = pendingEngineSelection != null,
onDismissRequest = { pendingEngineSelection = null },
title = stringResource(R.string.speak_engine),
text = stringResource(R.string.speak_engine_apply_scope),
confirmText = stringResource(R.string.general),
onConfirm = {
onIntent(ReadBookIntent.ApplySpeakEngine(pendingEngineValue))
pendingEngineValue = null
onIntent(ReadBookIntent.ApplySpeakEngine(pendingEngineSelection?.value))
pendingEngineSelection = null
},
dismissText = stringResource(R.string.book),
onDismiss = {
onIntent(ReadBookIntent.ApplySpeakEnginePerBook(pendingEngineValue))
pendingEngineValue = null
onIntent(ReadBookIntent.ApplySpeakEnginePerBook(pendingEngineSelection?.value))
pendingEngineSelection = null
},
)
@@ -232,7 +232,7 @@ fun SpeakEngineConfigSheet(
} else {
null
},
onClick = { pendingEngineValue = item.value },
onClick = { pendingEngineSelection = PendingSpeakEngineSelection(item.value) },
onLongClick = if (httpTtsId != null && !item.loginUrl.isNullOrBlank()) {
{ onIntent(ReadBookIntent.OpenHttpTtsLogin(httpTtsId)) }
} else null,
@@ -256,6 +256,8 @@ fun SpeakEngineConfigSheet(
}
}
private data class PendingSpeakEngineSelection(val value: String?)
@Composable
fun HttpTtsEditSheet(
show: Boolean,