Support mounting encrypted drive, fixes #144
This commit is contained in:
parent
12d47c8c80
commit
583d3dfa0d
4 changed files with 70 additions and 6 deletions
|
|
@ -35,6 +35,9 @@ create-archive = Create archive
|
||||||
empty-trash = Empty trash
|
empty-trash = Empty trash
|
||||||
empty-trash-warning = Are you sure you want to permanently delete all the items in 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
|
## New File/Folder Dialog
|
||||||
create-new-file = Create new file
|
create-new-file = Create new file
|
||||||
create-new-folder = Create new folder
|
create-new-folder = Create new folder
|
||||||
|
|
|
||||||
45
src/app.rs
45
src/app.rs
|
|
@ -274,6 +274,7 @@ pub enum Message {
|
||||||
Modifiers(Modifiers),
|
Modifiers(Modifiers),
|
||||||
MoveToTrash(Option<Entity>),
|
MoveToTrash(Option<Entity>),
|
||||||
MounterItems(MounterKey, MounterItems),
|
MounterItems(MounterKey, MounterItems),
|
||||||
|
MountResult(MounterKey, MounterItem, Result<bool, String>),
|
||||||
NavBarClose(Entity),
|
NavBarClose(Entity),
|
||||||
NavBarContext(Entity),
|
NavBarContext(Entity),
|
||||||
NavMenuAction(NavMenuAction),
|
NavMenuAction(NavMenuAction),
|
||||||
|
|
@ -405,6 +406,11 @@ pub enum DialogPage {
|
||||||
},
|
},
|
||||||
EmptyTrash,
|
EmptyTrash,
|
||||||
FailedOperation(u64),
|
FailedOperation(u64),
|
||||||
|
MountError {
|
||||||
|
mounter_key: MounterKey,
|
||||||
|
item: MounterItem,
|
||||||
|
error: String,
|
||||||
|
},
|
||||||
NetworkAuth {
|
NetworkAuth {
|
||||||
mounter_key: MounterKey,
|
mounter_key: MounterKey,
|
||||||
uri: String,
|
uri: String,
|
||||||
|
|
@ -1630,6 +1636,15 @@ impl Application for App {
|
||||||
DialogPage::FailedOperation(id) => {
|
DialogPage::FailedOperation(id) => {
|
||||||
log::warn!("TODO: retry operation {}", 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 {
|
DialogPage::NetworkAuth {
|
||||||
mounter_key: _,
|
mounter_key: _,
|
||||||
uri: _,
|
uri: _,
|
||||||
|
|
@ -1834,6 +1849,22 @@ impl Application for App {
|
||||||
|
|
||||||
return Command::batch(commands);
|
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) => {
|
Message::NetworkAuth(mounter_key, uri, auth, auth_tx) => {
|
||||||
self.dialog_pages.push_back(DialogPage::NetworkAuth {
|
self.dialog_pages.push_back(DialogPage::NetworkAuth {
|
||||||
mounter_key,
|
mounter_key,
|
||||||
|
|
@ -3198,6 +3229,19 @@ impl Application for App {
|
||||||
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
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 {
|
DialogPage::NetworkAuth {
|
||||||
mounter_key,
|
mounter_key,
|
||||||
uri,
|
uri,
|
||||||
|
|
@ -3988,6 +4032,7 @@ impl Application for App {
|
||||||
subscriptions.push(mounter.subscription().map(move |mounter_message| {
|
subscriptions.push(mounter.subscription().map(move |mounter_message| {
|
||||||
match mounter_message {
|
match mounter_message {
|
||||||
MounterMessage::Items(items) => Message::MounterItems(key, items),
|
MounterMessage::Items(items) => Message::MounterItems(key, items),
|
||||||
|
MounterMessage::MountResult(item, res) => Message::MountResult(key, item, res),
|
||||||
MounterMessage::NetworkAuth(uri, auth, auth_tx) => {
|
MounterMessage::NetworkAuth(uri, auth, auth_tx) => {
|
||||||
Message::NetworkAuth(key, uri, auth, auth_tx)
|
Message::NetworkAuth(key, uri, auth, auth_tx)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,7 @@ enum Cmd {
|
||||||
enum Event {
|
enum Event {
|
||||||
Changed,
|
Changed,
|
||||||
Items(MounterItems),
|
Items(MounterItems),
|
||||||
|
MountResult(MounterItem, Result<bool, String>),
|
||||||
NetworkAuth(String, MounterAuth, mpsc::Sender<MounterAuth>),
|
NetworkAuth(String, MounterAuth, mpsc::Sender<MounterAuth>),
|
||||||
NetworkResult(String, Result<bool, String>),
|
NetworkResult(String, Result<bool, String>),
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +325,7 @@ impl Gvfs {
|
||||||
event_tx.send(Event::Items(items(&monitor, IconSizes::default()))).unwrap();
|
event_tx.send(Event::Items(items(&monitor, IconSizes::default()))).unwrap();
|
||||||
}
|
}
|
||||||
Cmd::Mount(mounter_item) => {
|
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 };
|
let ItemKind::Volume = item.kind else { continue };
|
||||||
for (i, volume) in monitor.volumes().into_iter().enumerate() {
|
for (i, volume) in monitor.volumes().into_iter().enumerate() {
|
||||||
if i != item.index {
|
if i != item.index {
|
||||||
|
|
@ -338,14 +339,24 @@ impl Gvfs {
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("mount {}", name);
|
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(
|
VolumeExt::mount(
|
||||||
&volume,
|
&volume,
|
||||||
gio::MountMountFlags::NONE,
|
gio::MountMountFlags::NONE,
|
||||||
//TODO: gio::MountOperation needed for network shares with auth
|
Some(&mount_op),
|
||||||
gio::MountOperation::NONE,
|
|
||||||
gio::Cancellable::NONE,
|
gio::Cancellable::NONE,
|
||||||
move |result| {
|
move |res| {
|
||||||
log::info!("mount {}: result {:?}", name, result);
|
log::info!("mount {}: result {:?}", name, res);
|
||||||
|
event_tx.send(Event::MountResult(mounter_item, match res {
|
||||||
|
Ok(()) => Ok(true),
|
||||||
|
Err(err) => match err.kind::<gio::IOErrorEnum>() {
|
||||||
|
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 mount_op = mount_op(uri.clone(), event_tx.clone());
|
||||||
let event_tx = event_tx.clone();
|
let event_tx = event_tx.clone();
|
||||||
file.mount_enclosing_volume(
|
file.mount_enclosing_volume(
|
||||||
gio::MountMountFlags::empty(),
|
gio::MountMountFlags::NONE,
|
||||||
Some(&mount_op),
|
Some(&mount_op),
|
||||||
gio::Cancellable::NONE,
|
gio::Cancellable::NONE,
|
||||||
move |res| {
|
move |res| {
|
||||||
|
|
@ -499,6 +510,10 @@ impl Mounter for Gvfs {
|
||||||
match event {
|
match event {
|
||||||
Event::Changed => command_tx.send(Cmd::Rescan).unwrap(),
|
Event::Changed => command_tx.send(Cmd::Rescan).unwrap(),
|
||||||
Event::Items(items) => output.send(MounterMessage::Items(items)).await.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
|
Event::NetworkAuth(uri, auth, auth_tx) => output
|
||||||
.send(MounterMessage::NetworkAuth(uri, auth, auth_tx))
|
.send(MounterMessage::NetworkAuth(uri, auth, auth_tx))
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ pub type MounterItems = Vec<MounterItem>;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum MounterMessage {
|
pub enum MounterMessage {
|
||||||
Items(MounterItems),
|
Items(MounterItems),
|
||||||
|
MountResult(MounterItem, Result<bool, String>),
|
||||||
NetworkAuth(String, MounterAuth, mpsc::Sender<MounterAuth>),
|
NetworkAuth(String, MounterAuth, mpsc::Sender<MounterAuth>),
|
||||||
NetworkResult(String, Result<bool, String>),
|
NetworkResult(String, Result<bool, String>),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue