7.4 KiB
Phase 2 — /simplify review
Date: 2026-06-17
Branch: feat-phase2
Scope: git diff main...HEAD — the whole phase-2 feature branch (~5,900 added
lines across 34 files: tabs, search, resizable columns, WSL browsing,
icons/thumbnails, and supporting modules).
This was a quality pass (reuse, simplification, efficiency, altitude), not a correctness-bug hunt. The change was reviewed from four independent angles, the findings deduped, and the high-confidence ones applied. Everything below is behavior-preserving.
Verification: cargo check --workspace --all-targets, cargo clippy --workspace --all-targets, and cargo fmt --all --check are all clean; all 86
tests pass (23 librarian-core, 13 librarian-win, 50 librarian-app).
Applied
Reuse
-
tab_titlewas a verbatim re-implementation ofLocation::label().tab_titlereproducedlabel's logic for every arm (ThisPc → "This PC",Wsl → "Linux",Path → file_name() else display()).- Deleted
fn tab_titleincrates/librarian-app/src/main.rs;view_tabnow callsself.tab_location(i).label(). - The app-level test
tab_titles_use_the_folder_namewas removed and its coverage moved to where the logic now lives:path_label_is_the_file_name_or_full_path_for_rootsincrates/librarian-core/src/model.rs. address_textwas checked and left alone — it uses the fulldisplay()for paths, so it is not a duplicate oflabel.
- Deleted
-
rows::file_extensionduplicatedEntry::extension. Both computed the lowercase, dotless extension.- Added one shared free function
extension_of(&Path) -> Stringincrates/librarian-core/src/model.rs(re-exported fromlib.rs). Entry::extensionnow delegates to it;rows::file_extensionwas deleted androw_from_hitcallsextension_ofdirectly.
- Added one shared free function
-
type_labelduplicatedext_type_label. Incrates/librarian-app/src/rows.rs,type_labelre-derived the"{EXT} File"/"File"strings thatext_type_labelalready produces. It now returns early for directories and delegates toext_type_label(&entry.extension()).
Simplification
-
The
Content::ThisPc { drives: Vec::new() }placeholder appeared four times. It was used both as the real "This PC" landing page and as a throwaway filler. Addedimpl Default for Content(returning that value) incrates/librarian-app/src/main.rs; the park site insnapshot_flatnow usesstd::mem::take(&mut self.content), and the other sites useContent::default(). -
The "allocate a fresh load token" idiom was copy-pasted.
self.next_token += 1; let token = self.next_token; self.load_token = token;appeared in bothDirChangedandload_current. Collapsed into anext_load_token(&mut self) -> u64helper.
Efficiency
view_rowre-shaped every visible row's name text on every frame. The per-row ellipsis-tooltip check calledmeasure_width(&data.label, LIST_TEXT_SIZE)— a full text-shaping pass — for each rendered row, every redraw (scroll, hover, selection, spinner tick…).- Added a cached
name_px: f32toRow(crates/librarian-app/src/rows.rs). - Added
remeasure_details(&mut self)inmain.rs, which fillsname_pxalongside the existing column measurement. It is called from the two places that already measure details widths —recompute_rows(row set changed) andViewModeChanged(switching into details) — and is a no-op in the grid modes. Because the rows are parked per-tab, the cached widths travel with them across tab switches. view_row's check is now the float comparedata.name_px > widths.name. The cached value equals the old live measurement (font andLIST_TEXT_SIZEare constant), so tooltip behavior is unchanged.
- Added a cached
Altitude
-
is_visible'sname_filterparameter was dead infrastructure. It was a leftover seam from the old type-to-filter box that the ripgrep-backed search replaced; both surviving callers passed"". Dropped the parameter and its unreachable substring-match branch fromcrates/librarian-core/src/sort.rs, updated the two callers inmain.rs, and removed the now-vestigialname_filtertest. -
The WSL host literals (
wsl.localhost/wsl$) were duplicated across crates. The recognition strings lived in bothlibrarian-core'sis_wsl_root_pathand the app'stree.rs::is_wsl_path. Addedis_wsl_host(&str) -> bool(backed by a singleWSL_HOSTSconstant) incrates/librarian-core/src/model.rs(re-exported fromlib.rs); both recognizers now call it for the host test. The two predicates keep their deliberately different parsing strategies (component/Prefix-based "is this a distro root" vs. string-based "is this under a WSL host"); only the host knowledge is now shared.librarian-win::distro_unc_pathwas left as-is: it only constructs the canonical path (it is not a recognizer) andlibrarian-windoes not depend onlibrarian-core.
Considered but not applied
-
TabState/snapshot_flat/restore_flat/reset_flatrepeat the same ~15 fields four times (the top simplification finding). The proper fix — embedding the per-tab fields in one struct held byLibrarianand moving it as a unit — would require rewriting everyself.<field>access across the whole ~5,000-linemain.rs, almost all of it outside this diff. Too broad and risky for a cleanup pass; better done deliberately as its own focused change. It is the most valuable remaining cleanup and also the one most likely to harbor a silent "forgot a field inrestore_flat" bug, so it is worth scheduling. -
is_input_shortcuthand-mirrors the set of messageskey_to_messagecan produce (flagged by both the simplification and altitude angles; the comment itself says "keep in sync"). The only real dedup is to gate at the source — tag keyboard-origin messages, or suppress translation in the subscription while the loading overlay is up — which is an architectural change to the message flow that risks altering behavior. Left as-is. -
view_command_bar/view_toolbarbuild a row withlet mut bar … if let Some(clear) = clear { bar = bar.push(clear) }. The suggested.push_maybe()does not exist onRowin iced 0.14.2 (onlygridandkeyed::columnexpose it), so the current form is already the idiomatic one. No change. -
The command bar is rendered inside the right
pane_gridpane rather than at the top level. This is an intentional trick to align its controls with the list's columns across the tree/list divider; moving it would change the layout. Left as intended behavior. -
ColumnLayout/ColumnPx/ColumnMeasureencode the four columns as named fields with per-columnmatchaccessors instead of an array indexed byColumn. The altitude angle flagged it; the simplification angle explicitly judged the named fields more readable than the array churn for a fixed, rarely-changing set of four. Kept the named fields. -
Smaller efficiency / cohesion items — co-locating
ViewMode's two string-mapping tables, caching the per-frame tab-title and tree-row label allocations, and the redundant startuplist_wsl_distros()call. Each is low value (small N, already off the UI thread, or cross-file cohesion only) and would add state or coupling that cuts against the simplification goal. Left as-is.