Technische ID als Identität der Notizen; Pfad wird zur Eigenschaft
Bisher war der Dateipfad die Identität einer Notiz: Umbenennen brach Verweise, und der Pfad tauchte in der Oberfläche auf (Tooltips, Menüpunkte "Dateiname ändern"/"Ordnerpfad ändern"). Jede Notiz trägt jetzt eine technische ID im Frontmatter (id: <uuid>), die nie wechselt; der Systempfad ist nur noch eine Eigenschaft. - ensure_ids ergänzt fehlende IDs beim Seitenaufbau (wie ensure_node_texts); frontmatter() schreibt sie bei jedem Anlegen als erste Zeile. - Doc, WikiDocEntry, FolderNode und Suchtreffer führen die ID mit; resolve_id löst sie auf den aktuellen relpath auf. - Commands sprechen IDs: archive_read/write/set_title/delete nehmen `id`, archive_create_doc/create_folder die ID des Elternknotens plus Namen, panel_archive_cmd den Zielknoten als ID. - Frontend adressiert durchgehend über IDs: Auswahl, Klapp-Zustand, Verlauf des Zurück-Knopfs, Wikilink-Sprünge, Suchtreffer-Vormerkung und der Zielordner-Baum des Archiv-Dialogs. - Der Pfad ist aus der Oberfläche verschwunden: die Menüpunkte zum Umbenennen von Datei und Ordner samt Commands (archive_rename, archive_move, archive_move_folder) sind entfallen — es gibt nur noch den Titel, Name und Titel können nicht mehr auseinanderlaufen. Offen dadurch: Verschieben im Baum fehlt (ToDo: Drag & Drop). Archiv-Dialog nebenbei überarbeitet: modales Popup im Design der Archiv-Ansicht mit Abbrechen und zuverlässigem Escape, Zielordner über einen einklappbaren Baum statt Pfadeingabe, zusätzlicher Knopf "Auf Platte legen" (panel_save_as); Archivieren öffnet keinen Dateimanager mehr.
This commit is contained in:
+60
-29
@@ -177,7 +177,9 @@ function b64ToBytes(b64: string): Uint8Array {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
await win.listen<string>("pty-output", (e) => term.write(b64ToBytes(e.payload)));
|
||||
await win.listen<string>("pty-output", (e) =>
|
||||
term.write(b64ToBytes(e.payload)),
|
||||
);
|
||||
await win.listen("pty-exit", () =>
|
||||
term.write(`\r\n\x1b[90m${t("panel.processEnded")}\x1b[0m\r\n`),
|
||||
);
|
||||
@@ -281,41 +283,70 @@ document.getElementById("panel-hide")!.addEventListener("click", () => {
|
||||
// Archivieren: Button klappt das Formular (Ordner/Beschreibung/Schlagwörter)
|
||||
// auf; Abschicken wählt notfalls erst das Archiv-Home per Dialog.
|
||||
const archiveBtn = document.getElementById("panel-archive")!;
|
||||
const archiveForm = initArchiveForm(archiveBtn, async (meta) => {
|
||||
try {
|
||||
const configured = await invoke<string | null>("panel_archive_dir_cmd", {
|
||||
project,
|
||||
});
|
||||
let dir: string | undefined;
|
||||
if (!configured) {
|
||||
const { open } = await import("@tauri-apps/plugin-dialog");
|
||||
const chosen = await open({ directory: true, title: t("panel.chooseArchiveDir") });
|
||||
if (!chosen) return;
|
||||
dir = chosen as string;
|
||||
const archiveForm = initArchiveForm(
|
||||
archiveBtn,
|
||||
async (meta) => {
|
||||
try {
|
||||
const configured = await invoke<string | null>("panel_archive_dir_cmd", {
|
||||
project,
|
||||
});
|
||||
let dir: string | undefined;
|
||||
if (!configured) {
|
||||
const { open } = await import("@tauri-apps/plugin-dialog");
|
||||
const chosen = await open({
|
||||
directory: true,
|
||||
title: t("panel.chooseArchiveDir"),
|
||||
});
|
||||
if (!chosen) return;
|
||||
dir = chosen as string;
|
||||
}
|
||||
await view.flush(); // offene Bearbeitung erst speichern — archiviert, was zu sehen ist
|
||||
await invoke<string>("panel_archive_cmd", {
|
||||
project,
|
||||
dir,
|
||||
folder: meta.folder ?? null,
|
||||
description: meta.description ?? null,
|
||||
tags: meta.tags,
|
||||
});
|
||||
flash(archiveBtn, "copied", 1400);
|
||||
} catch (e) {
|
||||
flash(archiveBtn, "error", 1400);
|
||||
panelToast(`Archivieren fehlgeschlagen: ${e}`);
|
||||
invoke("term_log", { msg: `archive: ${e}` });
|
||||
}
|
||||
await view.flush(); // offene Bearbeitung erst speichern — archiviert, was zu sehen ist
|
||||
const path = await invoke<string>("panel_archive_cmd", {
|
||||
project,
|
||||
dir,
|
||||
folder: meta.folder ?? null,
|
||||
description: meta.description ?? null,
|
||||
tags: meta.tags,
|
||||
});
|
||||
flash(archiveBtn, "copied", 1400);
|
||||
invoke("reveal_path_cmd", { path });
|
||||
} catch (e) {
|
||||
flash(archiveBtn, "error", 1400);
|
||||
panelToast(`Archivieren fehlgeschlagen: ${e}`);
|
||||
invoke("term_log", { msg: `archive: ${e}` });
|
||||
}
|
||||
});
|
||||
},
|
||||
{
|
||||
// Ordner-Vorschläge aus dem Archiv; „Auf Platte legen" schreibt den
|
||||
// Entwurf an einen frei gewählten Pfad (ohne Archiv, ohne Frontmatter).
|
||||
folders: () => invoke<string[]>("archive_folders", { project }),
|
||||
onSave: async () => {
|
||||
try {
|
||||
const { save } = await import("@tauri-apps/plugin-dialog");
|
||||
const path = await save({
|
||||
title: t("archiveForm.saveTitle"),
|
||||
defaultPath: "entwurf.md",
|
||||
});
|
||||
if (!path) return;
|
||||
await view.flush();
|
||||
await invoke("panel_save_as", { project, path });
|
||||
flash(archiveBtn, "copied", 1400);
|
||||
} catch (e) {
|
||||
flash(archiveBtn, "error", 1400);
|
||||
panelToast(`Speichern fehlgeschlagen: ${e}`);
|
||||
}
|
||||
},
|
||||
},
|
||||
);
|
||||
archiveBtn.addEventListener("click", () => archiveForm.toggle());
|
||||
|
||||
// Splitter: Panelbreite ziehen.
|
||||
splitter.addEventListener("mousedown", (e) => {
|
||||
e.preventDefault();
|
||||
const move = (ev: MouseEvent) => {
|
||||
const w = Math.max(240, Math.min(window.innerWidth - 200, window.innerWidth - ev.clientX));
|
||||
const w = Math.max(
|
||||
240,
|
||||
Math.min(window.innerWidth - 200, window.innerWidth - ev.clientX),
|
||||
);
|
||||
panel.style.width = `${w}px`;
|
||||
fit.fit();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user