From 5fd7be593a74ee88d4c94c88aec127a37c3a6bd1 Mon Sep 17 00:00:00 2001 From: Jason Rodney Hansen Date: Sun, 23 Mar 2025 14:18:00 -0600 Subject: [PATCH 1/3] Use Open Folder dialog for Extract To --- src/app.rs | 103 ++++++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 48 deletions(-) diff --git a/src/app.rs b/src/app.rs index d5cba63..160d572 100644 --- a/src/app.rs +++ b/src/app.rs @@ -63,11 +63,10 @@ use trash::TrashItem; #[cfg(feature = "wayland")] use wayland_client::{protocol::wl_output::WlOutput, Proxy}; -use crate::mime_app::MimeApp; -use crate::operation::{OperationError, OperationErrorType}; use crate::{ clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste}, config::{AppTheme, Config, DesktopConfig, Favorite, IconSizes, TabConfig, TypeToSearch}, + dialog::{DialogKind, DialogMessage}, fl, home_dir, key_bind::key_binds, localize::LANGUAGE_SORTER, @@ -77,6 +76,11 @@ use crate::{ spawn_detached::spawn_detached, tab::{self, HeadingOptions, ItemMetadata, Location, Tab, HOVER_DURATION}, }; +use crate::{ + dialog::Dialog, + operation::{OperationError, OperationErrorType}, +}; +use crate::{dialog::DialogResult, mime_app::MimeApp}; #[derive(Clone, Debug)] pub enum Mode { @@ -291,11 +295,13 @@ pub enum Message { DesktopViewOptions, DialogCancel, DialogComplete, + FileDialogMessage(DialogMessage), DialogPush(DialogPage), DialogUpdate(DialogPage), DialogUpdateComplete(DialogPage), ExtractHere(Option), ExtractTo(Option), + ExtractToResult(DialogResult), #[cfg(all(feature = "desktop", feature = "wayland"))] Focused(window::Id), Key(Modifiers, Key, Option), @@ -434,11 +440,6 @@ pub enum DialogPage { archive_type: ArchiveType, password: Option, }, - ExtractTo { - paths: Vec, - to: PathBuf, - password: Option, - }, EmptyTrash, FailedOperation(u64), ExtractPassword { @@ -503,6 +504,7 @@ pub enum WindowKind { Desktop(Entity), DesktopViewOptions, Preview(Option, PreviewKind), + FileDialog(Option>), } pub struct WatcherWrapper { @@ -570,6 +572,7 @@ pub struct App { nav_drag_id: DragId, tab_drag_id: DragId, auto_scroll_speed: Option, + file_dialog_opt: Option>, } impl App { @@ -1794,6 +1797,7 @@ impl Application for App { nav_drag_id: DragId::new(), tab_drag_id: DragId::new(), auto_scroll_speed: None, + file_dialog_opt: None, }; let mut commands = vec![app.update_config()]; @@ -2237,17 +2241,6 @@ impl Application for App { DialogPage::EmptyTrash => { self.operation(Operation::EmptyTrash); } - DialogPage::ExtractTo { - paths, - to, - password, - } => { - self.operation(Operation::Extract { - paths, - to, - password: None, - }); - } DialogPage::FailedOperation(id) => { log::warn!("TODO: retry operation {}", id); } @@ -2402,13 +2395,47 @@ impl Application for App { .and_then(|first| first.parent()) .map(|parent| parent.to_path_buf()) { - self.dialog_pages.push_back(DialogPage::ExtractTo { - paths, - to: destination, - password: None, - }); + let (dialog, command) = Dialog::new( + DialogKind::OpenFolder, + Some(destination), + Message::FileDialogMessage, + Message::ExtractToResult, + ); + self.windows + .insert(dialog.window_id(), WindowKind::FileDialog(Some(paths))); + self.file_dialog_opt = Some(dialog); + return command; }; } + Message::ExtractToResult(result) => { + match result { + DialogResult::Cancel => {} + DialogResult::Open(selected_paths) => { + let mut archive_paths = None; + if let Some(file_dialog) = &self.file_dialog_opt { + let window = self.windows.remove(&file_dialog.window_id()); + if let Some(WindowKind::FileDialog(paths)) = window { + archive_paths = paths; + } + } + if let Some(archive_paths) = archive_paths { + if !selected_paths.is_empty() { + self.operation(Operation::Extract { + paths: archive_paths, + to: selected_paths[0].clone(), + password: None, + }); + } + } + } + } + self.file_dialog_opt = None; + } + Message::FileDialogMessage(dialog_message) => { + if let Some(dialog) = &mut self.file_dialog_opt { + return dialog.update(dialog_message); + } + } Message::Key(modifiers, key, text) => { let entity = self.tab_model.active(); for (key_bind, action) in self.key_binds.iter() { @@ -2935,7 +2962,7 @@ impl Application for App { self.dialog_pages.push_back(match err.kind { OperationErrorType::Generic(_) => DialogPage::FailedOperation(id), OperationErrorType::PasswordRequired => DialogPage::ExtractPassword { - id: id, + id, password: String::from(""), }, }); @@ -4121,30 +4148,6 @@ impl Application for App { .secondary_action( widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel), ), - DialogPage::ExtractTo { - paths, - to, - password, - } => widget::dialog() - .title(fl!("extract-to")) - .body(fl!("extract-to-prompt")) - .control( - widget::text_input("Enter the path to extract to", to.to_string_lossy()) - .on_input(move |to| { - Message::DialogUpdate(DialogPage::ExtractTo { - paths: paths.clone(), - to: PathBuf::from(to), - password: password.clone(), - }) - }), - ) - .primary_action( - widget::button::suggested(fl!("extract-here")) - .on_press(Message::DialogComplete), - ) - .secondary_action( - widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel), - ), DialogPage::FailedOperation(id) => { //TODO: try next dialog page (making sure index is used by Dialog messages)? let (operation, _, err) = self.failed_operations.get(id)?; @@ -4935,6 +4938,10 @@ impl Application for App { Some(WindowKind::Preview(entity_opt, kind)) => self .preview(entity_opt, kind, false) .map(|x| Message::TabMessage(*entity_opt, x)), + Some(WindowKind::FileDialog(..)) => match &self.file_dialog_opt { + Some(dialog) => return dialog.view(id), + None => widget::text("Unknown window ID").into(), + }, None => { //TODO: distinct views per monitor in desktop mode return self.view_main().map(|message| match message { From 162768af8ff9b4ca9c57be376176db1c1fdfac82 Mon Sep 17 00:00:00 2001 From: Jason Rodney Hansen Date: Sun, 23 Mar 2025 14:30:22 -0600 Subject: [PATCH 2/3] Fix toasts for Extract and Compress --- src/app.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/app.rs b/src/app.rs index 160d572..8e9fcec 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2914,6 +2914,12 @@ impl Application for App { ) .map(cosmic::Action::App), ); + } else { + commands.push( + self.toasts + .push(widget::toaster::Toast::new(description)) + .map(cosmic::Action::App), + ); } } From dfa857b1e53504547e0b5357819beda59c35bc3f Mon Sep 17 00:00:00 2001 From: Jason Rodney Hansen Date: Sun, 23 Mar 2025 15:28:18 -0600 Subject: [PATCH 3/3] Set title and accept button label for extract dialog --- i18n/en/cosmic_files.ftl | 2 +- i18n/hu/cosmic_files.ftl | 3 +-- i18n/nl/cosmic_files.ftl | 1 - src/app.rs | 6 ++++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/i18n/en/cosmic_files.ftl b/i18n/en/cosmic_files.ftl index 30442c0..86b99de 100644 --- a/i18n/en/cosmic_files.ftl +++ b/i18n/en/cosmic_files.ftl @@ -43,7 +43,7 @@ create-archive = Create archive ## Extract Dialog extract-password-required = Password required extract-to = Extract To... -extract-to-prompt = Input a location to extract the archive to. +extract-to-title = Extract to folder ## Empty Trash Dialog empty-trash = Empty trash diff --git a/i18n/hu/cosmic_files.ftl b/i18n/hu/cosmic_files.ftl index 637f7d0..31f200a 100644 --- a/i18n/hu/cosmic_files.ftl +++ b/i18n/hu/cosmic_files.ftl @@ -43,7 +43,6 @@ create-archive = Tömörített fájl létrehozása ## Extract Dialog extract-password-required = Jelszó szükséges extract-to = Kibontás ide... -extract-to-prompt = Adja meg a helyet, ahová ki szeretné bontani a tömörített fájlt. ## Empty Trash Dialog empty-trash = Kuka ürítése @@ -321,4 +320,4 @@ sort-z-a = Z-A sort-newest-first = Legújabb előre sort-oldest-first = Legrégibb előre sort-smallest-to-largest = Legkisebbtől a legnagyobbig -sort-largest-to-smallest = Legnagyobbtól a legkisebbig \ No newline at end of file +sort-largest-to-smallest = Legnagyobbtól a legkisebbig diff --git a/i18n/nl/cosmic_files.ftl b/i18n/nl/cosmic_files.ftl index 4869a4c..f561c2c 100644 --- a/i18n/nl/cosmic_files.ftl +++ b/i18n/nl/cosmic_files.ftl @@ -43,7 +43,6 @@ create-archive = Maak een archiefbestand ## Extract Dialog extract-password-required = Wachtwoord vereist extract-to = Uitpakken naar... -extract-to-prompt = Voer een locatie in om dit archief naar uit te pakken. ## Empty Trash Dialog empty-trash = Prullenbak legen? diff --git a/src/app.rs b/src/app.rs index 8e9fcec..cb373cf 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2395,16 +2395,18 @@ impl Application for App { .and_then(|first| first.parent()) .map(|parent| parent.to_path_buf()) { - let (dialog, command) = Dialog::new( + let (mut dialog, dialog_task) = Dialog::new( DialogKind::OpenFolder, Some(destination), Message::FileDialogMessage, Message::ExtractToResult, ); + let set_title_task = dialog.set_title(fl!("extract-to-title")); + dialog.set_accept_label(fl!("extract-here")); self.windows .insert(dialog.window_id(), WindowKind::FileDialog(Some(paths))); self.file_dialog_opt = Some(dialog); - return command; + return Task::batch([set_title_task, dialog_task]); }; } Message::ExtractToResult(result) => {