Bugfix-Runde Panel/Archiv: Datenverlust, Suche, Löschen, Markdown
- ProjectConfig reicht unbekannte Keys durch (serde flatten). Bisher verlor jeder read-modify-write die Felder neuerer Versionen; so ging archiveHome bei der Pool-Zuweisung durch einen älteren Build verloren. - Archiv-Suche: Nutzereingabe wird in einen FTS5-Ausdruck übersetzt, der nicht scheitern kann. ai-control, C++ oder eine halbe Phrase warfen bisher einen Syntaxfehler — bei der Live-Suche in jedem Tippzwischenstand. - commands_delete: Befehlstext als Identität, Indizes werden geprüft. Bisher Panik oder Löschen der falschen Kachel, wenn die Panel-Indizes der Datei hinterherhingen. - Archivieren überschreibt keine Datei mehr: Der Stempel hat Minutenauflösung, bei Kollision wird -2, -3, ... angehängt. - archive_panel prüft erst auf leeres Panel, dann wird das Archiv-Home gesetzt; bisher blieb ein umkonfiguriertes Home trotz Meldung "nicht archiviert". - Kaputte .claude.json eines Pools wird nicht mehr durch eine frische ersetzt; nur eine fehlende Datei rechtfertigt das. - Archiv-Formular leert beim Schließen — sonst galten Ordner und Schlagwörter des vorigen Dokuments unbemerkt fürs nächste. - Markdown fürs Panel entschärft (src/markdown.ts): rohes HTML wird als Text ausgegeben, Link- und Bildziele auf harmlose Schemata beschränkt. Das Panel teilt sich den Webview mit dem Terminal, dessen term_write in die PTY schreibt; ohne CSP war das ein Weg von Fremdinhalt zu Befehlsausführung. Regressionstests je Fix: 73 Rust-Tests, 35 Frontend-Tests.
This commit is contained in:
@@ -249,8 +249,19 @@ pub fn commands_read(project: String) -> String {
|
||||
/// Panel). `line` ist der Index der nicht-leeren JSONL-Zeile, `entry` der
|
||||
/// Index im commands-Array des Records; ein leer gewordener Record fällt mit
|
||||
/// weg. Der Watcher meldet den neuen Stand als `commands-update`.
|
||||
///
|
||||
/// `cmd` ist der angezeigte Befehlstext und dient als Identität: Die Indizes
|
||||
/// des Panels sind der Datei um bis zu ein Watcher-Intervall hinterher, und
|
||||
/// ein leer gewordener Record verschiebt alle folgenden. Ohne Abgleich löscht
|
||||
/// ein Doppelklick — oder das zweite Fenster auf derselben Liste — die falsche
|
||||
/// Kachel oder greift ins Leere.
|
||||
#[tauri::command]
|
||||
pub fn commands_delete(project: String, line: usize, entry: usize) -> Result<(), String> {
|
||||
pub fn commands_delete(
|
||||
project: String,
|
||||
line: usize,
|
||||
entry: usize,
|
||||
cmd: String,
|
||||
) -> Result<(), String> {
|
||||
let path = commands_file(&project);
|
||||
let text = std::fs::read_to_string(&path).map_err(|e| e.to_string())?;
|
||||
let mut records: Vec<serde_json::Value> = text
|
||||
@@ -258,9 +269,14 @@ pub fn commands_delete(project: String, line: usize, entry: usize) -> Result<(),
|
||||
.filter(|l| !l.trim().is_empty())
|
||||
.map(|l| serde_json::from_str(l).map_err(|e| e.to_string()))
|
||||
.collect::<Result<_, _>>()?;
|
||||
let cmds = records[line]["commands"]
|
||||
let cmds = records
|
||||
.get_mut(line)
|
||||
.ok_or("Befehl bereits entfernt")?["commands"]
|
||||
.as_array_mut()
|
||||
.ok_or("Record ohne commands")?;
|
||||
if cmds.get(entry).map(|c| c["cmd"].as_str() != Some(cmd.as_str())).unwrap_or(true) {
|
||||
return Err("Befehl bereits entfernt".into());
|
||||
}
|
||||
cmds.remove(entry);
|
||||
if cmds.is_empty() {
|
||||
records.remove(line);
|
||||
|
||||
Reference in New Issue
Block a user