diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/HighlightRuleEditSheet.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/HighlightRuleEditSheet.kt index 0c8737207..b28b6f6c4 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/HighlightRuleEditSheet.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/HighlightRuleEditSheet.kt @@ -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(null) } + var patternError by remember(show, rule) { mutableStateOf(null) } // SAF image picker val imagePicker = rememberLauncherForActivityResult( diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadAloudConfigSheet.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadAloudConfigSheet.kt index 6cea9124c..390dfaed1 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadAloudConfigSheet.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadAloudConfigSheet.kt @@ -154,22 +154,22 @@ fun SpeakEngineConfigSheet( ) { val items = state.ttsEngineItems val selectedValue = state.selectedTtsEngine - var pendingEngineValue by remember { mutableStateOf(null) } + var pendingEngineSelection by remember { mutableStateOf(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,