The workspace
A home screen where you choose, and a workspace where you work. The two-scope shape, and the one that is worth understanding before you change anything.
AppState is provided by the root and lives for the whole process. WorkspaceState is provided by the workspace view and lives only while a project is open — its entries, its selection, its active tab.
The root drops the workspace entity when the route goes home. That is what stops a closed project's state leaking into the next one, and what stops an in-flight load landing in a view that has moved on. Settings stay at the root, because ⌘, has to work on the home screen too.
What you are carrying
modelThe project, and what a project contains.
storeProjects on disk, one JSON document.
hostOwns the active-project cursor, not the UI.
appHome ⇄ workspace routing, two state scopes.
Start it
scripts/new.sh Acme ~/Dev/acme --template workspace
What it looks like
match self.state.route.get(cx) {
Route::Home => {
// Dropping the entity here is what stops a closed project's signals
// and in-flight loads from outliving it.
self.workspace = None;
div().size_full().child(self.home.clone())
}
Route::Workspace(id) => match self.state.host.active().filter(|p| p.id == id) {
Some(project) => div().size_full().child(self.workspace_for(project, cx)),
// The route says open and the host disagrees. An empty workspace
// would strand the user, so fall back rather than render nothing.
None => { self.state.route.set(cx, Route::Home); div().size_full().child(self.home.clone()) }
},
}