yoda: add "Always use this app" toggle to OpenWith dialog
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
This commit is contained in:
parent
a025fd6380
commit
e8d62ae43d
3 changed files with 37 additions and 2 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
37
src/app.rs
37
src/app.rs
|
|
@ -407,6 +407,7 @@ pub enum Message {
|
|||
OpenWithBrowse,
|
||||
OpenWithDialog(Option<Entity>),
|
||||
OpenWithSelection(usize),
|
||||
OpenWithToggleDefault(bool),
|
||||
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
|
||||
Overlap(window::Id, OverlapNotifyEvent),
|
||||
Paste(Option<Entity>),
|
||||
|
|
@ -577,6 +578,9 @@ pub enum DialogPage {
|
|||
mime: mime_guess::Mime,
|
||||
selected: usize,
|
||||
store_opt: Option<MimeApp>,
|
||||
/// 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::<Tab>(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(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue