diff --git a/i18n/en/cosmic_files.ftl b/i18n/en/cosmic_files.ftl index b5f183b..b18f5d9 100644 --- a/i18n/en/cosmic_files.ftl +++ b/i18n/en/cosmic_files.ftl @@ -35,6 +35,9 @@ create-archive = Create archive empty-trash = Empty trash empty-trash-warning = Are you sure you want to permanently delete all the items in Trash? +## Mount Error Dialog +mount-error = Unable to access drive + ## New File/Folder Dialog create-new-file = Create new file create-new-folder = Create new folder diff --git a/src/app.rs b/src/app.rs index d4c1c82..f1ab56b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -274,6 +274,7 @@ pub enum Message { Modifiers(Modifiers), MoveToTrash(Option), MounterItems(MounterKey, MounterItems), + MountResult(MounterKey, MounterItem, Result), NavBarClose(Entity), NavBarContext(Entity), NavMenuAction(NavMenuAction), @@ -405,6 +406,11 @@ pub enum DialogPage { }, EmptyTrash, FailedOperation(u64), + MountError { + mounter_key: MounterKey, + item: MounterItem, + error: String, + }, NetworkAuth { mounter_key: MounterKey, uri: String, @@ -1630,6 +1636,15 @@ impl Application for App { DialogPage::FailedOperation(id) => { log::warn!("TODO: retry operation {}", id); } + DialogPage::MountError { + mounter_key, + item, + error: _, + } => { + if let Some(mounter) = MOUNTERS.get(&mounter_key) { + return mounter.mount(item).map(|_| message::none()); + } + } DialogPage::NetworkAuth { mounter_key: _, uri: _, @@ -1834,6 +1849,22 @@ impl Application for App { return Command::batch(commands); } + Message::MountResult(mounter_key, item, res) => match res { + Ok(true) => { + log::info!("connected to {:?}", item); + } + Ok(false) => { + log::info!("cancelled connection to {:?}", item); + } + Err(error) => { + log::warn!("failed to connect to {:?}: {}", item, error); + self.dialog_pages.push_back(DialogPage::MountError { + mounter_key, + item, + error, + }); + } + }, Message::NetworkAuth(mounter_key, uri, auth, auth_tx) => { self.dialog_pages.push_back(DialogPage::NetworkAuth { mounter_key, @@ -3198,6 +3229,19 @@ impl Application for App { widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel), ) } + DialogPage::MountError { + mounter_key: _, + item: _, + error, + } => widget::dialog(fl!("mount-error")) + .body(error) + .icon(widget::icon::from_name("dialog-error").size(64)) + .primary_action( + widget::button::standard(fl!("try-again")).on_press(Message::DialogComplete), + ) + .secondary_action( + widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel), + ), DialogPage::NetworkAuth { mounter_key, uri, @@ -3988,6 +4032,7 @@ impl Application for App { subscriptions.push(mounter.subscription().map(move |mounter_message| { match mounter_message { MounterMessage::Items(items) => Message::MounterItems(key, items), + MounterMessage::MountResult(item, res) => Message::MountResult(key, item, res), MounterMessage::NetworkAuth(uri, auth, auth_tx) => { Message::NetworkAuth(key, uri, auth, auth_tx) } diff --git a/src/mounter/gvfs.rs b/src/mounter/gvfs.rs index 9bbbd19..03bf5ef 100644 --- a/src/mounter/gvfs.rs +++ b/src/mounter/gvfs.rs @@ -212,6 +212,7 @@ enum Cmd { enum Event { Changed, Items(MounterItems), + MountResult(MounterItem, Result), NetworkAuth(String, MounterAuth, mpsc::Sender), NetworkResult(String, Result), } @@ -324,7 +325,7 @@ impl Gvfs { event_tx.send(Event::Items(items(&monitor, IconSizes::default()))).unwrap(); } Cmd::Mount(mounter_item) => { - let MounterItem::Gvfs(item) = mounter_item else { continue }; + let MounterItem::Gvfs(ref item) = mounter_item else { continue }; let ItemKind::Volume = item.kind else { continue }; for (i, volume) in monitor.volumes().into_iter().enumerate() { if i != item.index { @@ -338,14 +339,24 @@ impl Gvfs { } log::info!("mount {}", name); + //TODO: do not use name as a URI for mount_op + let mount_op = mount_op(name.to_string(), event_tx.clone()); + let event_tx = event_tx.clone(); + let mounter_item = mounter_item.clone(); VolumeExt::mount( &volume, gio::MountMountFlags::NONE, - //TODO: gio::MountOperation needed for network shares with auth - gio::MountOperation::NONE, + Some(&mount_op), gio::Cancellable::NONE, - move |result| { - log::info!("mount {}: result {:?}", name, result); + move |res| { + log::info!("mount {}: result {:?}", name, res); + event_tx.send(Event::MountResult(mounter_item, match res { + Ok(()) => Ok(true), + Err(err) => match err.kind::() { + Some(gio::IOErrorEnum::FailedHandled) => Ok(false), + _ => Err(format!("{}", err)) + } + })).unwrap(); }, ); } @@ -355,7 +366,7 @@ impl Gvfs { let mount_op = mount_op(uri.clone(), event_tx.clone()); let event_tx = event_tx.clone(); file.mount_enclosing_volume( - gio::MountMountFlags::empty(), + gio::MountMountFlags::NONE, Some(&mount_op), gio::Cancellable::NONE, move |res| { @@ -499,6 +510,10 @@ impl Mounter for Gvfs { match event { Event::Changed => command_tx.send(Cmd::Rescan).unwrap(), Event::Items(items) => output.send(MounterMessage::Items(items)).await.unwrap(), + Event::MountResult(item, res) => output + .send(MounterMessage::MountResult(item, res)) + .await + .unwrap(), Event::NetworkAuth(uri, auth, auth_tx) => output .send(MounterMessage::NetworkAuth(uri, auth, auth_tx)) .await diff --git a/src/mounter/mod.rs b/src/mounter/mod.rs index a109852..17a6b34 100644 --- a/src/mounter/mod.rs +++ b/src/mounter/mod.rs @@ -85,6 +85,7 @@ pub type MounterItems = Vec; #[derive(Clone, Debug)] pub enum MounterMessage { Items(MounterItems), + MountResult(MounterItem, Result), NetworkAuth(String, MounterAuth, mpsc::Sender), NetworkResult(String, Result), }