Skip to main content

max / audiofiles

The sync panel says it is live, and notices what happened elsewhere Closes the finding this module's header has carried since the port: the state moves without anyone acting -- an OAuth callback lands in another process and `Authenticating` becomes `NeedsEncryption` -- and a description is built once, so the described panel was a photograph. `Slot::live` on the body says the contents move and says nothing about how often to look. The cadence is `quasi_immediate::CADENCE`, paced by the runtime, so the host asks `refreshes()` and owns no timer. A live screen with no call to fetch is re-asked at its own address, which is what re-reading means when the state is the app's own. Takes quasi 0.33.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-19 02:40 UTC
Signed with PGP, not checked
Commit: 1dade386f327a31ed57c7a08891778f243eb2307
Parent: 16edea0
4 files changed, +68 insertions, -39 deletions
M Cargo.lock +34 -34
@@ -4241,7 +4241,7 @@
4241 4241
4242 4242 [[package]]
4243 4243 name = "quasi-immediate"
4244 - version = "0.32.0"
4244 + version = "0.33.0"
4245 4245 dependencies = [
4246 4246 "docengine",
4247 4247 "egui",
@@ -4251,7 +4251,7 @@
4251 4251
4252 4252 [[package]]
4253 4253 name = "quasi-router"
4254 - version = "0.32.0"
4254 + version = "0.33.0"
4255 4255 dependencies = [
4256 4256 "makeover-layout",
4257 4257 ]
@@ -7540,10 +7540,6 @@
7540 7540 "winnow 1.0.4",
7541 7541 ]
7542 7542
7543 - [[patch.unused]]
7544 - name = "quasi-type"
7545 - version = "0.1.0"
7546 -
7547 7543 [[patch.unused]]
7548 7544 name = "makeover-build"
7549 7545 version = "0.46.0"
@@ -7560,6 +7556,38 @@
7560 7556 name = "makeover-webview"
7561 7557 version = "0.51.0"
7562 7558
7559 + [[patch.unused]]
7560 + name = "quasi-axum"
7561 + version = "0.33.0"
7562 +
7563 + [[patch.unused]]
7564 + name = "quasi-basics"
7565 + version = "0.33.0"
7566 +
7567 + [[patch.unused]]
7568 + name = "quasi-http"
7569 + version = "0.33.0"
7570 +
7571 + [[patch.unused]]
7572 + name = "quasi-notifs"
7573 + version = "0.33.0"
7574 +
7575 + [[patch.unused]]
7576 + name = "quasi-store"
7577 + version = "0.1.0"
7578 +
7579 + [[patch.unused]]
7580 + name = "quasi-tauri"
7581 + version = "0.33.0"
7582 +
7583 + [[patch.unused]]
7584 + name = "quasi-webview"
7585 + version = "0.33.0"
7586 +
7587 + [[patch.unused]]
7588 + name = "quasi-type"
7589 + version = "0.1.0"
7590 +
7563 7591 [[patch.unused]]
7564 7592 name = "kberg"
7565 7593 version = "0.1.0"
@@ -7571,31 +7599,3 @@
7571 7599 [[patch.unused]]
7572 7600 name = "painhours"
7573 7601 version = "0.1.0"
7574 -
7575 - [[patch.unused]]
7576 - name = "quasi-axum"
7577 - version = "0.32.0"
7578 -
7579 - [[patch.unused]]
7580 - name = "quasi-basics"
7581 - version = "0.32.0"
7582 -
7583 - [[patch.unused]]
7584 - name = "quasi-http"
7585 - version = "0.32.0"
7586 -
7587 - [[patch.unused]]
7588 - name = "quasi-notifs"
7589 - version = "0.32.0"
7590 -
7591 - [[patch.unused]]
7592 - name = "quasi-store"
7593 - version = "0.1.0"
7594 -
7595 - [[patch.unused]]
7596 - name = "quasi-tauri"
7597 - version = "0.32.0"
7598 -
7599 - [[patch.unused]]
7600 - name = "quasi-webview"
7601 - version = "0.32.0"
M Cargo.toml +2 -2
@@ -21,8 +21,8 @@
21 21 makeover-immediate = "0.30.0"
22 22 # The described screens, behind audiofiles-browser's `quasi` feature. By git URL
23 23 # with a version requirement, per the tree's rule for cross-repo deps.
24 - quasi-router = { git = "https://makenot.work/git/max/quasi.git", version = "0.32" }
25 - quasi-immediate = { git = "https://makenot.work/git/max/quasi.git", version = "0.32" }
24 + quasi-router = { git = "https://makenot.work/git/max/quasi.git", version = "0.33" }
25 + quasi-immediate = { git = "https://makenot.work/git/max/quasi.git", version = "0.33" }
26 26 egui = { version = "0.35", default-features = false, features = ["default_fonts"] }
27 27 egui_extras = { version = "0.35", default-features = false }
28 28 eframe = { version = "0.35", default-features = false, features = ["default_fonts", "glow"] }
@@ -1596,6 +1596,22 @@
1596 1596 perform(runtime, ui, host, step);
1597 1597 }
1598 1598
1599 + // A screen that says it is live is re-asked on the renderer's own
1600 + // cadence, which is `quasi_immediate::CADENCE` and is paced by the
1601 + // runtime rather than by anything here. This is the whole of what
1602 + // the sync panel's finding asked for: its state moves when an OAuth
1603 + // callback lands in another process, and until now nothing but an
1604 + // intent or a per-frame reload would notice.
1605 + //
1606 + // Under the same overlay guard as the refresh above, and for the
1607 + // same reason: a live screen's address is the screen underneath an
1608 + // open modal, and asking for it would take the modal down.
1609 + if !runtime.overlaid() {
1610 + for request in runtime.refreshes() {
1611 + call(runtime, host, request);
1612 + }
1613 + }
1614 +
1599 1615 let step = runtime.show(ui, &immediate);
1600 1616 perform(runtime, ui, host, step);
1601 1617 });
@@ -35,7 +35,7 @@
35 35 //! description says "somewhere outside the app" and each host already knows what
36 36 //! that means for it.
37 37 //!
38 - //! # THE FINDING: a description is built once, and this screen is alive
38 + //! # THE FINDING, closed: a description is built once, and this screen is alive
39 39 //!
40 40 //! The panel reads `sync.status()` **every frame** and redraws from it: the
41 41 //! spinner while syncing, the pending-changes count as it falls, the state
@@ -53,7 +53,12 @@
53 53 //! timeout here. How long an undo stays offered is renderer policy"). The
54 54 //! missing word is nearer "this region reports something that changes without
55 55 //! the user" — a fact about the content, which the renderer then answers with a
56 - //! cadence of its own choosing. Filed rather than invented here.
56 + //! cadence of its own choosing.
57 + //!
58 + //! That is what [`Slot::live`](quasi_router::Slot::live) is, and this screen is
59 + //! its acceptance case. `screen` sets it on the body; each renderer holds one
60 + //! `CADENCE` for every live region it draws, so the two hosts no longer invent
61 + //! their own. Nothing here re-reads per frame any more.
57 62 //!
58 63 //! # The subscription section, and the two findings it produced
59 64 //!
@@ -286,7 +291,15 @@
286 291 /// bookmark into a lie.
287 292 fn screen(sync: &dyn Sync) -> Screen {
288 293 let status = sync.status();
289 - let mut body = Slot::new(BODY, RegionKind::Pane).with(Node::page("Cloud Sync"));
294 + // Live, which is the whole of what the finding in this module's header
295 + // asked for. The state moves without anyone acting: an OAuth callback lands
296 + // in another process and `Authenticating` becomes `NeedsEncryption`, and the
297 + // pending count falls while a sync runs. The description says the contents
298 + // move and says nothing about how often to look; the cadence is
299 + // `quasi_immediate::CADENCE`, and the host no longer owns a timer.
300 + let mut body = Slot::new(BODY, RegionKind::Pane)
301 + .live()
302 + .with(Node::page("Cloud Sync"));
290 303
291 304 body = match status.state {
292 305 State::Disconnected => disconnected(body),