Skip to main content

max / audiofiles

Draw the flipped warning instead of its Debug rendering `panel::window` matched a home address answering `Outcome::Screen` and fell through to a `format!("{other:?}")` label for anything else. Every described window before the flip answered `Screen`, so nothing noticed; the loose-files warning answers `Over`, and the window it was given drew a wall of Rust. `Over` is now accepted alongside `Screen`. "Over" says what a screen is drawn on top of, and a modal handed a window of its own is drawn on top of the app, so the two are the same thing from a host's side. The parity harness grows the job that would have caught it. A test there used to compare a described screen against the shipped panel it replaces, and that test dies with the module it compares against. It now also compares a described screen against what `panel::draw_*` actually drew for it, which outlives the flip and is what fails when the host stops rendering a screen it still serves. Two normalizations follow from reading a real rendering: an act carrying a key is drawn as `label (key)`, matched on the renderer's exact two-space separator so a label legitimately ending in a parenthetical survives, and `Parity::in_a_window` names the three controls an egui window frame adds.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-22 17:11 UTC
Signed with PGP, not checked
Commit: 3d1f0e3711fe8f1b1e9e16c6205a3a8734693a36
Parent: 84c613d
2 files changed, +73 insertions, -1 deletion
@@ -1729,7 +1729,19 @@
1729 1729 // holds and the help overlay lists. Every described
1730 1730 // window gets them, which is what "works from every
1731 1731 // screen" means for an app that has several.
1732 - quasi_router::Outcome::Screen(screen) => {
1732 + // `Over` as well as `Screen`, because a screen that is
1733 + // an overlay everywhere else is the whole of this window
1734 + // when the window is what the app opened for it. "Over"
1735 + // says what a screen is drawn on top of, and a modal
1736 + // given a window of its own is drawn on top of the app.
1737 + //
1738 + // Missing until 2026-08-22, and it did not matter while
1739 + // every described window was a `Screen`: the first flip
1740 + // pointed a window at `/library/loose-files`, which is
1741 + // an `Over`, and the window drew the outcome's `Debug`
1742 + // rendering instead of the screen.
1743 + quasi_router::Outcome::Screen(screen)
1744 + | quasi_router::Outcome::Over(screen) => {
1733 1745 none.insert(Runtime::new(screen).with_chrome(super::help::chrome()))
1734 1746 }
1735 1747 other => {
@@ -44,6 +44,20 @@
44 44 //! [`Offering::addresses_resolve`], which is the other half of the same claim:
45 45 //! every act the screen offers reaches a route the router actually has.
46 46 //!
47 + //! # Two jobs, and the second outlives the first
48 + //!
49 + //! Before a flip, a test here compares the described screen against the shipped
50 + //! panel it is about to replace. That test dies with the module it compared
51 + //! against, which is correct: there is nothing left to compare.
52 + //!
53 + //! After a flip, a test here compares the described screen against **what the
54 + //! host actually drew for it**, which is the same reader pointed at
55 + //! `panel::draw_*` instead of at `ui::*`. That one is permanent, and it is the
56 + //! guard the first flip needed and did not have: `panel::window` accepted a
57 + //! home address answering `Outcome::Screen` and not `Outcome::Over`, so the
58 + //! flipped loose-files warning drew the outcome's `Debug` rendering. Everything
59 + //! compiled, every other test passed, and the screen was a wall of Rust.
60 + //!
47 61 //! # The allowances
48 62 //!
49 63 //! A flip is allowed to change what a screen offers, and where it does, the
@@ -427,6 +441,18 @@
427 441 said = stripped.trim_end();
428 442 }
429 443 }
444 + // An act carrying a key is drawn with it, as `label (key)`. The
445 + // description says the key on the act instead, so this is the same
446 + // normalization the caret gets: one fact, said two ways.
447 + //
448 + // Matched on the renderer's exact separator, two spaces, rather than on any
449 + // trailing parenthetical. A label can legitimately end in one -- the theme
450 + // picker shows "System (audiofiles)" -- and a looser rule silently ate it.
451 + if said.ends_with(')')
452 + && let Some((label, _)) = said.rsplit_once(" (")
453 + {
454 + said = label.trim_end();
455 + }
430 456 said.to_owned()
431 457 }
432 458
@@ -504,6 +530,21 @@
504 530 self
505 531 }
506 532
533 + /// The `egui::Window` a described screen is drawn in, which is chrome.
534 + ///
535 + /// Three controls that belong to the frame rather than to the screen: the
536 + /// title bar's collapsing control, which carries the window's own name;
537 + /// egui's "Hide" for the same collapse; and "Close window" for the X. The
538 + /// description names the screen in `Screen::title` and leaves the frame to
539 + /// the host, which is the arrangement, so none of the three has a
540 + /// counterpart to compare against.
541 + #[must_use]
542 + pub(super) fn in_a_window(self, title: &str) -> Self {
543 + self.dropping(title)
544 + .dropping("Hide")
545 + .dropping("Close window")
546 + }
547 +
507 548 /// Assert the two sides offer the same thing, panicking with a diff if not.
508 549 pub(super) fn assert(&self, described: &Offering, shipped: &Offering) {
509 550 let mut want: BTreeMap<Offer, isize> = BTreeMap::new();
@@ -709,3 +750,22 @@
709 750 .gaining("Row height")
710 751 .assert(&described, &shipped);
711 752 }
753 +
754 + #[test]
755 + fn the_flipped_warning_serves_what_it_describes() {
756 + let (mut state, _dir) = fixture();
757 + state.loose_files.loose_files_missing_count = 3;
758 + state.loose_files.show_loose_files_warning = true;
759 +
760 + let described = described(&super::panel::described_screen(
761 + &state,
762 + "/library/loose-files",
763 + ));
764 + let drawn = shipped(|ui| {
765 + super::panel::draw_integrity(ui.ctx(), &mut state);
766 + });
767 +
768 + Parity::strict()
769 + .in_a_window("Loose-files mode warning")
770 + .assert(&described, &drawn);
771 + }