font browser
fix(refresh): Ctrl+R and Remove Font rescan the disk, not just the list
RefreshFonts and RemoveFont relisted the font database as loaded at launch,
so a font installed while the app was open never appeared and a removed one
stayed listed until a restart. Both now go through cce_ui::rescan_fonts,
which also brings the renderer's database along; Remove Font waits for the
trash to finish so the rescan finds the file gone. The selection follows
its family by name, since a rescan can add families above it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
src/main.rs | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index 4406392..dafb987 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -394,6 +394,15 @@ impl TypefaceApp {
v
}
+ /// Pick up fonts installed or removed since launch: the font database is
+ /// the disk as it was at startup until rescanned, so a reload alone only
+ /// relisted what was already known. The engine's renderer takes the same
+ /// change before its next frame.
+ fn rescan_fonts(&mut self) {
+ cce_ui::rescan_fonts(&mut self.font_system);
+ self.reload_fonts();
+ }
+
fn reload_fonts(&mut self) {
self.all_fonts = previewable_fonts(self.font_system.db());
self.families = self.extract_families(&self.all_fonts);
@@ -415,6 +424,11 @@ impl TypefaceApp {
self.ui_context.register_host(btn);
}
+ // A rescan can add families above the selection: keep it by name, not
+ // by row. (A removed family leaves its row to the one after it.)
+ if let Some(i) = self.selected_family.as_ref().and_then(|f| self.filtered.iter().position(|g| g == f)) {
+ self.selected_idx = Some(i);
+ }
if let Some(sel) = self.selected_idx {
if sel >= self.filtered.len() {
self.selected_idx = None;
@@ -892,16 +906,17 @@ impl Application for TypefaceApp {
AppMessage::RemoveFont => {
if let Some(ref file) = self.selected_file {
if self.is_user_font {
- let _ = std::process::Command::new("gio").args(["trash", file]).spawn();
+ // Waited for: the rescan must find the file gone.
+ let _ = std::process::Command::new("gio").args(["trash", file]).status();
let _ = std::process::Command::new("fc-cache").arg("-f").spawn();
- self.reload_fonts();
+ self.rescan_fonts();
*needs_rebuild = true;
self.needs_rebuild = true;
}
}
}
AppMessage::RefreshFonts => {
- self.reload_fonts();
+ self.rescan_fonts();
*needs_rebuild = true;
self.needs_rebuild = true;
}