Skip to main content

max / audiofiles

Prove the described detail panel keeps Cmd+Z `162b99a3` set the bar for its own flip -- "a flip that loses Cmd+Z has failed" -- and nothing was checking it. The undo entry is why the detail panel's tag writes are intents rather than handle calls: a route can remove the tag and cannot push the entry that makes it recoverable, so what the app does around a write is what decides where the write goes.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-22 19:45 UTC
Signed with PGP, not checked
Commit: 1fe9eaca6f0f9d0e3573133397ed0658631c3edf
Parent: 4953cfd
1 file changed, +57 insertions, -0 deletions
@@ -2090,3 +2090,60 @@
2090 2090 Err(message) => panic!("{address} was refused: {message}"),
2091 2091 }
2092 2092 }
2093 +
2094 + #[cfg(test)]
2095 + mod tests {
2096 + use super::*;
2097 +
2098 + /// A real app with one sample chosen, which is what a tag act needs.
2099 + fn chosen() -> (BrowserState, tempfile::TempDir) {
2100 + use std::sync::Arc;
2101 +
2102 + let dir = tempfile::TempDir::new().unwrap();
2103 + let shared = Arc::new(crate::state::SharedState::new());
2104 + let mut state = BrowserState::new(dir.path(), shared, 44_100.0, "Vault").unwrap();
2105 +
2106 + let vfs = state.current_vfs_id().unwrap();
2107 + let parent = state.nav.current_dir;
2108 + let db = audiofiles_core::db::Database::open(state.data_dir.join("audiofiles.db")).unwrap();
2109 + db.conn()
2110 + .execute(
2111 + "INSERT OR IGNORE INTO samples \
2112 + (hash, original_name, file_extension, file_size, import_date, last_modified) \
2113 + VALUES ('aaa111', 'aaa111.wav', 'wav', 100, 0, 0)",
2114 + [],
2115 + )
2116 + .unwrap();
2117 + state
2118 + .backend
2119 + .create_sample_link(vfs, parent, "kick.wav", "aaa111")
2120 + .unwrap();
2121 + state.refresh_contents();
2122 + state.nav.selection.set_single(0);
2123 + (state, dir)
2124 + }
2125 +
2126 + #[test]
2127 + fn removing_a_tag_from_the_described_panel_is_undoable() {
2128 + // `162b99a3` states the bar this has to clear: "a flip that loses Cmd+Z
2129 + // has failed." It is the reason the detail panel's tag writes are
2130 + // intents rather than handle calls -- a route can remove the tag and
2131 + // cannot push the undo entry that makes it recoverable, so what the app
2132 + // does *around* a write is what decides where the write goes.
2133 + let (mut state, _dir) = chosen();
2134 + add_tag(&mut state, "drums");
2135 + assert_eq!(state.detail.selected_tags.len(), 1);
2136 +
2137 + remove_tag(&mut state, "drums");
2138 + assert!(state.detail.selected_tags.is_empty(), "the tag is gone");
2139 +
2140 + assert!(state.can_undo(), "and taking it off is undoable");
2141 + state.undo();
2142 + assert_eq!(
2143 + state.detail.selected_tags.len(),
2144 + 1,
2145 + "undo puts it back: {:?}",
2146 + state.detail.selected_tags
2147 + );
2148 + }
2149 + }