refactor: Router zusammenfuehren und offenen Workspace im Context fuehren

Die App hatte zwei Routable-Enums, zwischen denen ein Signal<bool> umschaltete.
Der Schalter wurde nie gesetzt - beim ersten Umlegen waere aufgefallen, dass
sich beide Router dieselbe History teilen und beide "/" belegen: Wer im
Selector auf "Open Workspace" klickt, steht auf /ws_open, und der
Editor-Router kennt nur / und /editor.

Jetzt ein Enum, der Editor-Teil unter #[nest("/workspace")]. An die Stelle des
bool tritt Signal<Option<Workspace>> in einem Context-Provider - Props
scheiden aus, weil sich durch ein Outlet keine durchreichen lassen. Fehlt der
Workspace, schickt ein Guard im EditorShell-Layout zurueck zum Selector; der
Fall tritt real bei Hot-Reload auf, wo der Context faellt und die Route bleibt.

Der Selector verliert seine Reiter und wird eine einzige Route. Das folgt aus
dem UI-Prototyp in Issue #8: Oeffnen ist der Alltagsfall, Hinzufuegen passiert
pro Workspace einmal - zwei gleichrangige Reiter verlangten bei jedem Start
eine Entscheidung, die fast immer dieselbe ist. Damit entfallen der leere
Stub create_new_workspace.rs, die Tab-Konstante fuer den Selector und die
zugehoerigen CSS-Klassen.

Weil EnumIter nicht mehr gebraucht wird, faellt strum_macros als direkte
Abhaengigkeit weg; strum re-exportiert die Derives bereits.

Entscheidungen dazu in den Issues #5, #6 und #8.
This commit is contained in:
2026-08-28 08:57:19 +02:00
parent d2f5316a52
commit 91fd351d59
12 changed files with 143 additions and 131 deletions

View File

@@ -1,11 +0,0 @@
use dioxus::prelude::*;
/// Create new Workspace Layout
// TODO: Platzhalter — Formular zum Anlegen eines Workspace (Name, Pfad) und
// Verdrahtung als Ziel von WorkspaceRoute::NewWorkspace fehlen noch.
#[component]
fn NewWorkspaceLayout() -> Element {
rsx! {
div {}
}
}

View File

@@ -1,2 +1 @@
pub mod selector;
pub mod create_new_workspace;

View File

@@ -1,61 +1,26 @@
use dioxus::prelude::*;
use strum::{EnumMessage, IntoEnumIterator};
use strum_macros::EnumIter;
use crate::components::custom_link::custom_link_component::CustomLink;
#[derive(Debug, Clone, Routable, PartialEq, EnumIter, EnumMessage)]
#[rustfmt::skip]
pub enum WorkspaceRoute {
#[layout(Workspace)]
#[route("/")]
#[strum(message = "Create new Workspace")]
NewWorkspace {},
#[route("/ws_open")]
#[strum(message = "Open Workspace")]
OpenWorkspace {},
}
/// Page to create new Workspace
/// Der Bildschirm vor dem Editor: einen bekannten Workspace öffnen oder einen
/// hinzufügen. Eine einzige Route, keine Reiter — die Workspace-Liste führt,
/// das Hinzufügen ist Nebenaktion.
#[component]
fn NewWorkspace() -> Element {
pub fn Selector() -> Element {
rsx! {
div {
"New Workspace",
}
}
}
/// Page to open available Workspaces
#[component]
fn OpenWorkspace() -> Element {
rsx! {
div {
"Open Workspace",
}
}
}
/// Workspace Layout
#[component]
fn Workspace() -> Element {
rsx! {
div {
class: "workspace-selector-layout",
div {
class: "workspace-selector-links",
for route in WorkspaceRoute::iter() {
CustomLink {
key: "{route}",
label: route.get_message().unwrap_or_default(),
href: route.clone(),
css: "workspace-selector",
div { class: "workspace-selector-layout",
div { class: "workspace-selector-view",
// TODO: Workspace-Liste aus workspaces.ron laden und darstellen
// (Ordnername, Pfad darunter, Statusabzeichen). Bis dahin nur
// der leere Zustand.
div { class: "empty-state",
span { class: "empty-state-title", "Noch kein Workspace" }
span { "Der erste Workspace ist ein Ordner deiner Wahl." }
// TODO: Nativen Ordner-Dialog anbinden, Marker anlegen und
// den Workspace in den Context schreiben.
button { class: "btn btn-primary", disabled: true,
"Workspace hinzufügen…"
}
}
}
div {
class: "workspace-selector-view",
Outlet::<WorkspaceRoute> { }
}
}
}
}