feat(desktop): signature updater Tauri + wizard persistant + protocole E2E (#77)
CI / lint (push) Successful in 1m11s
CI / security (push) Successful in 43s
CI / test (push) Successful in 2m22s
CI / build (push) Successful in 1m41s
CI / e2e (push) Successful in 10m50s
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s
CI / lint (push) Successful in 1m11s
CI / security (push) Successful in 43s
CI / test (push) Successful in 2m22s
CI / build (push) Successful in 1m41s
CI / e2e (push) Successful in 10m50s
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s
- Signature des mises a jour Tauri : paire de cles minisign generee, cle publique dans tauri.conf.json, createUpdaterArtifacts actif, secrets CI exposes (repli build non signe si secret absent). - Wizard 1er lancement : etat persistant wizard_done cote Rust (get_wizard_state/complete_wizard) pour ne plus reafficher la banniere, retro-compatible. - Protocole des 6 tests E2E manuels : docs/DESKTOP_E2E_CHECKLIST.md. - CI : desktop.test.mjs ajoute au job lint. - Docs : ROADMAP, fiche desktop-tauri, CHANGELOG, README desktop, guide releases. - fix(build): retirer les libs WeasyPrint inutiles du stage builder Docker.
This commit is contained in:
@@ -78,6 +78,11 @@ struct AppConfig {
|
||||
window_y: Option<f64>,
|
||||
window_width: Option<f64>,
|
||||
window_height: Option<f64>,
|
||||
/// True once the user has picked a vault or dismissed the first-run wizard.
|
||||
/// `#[serde(default)]` keeps existing config files (written before this
|
||||
/// field existed) parseable instead of falling back to a full reset.
|
||||
#[serde(default)]
|
||||
wizard_done: bool,
|
||||
}
|
||||
|
||||
impl Default for AppConfig {
|
||||
@@ -90,6 +95,7 @@ impl Default for AppConfig {
|
||||
window_y: None,
|
||||
window_width: Some(1200.0),
|
||||
window_height: Some(800.0),
|
||||
wizard_done: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,6 +292,7 @@ fn get_config() -> AppConfig {
|
||||
fn save_vault_path(path: String) -> Result<(), String> {
|
||||
let mut config = load_config();
|
||||
config.vault_path = Some(path);
|
||||
config.wizard_done = true;
|
||||
save_config(&config);
|
||||
info!("Vault path saved: {}", config.vault_path.as_deref().unwrap_or("none"));
|
||||
Ok(())
|
||||
@@ -305,6 +312,7 @@ async fn pick_vault_folder(app: tauri::AppHandle) -> Result<String, String> {
|
||||
let p_str = p.to_string();
|
||||
let mut config = load_config();
|
||||
config.vault_path = Some(p_str.clone());
|
||||
config.wizard_done = true;
|
||||
save_config(&config);
|
||||
Ok(p_str)
|
||||
}
|
||||
@@ -312,6 +320,20 @@ async fn pick_vault_folder(app: tauri::AppHandle) -> Result<String, String> {
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_wizard_state() -> bool {
|
||||
load_config().wizard_done
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn complete_wizard() -> Result<(), String> {
|
||||
let mut config = load_config();
|
||||
config.wizard_done = true;
|
||||
save_config(&config);
|
||||
info!("First-run wizard marked as completed");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_system_theme(app: tauri::AppHandle) -> String {
|
||||
use tauri::Theme;
|
||||
@@ -564,6 +586,8 @@ fn main() {
|
||||
get_config,
|
||||
save_vault_path,
|
||||
get_vault_path,
|
||||
get_wizard_state,
|
||||
complete_wizard,
|
||||
pick_vault_folder,
|
||||
get_system_theme,
|
||||
restart_backend,
|
||||
@@ -904,6 +928,7 @@ mod tests {
|
||||
assert!(c.dirs.is_empty());
|
||||
assert_eq!(c.window_width, Some(1200.0));
|
||||
assert_eq!(c.window_height, Some(800.0));
|
||||
assert!(!c.wizard_done);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -919,6 +944,7 @@ mod tests {
|
||||
window_y: Some(200.0),
|
||||
window_width: Some(1400.0),
|
||||
window_height: Some(900.0),
|
||||
wizard_done: true,
|
||||
};
|
||||
let loaded = roundtrip_config(&c);
|
||||
assert_eq!(loaded.vault_path, Some("/test/vault".into()));
|
||||
@@ -927,6 +953,33 @@ mod tests {
|
||||
assert_eq!(loaded.vaults[1].path, "/v/work");
|
||||
assert_eq!(loaded.dirs.len(), 1);
|
||||
assert_eq!(loaded.window_x, Some(100.0));
|
||||
assert!(loaded.wizard_done);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_without_wizard_done_parses() {
|
||||
// Backward compatibility: config files written before `wizard_done`
|
||||
// existed must still load (instead of resetting to defaults).
|
||||
let json = r#"{
|
||||
"vault_path": "/old/vault",
|
||||
"vaults": [{"name": "Old", "path": "/old"}],
|
||||
"dirs": [],
|
||||
"window_x": null,
|
||||
"window_y": null,
|
||||
"window_width": 1000.0,
|
||||
"window_height": 700.0
|
||||
}"#;
|
||||
let c: AppConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(c.vaults.len(), 1);
|
||||
assert_eq!(c.vaults[0].name, "Old");
|
||||
assert!(!c.wizard_done);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wizard_done_roundtrip() {
|
||||
let mut c = AppConfig::default();
|
||||
c.wizard_done = true;
|
||||
assert!(roundtrip_config(&c).wizard_done);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user