From e8d62ae43d0eb6b21f0c35910106f7713fcd8a5f Mon Sep 17 00:00:00 2001 From: leyoda Date: Thu, 23 Apr 2026 20:18:21 +0200 Subject: [PATCH] yoda: add "Always use this app" toggle to OpenWith dialog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'Open with...' dialog let you pick an app but never remembered your choice — you'd see the same dialog again next time. The infrastructure was already there (MimeAppCache::set_default writes to mimeapps.list), just never wired to the UI. Adds a toggler below the app list labelled 'Always use this app for this file type' (EN) / 'Toujours utiliser cette application pour ce type de fichier' (FR). When enabled, after spawning the selected app, the default handler for the file's mime type is persisted via self.mime_app_cache.set_default(mime, app.id). Implementation: - DialogPage::OpenWith gains a set_default: bool field (defaulted false) - Message::OpenWithToggleDefault(bool) + handler mutates the dialog state - DialogComplete handler for OpenWith calls set_default after a clean spawn when the flag is set - Dialog rendering adds a .control(widget::row) with label + toggler, between the scrollable list and the action buttons - i18n strings added: en/fr open-with-set-default --- i18n/en/cosmic_files.ftl | 1 + i18n/fr/cosmic_files.ftl | 1 + src/app.rs | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/i18n/en/cosmic_files.ftl b/i18n/en/cosmic_files.ftl index 69a76c6..9fed322 100644 --- a/i18n/en/cosmic_files.ftl +++ b/i18n/en/cosmic_files.ftl @@ -96,6 +96,7 @@ save-file = Save file ## Open With Dialog open-with-title = How do you want to open "{$name}"? +open-with-set-default = Always use this app for this file type browse-store = Browse {$store} other-apps = Other applications related-apps = Related applications diff --git a/i18n/fr/cosmic_files.ftl b/i18n/fr/cosmic_files.ftl index a461a9f..e0fa6f9 100644 --- a/i18n/fr/cosmic_files.ftl +++ b/i18n/fr/cosmic_files.ftl @@ -92,6 +92,7 @@ save-file = Enregistrer fichier ## Open With Dialog open-with-title = Comment souhaitez-vous ouvrir "{ $name }" ? +open-with-set-default = Toujours utiliser cette application pour ce type de fichier browse-store = Parcourir { $store } ## Permanently delete Dialog diff --git a/src/app.rs b/src/app.rs index feca9c5..2224ab5 100644 --- a/src/app.rs +++ b/src/app.rs @@ -407,6 +407,7 @@ pub enum Message { OpenWithBrowse, OpenWithDialog(Option), OpenWithSelection(usize), + OpenWithToggleDefault(bool), #[cfg(all(feature = "wayland", feature = "desktop-applet"))] Overlap(window::Id, OverlapNotifyEvent), Paste(Option), @@ -577,6 +578,9 @@ pub enum DialogPage { mime: mime_guess::Mime, selected: usize, store_opt: Option, + /// When true, the chosen app is written to mimeapps.list as the + /// default handler for `mime` after it spawns. + set_default: bool, }, PermanentlyDelete { paths: Box<[PathBuf]>, @@ -3232,6 +3236,7 @@ impl Application for App { path, mime, selected, + set_default, .. } => { let available_apps = self.get_apps_for_mime(&mime); @@ -3250,6 +3255,11 @@ impl Application for App { None, ); } + // Yoda: persist as default if the user asked for it. + if set_default { + self.mime_app_cache + .set_default(mime.clone(), app.id.clone()); + } } Err(err) => { log::warn!( @@ -3872,6 +3882,7 @@ impl Application for App { .and_then(|mime| { self.mime_app_cache.get(&mime).first().cloned() }), + set_default: false, }, Some(CONFIRM_OPEN_WITH_BUTTON_ID.clone()), ); @@ -3883,6 +3894,13 @@ impl Application for App { *selected = index; } } + Message::OpenWithToggleDefault(enabled) => { + if let Some(DialogPage::OpenWith { set_default, .. }) = + self.dialog_pages.front_mut() + { + *set_default = enabled; + } + } Message::Paste(entity_opt) => { let entity = entity_opt.unwrap_or_else(|| self.tab_model.active()); if let Some(tab) = self.tab_model.data_mut::(entity) @@ -5110,6 +5128,7 @@ impl Application for App { .and_then(|mime| { self.mime_app_cache.get(&mime).first().cloned() }), + set_default: false, }, None, ); @@ -5953,7 +5972,7 @@ impl Application for App { mime, selected, store_opt, - .. + set_default, } => { let name = match path.file_name() { Some(file_name) => file_name.to_str(), @@ -6038,7 +6057,21 @@ impl Application for App { } else { Length::Shrink } - })); + })) + // Yoda: let the user make this choice stick. A plain row + // instead of settings::item::builder because the latter + // returns a section Item, not an Element usable in .control(). + .control( + widget::row::with_children([ + widget::text::body(fl!("open-with-set-default")).into(), + widget::space::horizontal().into(), + widget::toggler(*set_default) + .on_toggle(Message::OpenWithToggleDefault) + .into(), + ]) + .spacing(space_s) + .align_y(Alignment::Center), + ); if let Some(app) = store_opt { dialog = dialog.tertiary_action(