feat: Ordner-Dialog und Anlegen-Flow

Setzt die Entscheidungen aus #2, #4 und #6 um: Der Knopf "Workspace
hinzufuegen..." oeffnet den nativen Ordner-Dialog, legt den Marker an und
uebernimmt den Workspace in Context, Liste und Editor.

Der Marker ist .dionotes/workspace.ron mit genau (schema_version: 1). Er wird
additiv angelegt, vorhandene Dateien bleiben unberuehrt - ein Test haelt das
fest. Ein beschaedigter Marker fuehrt dazu, dass der Workspace nicht
geoeffnet und der Marker nicht neu geschrieben wird; auch das ist getestet,
denn sobald dort ein Passwort-Hash liegt, waere stillschweigendes Neuanlegen
ein Weg, den Schutz auszuhebeln.

OpenError unterscheidet die drei Zustaende aus #6 - nicht erreichbar, kein
Workspace mehr, beschaedigt - plus den Fall eines zu neuen Schemas. Die
Display-Impl liefert genau die Formulierungen, mit denen spaeter die
Listeneintraege markiert werden.

Der Flow folgt der Regel aus #6: Ein abgebrochener Dialog ist kein Fehler und
erzeugt keine Meldung. Ein Ordner, der bereits Workspace ist, wird geoeffnet
statt abgelehnt - derselbe Knopf nimmt neue und wiedergefundene Workspaces
auf, was seine Beschriftung erst rechtfertigt. Ein nicht leerer Ordner loest
eine Rueckfrage aus, die ausdruecklich sagt, dass nichts Vorhandenes
veraendert wird; das ist beim Import der Normalfall, keine Ausnahme.

rfd wird mit denselben Features eingebunden, die dioxus-desktop ohnehin zieht
(xdg-portal statt default). Mit den Default-Features waeren neun
Wayland-Pakete dazugekommen, die das Portal nicht braucht - so kostet die
explizite Abhaengigkeit keinen einzigen zusaetzlichen Eintrag.
This commit is contained in:
2026-08-28 09:56:33 +02:00
parent 37a7bab30f
commit 276bc67dbe
5 changed files with 353 additions and 8 deletions

View File

@@ -167,6 +167,56 @@
font-weight: 600;
}
/* --- Dialog --------------------------------------------------------------------
Für Unterbrechungen einer laufenden Aktion. Zustände gehören dagegen inline
an ihren Ort, nicht in ein zweites Fenster.
-------------------------------------------------------------------------- */
.dialog-scrim {
position: fixed;
inset: 0;
display: grid;
place-items: center;
padding: var(--dn-space-4);
background: rgb(0 0 0 / 0.55);
z-index: 50;
}
.dialog {
width: min(28rem, 100%);
display: flex;
flex-direction: column;
gap: var(--dn-space-4);
padding: var(--dn-space-5);
border: 1px solid var(--dn-border-strong);
border-radius: var(--dn-radius-lg);
background: var(--dn-bg-sunken);
box-shadow: var(--dn-shadow);
}
.dialog h2 {
font-size: var(--dn-text-md);
font-weight: 600;
}
.dialog p {
color: var(--dn-fg-muted);
line-height: var(--dn-leading-normal);
}
.dialog code {
font-family: var(--dn-font-code);
font-size: var(--dn-text-sm);
color: var(--dn-fg);
overflow-wrap: anywhere;
}
.dialog-actions {
display: flex;
justify-content: flex-end;
gap: var(--dn-space-2);
}
/* --- Utilities ---------------------------------------------------------------- */
.visually-hidden {