max / audiofiles
6 files changed,
+86 insertions,
-19 deletions
| @@ -1168,6 +1168,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 1168 | 1168 | checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" | |
| 1169 | 1169 | ||
| 1170 | 1170 | [[package]] | |
| 1171 | + | name = "curve25519-dalek" | |
| 1172 | + | version = "4.1.3" | |
| 1173 | + | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1174 | + | checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" | |
| 1175 | + | dependencies = [ | |
| 1176 | + | "cfg-if", | |
| 1177 | + | "cpufeatures 0.2.17", | |
| 1178 | + | "curve25519-dalek-derive", | |
| 1179 | + | "fiat-crypto", | |
| 1180 | + | "rustc_version", | |
| 1181 | + | "subtle", | |
| 1182 | + | "zeroize", | |
| 1183 | + | ] | |
| 1184 | + | ||
| 1185 | + | [[package]] | |
| 1186 | + | name = "curve25519-dalek-derive" | |
| 1187 | + | version = "0.1.1" | |
| 1188 | + | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1189 | + | checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" | |
| 1190 | + | dependencies = [ | |
| 1191 | + | "proc-macro2", | |
| 1192 | + | "quote", | |
| 1193 | + | "syn 2.0.119", | |
| 1194 | + | ] | |
| 1195 | + | ||
| 1196 | + | [[package]] | |
| 1171 | 1197 | name = "dasp_sample" | |
| 1172 | 1198 | version = "0.11.0" | |
| 1173 | 1199 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| @@ -1609,6 +1635,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 1609 | 1635 | checksum = "b97b65636e5b9ef369943878ac74335ba1c55c1cb6adbf1e2c293c624248d693" | |
| 1610 | 1636 | ||
| 1611 | 1637 | [[package]] | |
| 1638 | + | name = "fiat-crypto" | |
| 1639 | + | version = "0.2.9" | |
| 1640 | + | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1641 | + | checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" | |
| 1642 | + | ||
| 1643 | + | [[package]] | |
| 1612 | 1644 | name = "field-offset" | |
| 1613 | 1645 | version = "0.3.6" | |
| 1614 | 1646 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| @@ -4455,7 +4487,7 @@ dependencies = [ | |||
| 4455 | 4487 | "security-framework", | |
| 4456 | 4488 | "security-framework-sys", | |
| 4457 | 4489 | "webpki-root-certs", | |
| 4458 | - | "windows-sys 0.52.0", | |
| 4490 | + | "windows-sys 0.61.2", | |
| 4459 | 4491 | ] | |
| 4460 | 4492 | ||
| 4461 | 4493 | [[package]] | |
| @@ -5338,6 +5370,7 @@ dependencies = [ | |||
| 5338 | 5370 | "unicode-normalization", | |
| 5339 | 5371 | "urlencoding", | |
| 5340 | 5372 | "uuid", | |
| 5373 | + | "x25519-dalek", | |
| 5341 | 5374 | "zeroize", | |
| 5342 | 5375 | ] | |
| 5343 | 5376 | ||
| @@ -6936,6 +6969,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 6936 | 6969 | checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" | |
| 6937 | 6970 | ||
| 6938 | 6971 | [[package]] | |
| 6972 | + | name = "x25519-dalek" | |
| 6973 | + | version = "2.0.1" | |
| 6974 | + | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 6975 | + | checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" | |
| 6976 | + | dependencies = [ | |
| 6977 | + | "curve25519-dalek", | |
| 6978 | + | "rand_core 0.6.4", | |
| 6979 | + | "zeroize", | |
| 6980 | + | ] | |
| 6981 | + | ||
| 6982 | + | [[package]] | |
| 6939 | 6983 | name = "xcursor" | |
| 6940 | 6984 | version = "0.3.10" | |
| 6941 | 6985 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| @@ -7107,6 +7151,20 @@ name = "zeroize" | |||
| 7107 | 7151 | version = "1.9.0" | |
| 7108 | 7152 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 7109 | 7153 | checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" | |
| 7154 | + | dependencies = [ | |
| 7155 | + | "zeroize_derive", | |
| 7156 | + | ] | |
| 7157 | + | ||
| 7158 | + | [[package]] | |
| 7159 | + | name = "zeroize_derive" | |
| 7160 | + | version = "1.5.0" | |
| 7161 | + | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 7162 | + | checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" | |
| 7163 | + | dependencies = [ | |
| 7164 | + | "proc-macro2", | |
| 7165 | + | "quote", | |
| 7166 | + | "syn 2.0.119", | |
| 7167 | + | ] | |
| 7110 | 7168 | ||
| 7111 | 7169 | [[package]] | |
| 7112 | 7170 | name = "zerotrie" |
| @@ -267,10 +267,11 @@ impl BrowserState { | |||
| 267 | 267 | ||
| 268 | 268 | /// Refresh the collection list from the database. | |
| 269 | 269 | pub fn refresh_collections(&mut self) { | |
| 270 | - | self.collections_ui.collections = self.backend.list_collections().unwrap_or_else(|e| { | |
| 271 | - | warn!("Failed to load collections: {e}"); | |
| 272 | - | Vec::new() | |
| 273 | - | }); | |
| 270 | + | self.collections_ui.collections = | |
| 271 | + | Arc::new(self.backend.list_collections().unwrap_or_else(|e| { | |
| 272 | + | warn!("Failed to load collections: {e}"); | |
| 273 | + | Vec::new() | |
| 274 | + | })); | |
| 274 | 275 | } | |
| 275 | 276 | ||
| 276 | 277 | /// Activate a collection: show its members in the file list. |
| @@ -503,7 +503,7 @@ impl BrowserState { | |||
| 503 | 503 | last_dismissed_suggestion: None, | |
| 504 | 504 | current_theme_id: theme_id, | |
| 505 | 505 | collections_ui: CollectionsUiState { | |
| 506 | - | collections: collections_list, | |
| 506 | + | collections: Arc::new(collections_list), | |
| 507 | 507 | ..Default::default() | |
| 508 | 508 | }, | |
| 509 | 509 | edit: EditUiState::default(), |
| @@ -528,7 +528,10 @@ pub struct MirrorUiState { | |||
| 528 | 528 | /// Collections sidebar: list, active selection, and create/rename inputs. | |
| 529 | 529 | #[derive(Default)] | |
| 530 | 530 | pub struct CollectionsUiState { | |
| 531 | - | pub collections: Vec<audiofiles_core::collections::Collection>, | |
| 531 | + | // Arc so the sidebar / context menus can cheaply snapshot the list to | |
| 532 | + | // decouple the borrow (matching nav.vfs_list and all_tags) instead of | |
| 533 | + | // deep-cloning the Vec every frame. Replaced wholesale by refresh_collections. | |
| 534 | + | pub collections: std::sync::Arc<Vec<audiofiles_core::collections::Collection>>, | |
| 532 | 535 | pub active_collection: Option<audiofiles_core::CollectionId>, | |
| 533 | 536 | pub collection_create_input: String, | |
| 534 | 537 | pub collection_rename_target: Option<(audiofiles_core::CollectionId, String)>, |
| @@ -114,7 +114,7 @@ pub fn draw_context_menu( | |||
| 114 | 114 | let is_in_collection = state.collections_ui.active_collection.is_some(); | |
| 115 | 115 | if !collections.is_empty() { | |
| 116 | 116 | ui.menu_button("Add to Collection", |ui| { | |
| 117 | - | for coll in &collections { | |
| 117 | + | for coll in collections.iter() { | |
| 118 | 118 | if ui.button(&coll.name).clicked() { | |
| 119 | 119 | let _ = state.backend.add_to_collection(coll.id, &hash_clone); | |
| 120 | 120 | state.refresh_collections(); | |
| @@ -262,7 +262,7 @@ pub fn draw_multi_context_menu(ui: &mut egui::Ui, state: &mut BrowserState) { | |||
| 262 | 262 | let collections = state.collections_ui.collections.clone(); | |
| 263 | 263 | if !collections.is_empty() { | |
| 264 | 264 | ui.menu_button("Add to Collection", |ui| { | |
| 265 | - | for coll in &collections { | |
| 265 | + | for coll in collections.iter() { | |
| 266 | 266 | if ui.button(&coll.name).clicked() { | |
| 267 | 267 | let nodes = state.selected_nodes(); | |
| 268 | 268 | // Count only samples actually added — directories (no hash) |
| @@ -371,7 +371,7 @@ pub fn draw_sidebar(ui: &mut egui::Ui, state: &mut BrowserState) { | |||
| 371 | 371 | let collections = state.collections_ui.collections.clone(); | |
| 372 | 372 | let active_id = state.collections_ui.active_collection; | |
| 373 | 373 | let mut delete_id: Option<(audiofiles_core::CollectionId, String)> = None; | |
| 374 | - | for coll in &collections { | |
| 374 | + | for coll in collections.iter() { | |
| 375 | 375 | let is_active = active_id == Some(coll.id); | |
| 376 | 376 | // Dynamic collections re-apply their saved filter; manual collections | |
| 377 | 377 | // hold a fixed sample set. Distinguish with a text suffix instead of a | |
| @@ -529,15 +529,20 @@ pub fn draw_sidebar(ui: &mut egui::Ui, state: &mut BrowserState) { | |||
| 529 | 529 | // render alongside the filter input. | |
| 530 | 530 | let total = state.all_tags.len(); | |
| 531 | 531 | let query = state.search.tag_search.to_lowercase(); | |
| 532 | - | let filtered_tags: Vec<String> = if query.is_empty() { | |
| 533 | - | state.all_tags.as_ref().clone() | |
| 532 | + | // No filter is the common case: share the Arc rather than deep-cloning | |
| 533 | + | // the whole tag list every frame. A filter still materializes the | |
| 534 | + | // (smaller) matching subset. | |
| 535 | + | let filtered_tags: std::sync::Arc<Vec<String>> = if query.is_empty() { | |
| 536 | + | std::sync::Arc::clone(&state.all_tags) | |
| 534 | 537 | } else { | |
| 535 | - | state | |
| 536 | - | .all_tags | |
| 537 | - | .iter() | |
| 538 | - | .filter(|t| t.to_lowercase().contains(&query)) | |
| 539 | - | .cloned() | |
| 540 | - | .collect() | |
| 538 | + | std::sync::Arc::new( | |
| 539 | + | state | |
| 540 | + | .all_tags | |
| 541 | + | .iter() | |
| 542 | + | .filter(|t| t.to_lowercase().contains(&query)) | |
| 543 | + | .cloned() | |
| 544 | + | .collect(), | |
| 545 | + | ) | |
| 541 | 546 | }; | |
| 542 | 547 | // Tag filter input — pair with a Clear button when populated so the | |
| 543 | 548 | // user doesn't have to select-all-and-delete. Mirrors the sample | |
| @@ -657,7 +662,7 @@ pub fn draw_sidebar(ui: &mut egui::Ui, state: &mut BrowserState) { | |||
| 657 | 662 | if filtered_tags.is_empty() { | |
| 658 | 663 | ui.label(egui::RichText::new("No matching tags").color(theme::content_muted())); | |
| 659 | 664 | } else { | |
| 660 | - | let tree = build_tag_tree(&filtered_tags); | |
| 665 | + | let tree = build_tag_tree(filtered_tags.as_slice()); | |
| 661 | 666 | for (segment, node) in &tree { | |
| 662 | 667 | draw_tag_node(ui, "", segment, node, state); | |
| 663 | 668 | } |