fix style pack prefs sync consistency
This commit is contained in:
1 parent
ae2c7e4e74
commit
c77e235d96
2 files changed
+97
-9
No files matched your search
@@ -28,6 +28,7 @@ use crate::types::{
|
||||
builtin_style_pack_id, default_active_style_pack_id, ChineseScriptPreference, ComboBinding,
|
||||
CorrectionRule, CredentialsStatus, DictationSession, DictionaryEntry, HotkeyCapability,
|
||||
HotkeyStatus, OutputLanguagePreference, PolishMode, ShortcutBinding, StylePack,
|
||||
StylePackKind,
|
||||
StylePackRuntimeDiagnostics, StyleSystemPrompts, UpdateChannel, UserPreferences,
|
||||
VocabPresetStore, WindowsImeStatus,
|
||||
};
|
||||
@@ -157,8 +158,10 @@ pub fn set_settings(
|
||||
coord: CoordinatorState<'_>,
|
||||
app: AppHandle,
|
||||
tray_microphones: State<'_, TrayMicrophoneMenuState>,
|
||||
prefs: UserPreferences,
|
||||
mut prefs: UserPreferences,
|
||||
) -> Result<(), String> {
|
||||
let packs = coord.style_packs().list().map_err(|e| e.to_string())?;
|
||||
sync_style_pack_preferences(&mut prefs, &packs);
|
||||
// 广播给所有 webview。issue #205:QaPanel 跑在独立 webview,
|
||||
// 没有 HotkeySettingsContext,必须靠事件感知录音键变化,否则面板可见时
|
||||
// 用户改键会让浮窗里的 "{recordHotkey}" 文案一直停留在旧值。
|
||||
@@ -1257,6 +1260,7 @@ pub fn list_style_packs(coord: CoordinatorState<'_>) -> Result<Vec<StylePack>, S
|
||||
#[tauri::command]
|
||||
pub fn save_style_pack(
|
||||
coord: CoordinatorState<'_>,
|
||||
app: AppHandle,
|
||||
style_pack: StylePack,
|
||||
) -> Result<StylePack, String> {
|
||||
log::info!(
|
||||
@@ -1265,10 +1269,15 @@ pub fn save_style_pack(
|
||||
style_pack.kind,
|
||||
style_pack.base_mode
|
||||
);
|
||||
coord
|
||||
let saved = coord
|
||||
.style_packs()
|
||||
.upsert(style_pack)
|
||||
.map_err(|e| e.to_string())
|
||||
.map_err(|e| e.to_string())?;
|
||||
if saved.kind == StylePackKind::Builtin {
|
||||
let prefs = coord.prefs().get();
|
||||
let _ = sync_style_pack_prefs_and_persist(&*coord, &app, prefs)?;
|
||||
}
|
||||
Ok(saved)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -1324,13 +1333,17 @@ pub fn set_style_pack_enabled(
|
||||
#[tauri::command]
|
||||
pub fn reset_builtin_style_pack(
|
||||
coord: CoordinatorState<'_>,
|
||||
app: AppHandle,
|
||||
id: String,
|
||||
) -> Result<StylePack, String> {
|
||||
log::info!("[style-pack] command reset_builtin requested id={id}");
|
||||
coord
|
||||
let saved = coord
|
||||
.style_packs()
|
||||
.reset_builtin(&id)
|
||||
.map_err(|e| e.to_string())
|
||||
.map_err(|e| e.to_string())?;
|
||||
let prefs = coord.prefs().get();
|
||||
let _ = sync_style_pack_prefs_and_persist(&*coord, &app, prefs)?;
|
||||
Ok(saved)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
||||
@@ -24,8 +24,9 @@ use uuid::Uuid;
|
||||
|
||||
use crate::types::{
|
||||
builtin_style_pack_for_mode, builtin_style_pack_id, builtin_style_packs,
|
||||
default_active_style_pack_id, CorrectionRule, DictationSession, DictionaryEntry, PolishMode,
|
||||
StylePack, StylePackExample, StylePackKind, UserPreferences, VocabPresetStore,
|
||||
default_active_style_pack_id, CorrectionRule, CustomStylePrompts, DictationSession,
|
||||
DictionaryEntry, PolishMode, StylePack, StylePackExample, StylePackKind, UserPreferences,
|
||||
VocabPresetStore,
|
||||
BUILTIN_STYLE_PACK_LIGHT_ID,
|
||||
};
|
||||
|
||||
@@ -1407,6 +1408,10 @@ pub fn sync_style_pack_preferences(prefs: &mut UserPreferences, packs: &[StylePa
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if sync_builtin_style_prompt_preferences(prefs, packs) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if changed {
|
||||
log::info!(
|
||||
"[style-pack] sync_prefs active:{}->{} default_mode:{:?}->{:?} enabled_modes:{:?}->{:?}",
|
||||
@@ -1422,6 +1427,44 @@ pub fn sync_style_pack_preferences(prefs: &mut UserPreferences, packs: &[StylePa
|
||||
changed
|
||||
}
|
||||
|
||||
fn sync_builtin_style_prompt_preferences(prefs: &mut UserPreferences, packs: &[StylePack]) -> bool {
|
||||
let mut changed = false;
|
||||
let mut saw_builtin = false;
|
||||
for mode in [
|
||||
PolishMode::Raw,
|
||||
PolishMode::Light,
|
||||
PolishMode::Structured,
|
||||
PolishMode::Formal,
|
||||
] {
|
||||
let Some(pack) = packs
|
||||
.iter()
|
||||
.find(|pack| pack.kind == StylePackKind::Builtin && pack.base_mode == mode)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
saw_builtin = true;
|
||||
let next_prompt = pack.prompt.clone();
|
||||
let current_prompt = prefs.style_system_prompts.for_mode(mode);
|
||||
if current_prompt == next_prompt {
|
||||
continue;
|
||||
}
|
||||
match mode {
|
||||
PolishMode::Raw => prefs.style_system_prompts.raw = next_prompt,
|
||||
PolishMode::Light => prefs.style_system_prompts.light = next_prompt,
|
||||
PolishMode::Structured => prefs.style_system_prompts.structured = next_prompt,
|
||||
PolishMode::Formal => prefs.style_system_prompts.formal = next_prompt,
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if saw_builtin && prefs.custom_style_prompts != CustomStylePrompts::default() {
|
||||
prefs.custom_style_prompts = CustomStylePrompts::default();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
changed
|
||||
}
|
||||
|
||||
pub fn enabled_modes_from_style_packs(packs: &[StylePack]) -> Vec<PolishMode> {
|
||||
let mut modes = Vec::new();
|
||||
for mode in [
|
||||
@@ -2013,10 +2056,10 @@ impl CredentialsVault {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
chunk_json_payload, list_vocab_presets, save_vocab_presets,
|
||||
chunk_json_payload, list_vocab_presets, save_vocab_presets, sync_style_pack_preferences,
|
||||
validate_correction_rule_syntax, KEYRING_CHUNK_MAX_UTF16_UNITS,
|
||||
};
|
||||
use crate::types::{VocabPreset, VocabPresetStore};
|
||||
use crate::types::{builtin_style_packs, CustomStylePrompts, VocabPreset, VocabPresetStore};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -2075,4 +2118,36 @@ mod tests {
|
||||
assert!(validate_correction_rule_syntax("{num}到{num}粒", "{num}例").is_err());
|
||||
assert!(validate_correction_rule_syntax("几粒", "{num}例").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_style_pack_preferences_uses_builtin_store_prompts_as_source_of_truth() {
|
||||
let mut prefs = crate::types::UserPreferences {
|
||||
style_system_prompts: crate::types::StyleSystemPrompts {
|
||||
raw: "stale raw".into(),
|
||||
light: "stale light".into(),
|
||||
structured: "stale structured".into(),
|
||||
formal: "stale formal".into(),
|
||||
},
|
||||
custom_style_prompts: CustomStylePrompts {
|
||||
raw: String::new(),
|
||||
light: "legacy extra instruction".into(),
|
||||
structured: String::new(),
|
||||
formal: String::new(),
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let mut packs = builtin_style_packs();
|
||||
let light = packs
|
||||
.iter_mut()
|
||||
.find(|pack| pack.id == "builtin.light")
|
||||
.expect("builtin light pack");
|
||||
light.prompt = "fresh light prompt from store".into();
|
||||
|
||||
assert!(sync_style_pack_preferences(&mut prefs, &packs));
|
||||
assert_eq!(prefs.style_system_prompts.raw, packs[0].prompt);
|
||||
assert_eq!(prefs.style_system_prompts.light, "fresh light prompt from store");
|
||||
assert_eq!(prefs.style_system_prompts.structured, packs[2].prompt);
|
||||
assert_eq!(prefs.style_system_prompts.formal, packs[3].prompt);
|
||||
assert_eq!(prefs.custom_style_prompts, CustomStylePrompts::default());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user