App-Zustand des offenen Workspace und die Router-Struktur #5
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #1
Question
Wie wird der offene Workspace im App-Zustand geführt — und was ersetzt
workspace_selected?Der heutige Stand in
src/main.rs: einSignal<bool>schaltet zwischenRouter::<WorkspaceRoute>undRouter::<EditorRoute>. Das Signal wird nirgends gesetzt; der Übergang existiert also gar nicht. Einboolkann außerdem nicht sagen, welcher Workspace offen ist.Zu entscheiden:
Signal<Option<Workspace>>, ein eigener Enum über die App-Phase, etwas anderes?files-bar) daran — Context-Provider, Props-Durchreichung?/kennen. Ist das tragfähig, oder braucht es eine Route-Ebene darüber?Zielgröße: die Typen und ihr Ort im Baum, so konkret, dass man sie hinschreiben kann.
Antwort
Ein Router statt zwei.
WorkspaceRouteundEditorRouteverschmelzen zu einemRoutable-Enum, in dem der Editor-Teil unter#[nest("/workspace")]liegt. Der offene Workspace lebt alsSignal<Option<Workspace>>in einem Context-Provider.Warum nicht bei zwei Routern bleiben
Der heutige Aufbau ist nie gelaufen —
workspace_selectedwird nirgends auftruegesetzt. Beim ersten Umlegen des Schalters wäre er aufgefallen: beide Enums definieren#[route("/")]und teilen sich dieselbe History. Wer im Selector auf „Open Workspace" klickt, steht auf/ws_open; schaltet die App in diesem Moment auf denEditorRoute-Router um, bekommt der eine URL zu sehen, die er nicht kennt — er hat nur/und/editor. Das ist der wahrscheinlichste Weg durch die App, nicht ein Randfall.Reparieren ließe sich das mit einer erzwungenen Navigation bei jedem Wechsel. Das behandelt aber das Symptom: zwei Adressräume, die sich eine History teilen, bleiben zwei Adressräume.
Die Struktur
Apprendert nur nochRouter::<Route> {}— dasif workspace_selected()entfällt ersatzlos, ebenso dasSignal<bool>.Der Zustand
Ein benannter Typ statt
Option<PathBuf>:CONTEXT.mdführt „Workspace" als Domänenbegriff, der Marker bringt absehbar Einstellungen mit, die hier andocken, und ein nacktesPathBufim Context zwingt jeden Leser zu der Frage, welcher Pfad gemeint ist — Workspace-Ordner, Notiz oder Konfigurationsverzeichnis.Context, nicht Props: Der Workspace wird im Selector gesetzt und in der
files-bargelesen. Beide hängen unter einemOutlet, und durch einOutletlassen sich keine Props durchreichen. Das ist keine Wahl, sondern eine Randbedingung.Der Workspace-Pfad gehört nicht in die Route.
/workspace/C%3A%5CUsers%5C...wäre die Alternative; sie macht aus einem Dateipfad einen URL-Bestandteil samt Escaping-Fragen und gewinnt in einer Desktop-App ohne Adressleiste nichts.Der Guard
Das
EditorShell-Layout prüft den Context und schickt beiNonezurück zum Selector — eine Prüfung an genau der Stelle, an der derOutletsteht. Der Fall ist real: Hot-Reload während der Entwicklung setzt den Context zurück, die Route bleibt bestehen; später kommt „Workspace schließen" dazu.Ein statisches
#[redirect]scheidet aus — es sieht nur die URL, nicht den Zustand.Beim Bauen zu prüfen: ob die Navigation direkt im Render-Pfad erfolgen darf (
navigator().replace(...)plus leeresrsx!) oder in einenuse_effectgehört. Navigation ist ein Seiteneffekt, und Dioxus 0.7 ist an dieser Stelle nicht eindeutig dokumentiert. Die Entscheidung „Guard im Layout" ist davon unberührt, nur die Zeile darin.„Workspace wechseln"
Braucht keinen strukturellen Platzhalter. Mit dem Selector unter
/und dem Editor unter/workspace/...ist Wechseln eine Navigation nach/plus Leeren des Context — zwei Zeilen an dem Tag, an dem der Knopf dafür entsteht.Folge, die beim Ausformulieren aufgefallen ist
Die Tab-Leisten werden heute aus
Route::iter()erzeugt (Workspace()im Selector,Navbar()im Editor). Mit einem Enum liefertiter()alle vier Varianten — beide Leisten würden die Routen des jeweils anderen Bereichs mitlisten.Vorschlag, minimal und ohne Filterlogik:
Die Labels bleiben über
#[strum(message = ...)]an den Varianten,EnumIterwird nicht mehr gebraucht. Nachteil, offen ausgesprochen: eine neue Route zwingt einen nicht, das passende Array zu ergänzen — der Compiler prüft das nicht. Die Alternative wäreRoute::iter().filter(|r| matches!(...)), was denselben Pflegepunkt an eine unauffälligere Stelle schiebt.Klein genug, um es beim Bauen zu entscheiden — hier festgehalten, damit es nicht überrascht.
Nachtrag aus #8 (Selector-UI). Der Prototyp hat eine Annahme dieses Tickets widerlegt: Die gewonnene Variante kommt ohne Reiter aus, damit entfällt der Grund für zwei Selector-Routen.
Statt
NewWorkspace {}(/) undOpenWorkspace {}(/open) gibt es eine Route:Ersatzlos weg: die Konstante
SELECTOR_TABS, die CSS-Klasse.workspace-selector-links, die Tab-Komponente und das#[layout(Selector)]— der Selector ist der Bildschirm, es gibt keinen Outlet-Inhalt, der umschaltet.Der oben ausgewiesene Pflegepunkt (der Compiler erzwingt nicht, eine neue Route ins passende Tab-Array einzutragen) gilt damit nur noch für
EDITOR_TABS.Alles Übrige aus diesem Ticket bleibt gültig: ein Router,
#[nest("/workspace")]für den Editor-Teil,Signal<Option<Workspace>>im Context, Guard imEditorShell-Layout.