Start-Sequenz ergänzt: Splash-Screen, dann Startbildschirm mit Neues Projekt/Projekt öffnen/Zuletzt geöffnet.

Zuletzt-geöffnet-Liste (state/recentProjects.ts) trägt sich beim Öffnen und
beim Speichern automatisch ein, inkl. Öffnen über einen bekannten Pfad ohne
Dialog (verwaiste Einträge fliegen raus, wenn die Datei fehlt). Der Splash
wartet bewusst nicht auf den Update-Check — der läuft unabhängig im
Hintergrund weiter, damit ein langsames Netz den Start nie verzögert.
This commit is contained in:
2026-07-31 17:40:35 +02:00
parent fc31ef9f44
commit 06c0143d32
11 changed files with 407 additions and 8 deletions
+28 -2
View File
@@ -55,6 +55,26 @@ export async function openProjectFileNative(): Promise<OpenedProjectFile | null>
return { path: selected, content };
}
/**
* Öffnet eine Projektdatei über einen BEKANNTEN Pfad (kein Dialog) — für den
* Startbildschirm/„Zuletzt geöffnet" (state/recentProjects.ts): der Pfad kommt
* dort schon aus einem früheren Öffnen/Speichern. Nur unter Tauri sinnvoll.
*
* @returns `null` ohne Tauri oder wenn die Datei nicht mehr lesbar ist (z. B.
* gelöscht/verschoben) — der Aufrufer sollte den Eintrag dann aus der
* Zuletzt-geöffnet-Liste entfernen.
*/
export async function openProjectFileAtPath(path: string): Promise<OpenedProjectFile | null> {
if (!isTauriRuntime()) return null;
try {
const { readTextFile } = await import("@tauri-apps/plugin-fs");
const content = await readTextFile(path);
return { path, content };
} catch {
return null;
}
}
/**
* Speichert das Projekt-JSON in eine `.obp`-Datei. Unter Tauri nativer
* Speichern-Dialog mit Projekt-Filter, im Browser Blob-Download — beides via
@@ -62,10 +82,16 @@ export async function openProjectFileNative(): Promise<OpenedProjectFile | null>
*
* @param json Fertig serialisiertes Projekt (JSON.stringify des ProjectSlice).
* @param projectName `project.name` für den Standard-Dateinamen (Fallback "projekt").
* @param onSavedPath Optionaler Callback mit dem gewählten Pfad (Zuletzt-
* geöffnet-Liste, s. state/recentProjects.ts).
*/
export async function saveProjectFile(json: string, projectName: string): Promise<boolean> {
export async function saveProjectFile(
json: string,
projectName: string,
onSavedPath?: (path: string) => void,
): Promise<boolean> {
const filename = `${projectName || "projekt"}.${PROJECT_EXT}`;
return saveTextFile(json, filename, "application/json", PROJECT_DIALOG_FILTERS);
return saveTextFile(json, filename, "application/json", PROJECT_DIALOG_FILTERS, onSavedPath);
}
// ── Lock gegen Doppelöffnung (nur Tauri) ────────────────────────────────────
+5
View File
@@ -26,6 +26,9 @@ export interface FileDialogFilter {
* @param filters Optionale Datei-Endungsfilter fuer den nativen Dialog (z. B.
* Projekt-Endung). Additiv/optional, damit bestehende Aufrufer ohne
* Filter unveraendert funktionieren (Default-Verhalten: irgendeine Endung).
* @param onSavedPath Optionaler Callback mit dem gewaehlten Pfad, NUR bei
* erfolgreichem Tauri-Speichern (z. B. fuer die Zuletzt-geoeffnet-Liste,
* s. state/recentProjects.ts) — additiv, aendert den Rueckgabewert nicht.
* @returns `true` wenn geschrieben/geladen wurde, `false` bei Abbruch (Dialog
* ohne Pfad). Bei einem Tauri-Fehler wird auf den Browser-Fallback
* zurueckgefallen.
@@ -35,6 +38,7 @@ export async function saveTextFile(
defaultName: string,
mime = "application/octet-stream",
filters?: FileDialogFilter[],
onSavedPath?: (path: string) => void,
): Promise<boolean> {
if (isTauri()) {
try {
@@ -43,6 +47,7 @@ export async function saveTextFile(
if (!path) return false; // Nutzer hat abgebrochen
const { writeTextFile } = await import("@tauri-apps/plugin-fs");
await writeTextFile(path, content);
onSavedPath?.(path);
return true;
} catch (err) {
if (!warnedFallback) {