feat(tab): allow entering of network uri as path
This commit is contained in:
parent
e053db3bf9
commit
66733b7fda
3 changed files with 159 additions and 94 deletions
|
|
@ -16,6 +16,24 @@ use crate::{
|
|||
|
||||
const TARGET_URI_ATTRIBUTE: &str = "standard::target-uri";
|
||||
|
||||
fn resolve_uri(uri: &str) -> (String, gio::File) {
|
||||
let file = gio::File::for_uri(uri);
|
||||
// Resolve the target-uri if it exists
|
||||
if let Ok(file_info) = file.query_info(
|
||||
TARGET_URI_ATTRIBUTE,
|
||||
gio::FileQueryInfoFlags::NONE,
|
||||
gio::Cancellable::NONE,
|
||||
) {
|
||||
if let Some(resolved_uri) = file_info.attribute_as_string(TARGET_URI_ATTRIBUTE) {
|
||||
let resolved_uri = String::from(resolved_uri);
|
||||
let file = gio::File::for_uri(&resolved_uri);
|
||||
return (resolved_uri, file);
|
||||
}
|
||||
}
|
||||
|
||||
(uri.to_string(), file)
|
||||
}
|
||||
|
||||
fn gio_icon_to_path(icon: &gio::Icon, size: u16) -> Option<PathBuf> {
|
||||
if let Some(themed_icon) = icon.downcast_ref::<gio::ThemedIcon>() {
|
||||
for name in themed_icon.names() {
|
||||
|
|
@ -83,19 +101,8 @@ fn items(monitor: &gio::VolumeMonitor, sizes: IconSizes) -> MounterItems {
|
|||
}
|
||||
|
||||
fn network_scan(uri: &str, sizes: IconSizes) -> Result<Vec<tab::Item>, String> {
|
||||
let mut file = gio::File::for_uri(uri);
|
||||
let force_dir = uri.starts_with("network:///");
|
||||
|
||||
// Resolve the target-uri if it exists
|
||||
if let Ok(file_info) = file.query_info(
|
||||
TARGET_URI_ATTRIBUTE,
|
||||
gio::FileQueryInfoFlags::NONE,
|
||||
gio::Cancellable::NONE,
|
||||
) {
|
||||
if let Some(resolved_uri) = file_info.attribute_as_string(TARGET_URI_ATTRIBUTE) {
|
||||
file = gio::File::for_uri(resolved_uri.as_str());
|
||||
}
|
||||
}
|
||||
let (_, file) = resolve_uri(uri);
|
||||
|
||||
// Read .hidden file if present
|
||||
let hidden_files: Box<[String]> = if let Some(path) = file.path() {
|
||||
|
|
@ -210,6 +217,17 @@ fn network_scan(uri: &str, sizes: IconSizes) -> Result<Vec<tab::Item>, String> {
|
|||
Ok(items)
|
||||
}
|
||||
|
||||
fn dir_info(uri: &str) -> Result<(String, String), glib::Error> {
|
||||
let (resolved_uri, file) = resolve_uri(uri);
|
||||
let info = file.query_info(
|
||||
gio::FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
|
||||
gio::FileQueryInfoFlags::NONE,
|
||||
gio::Cancellable::NONE,
|
||||
)?;
|
||||
|
||||
Ok((resolved_uri, info.display_name().into()))
|
||||
}
|
||||
|
||||
fn mount_op(uri: String, event_tx: mpsc::UnboundedSender<Event>) -> gio::MountOperation {
|
||||
let mount_op = gio::MountOperation::new();
|
||||
mount_op.connect_ask_password(
|
||||
|
|
@ -270,6 +288,7 @@ enum Cmd {
|
|||
IconSizes,
|
||||
mpsc::Sender<Result<Vec<tab::Item>, String>>,
|
||||
),
|
||||
DirInfo(String, mpsc::Sender<Result<(String, String), glib::Error>>),
|
||||
Unmount(MounterItem),
|
||||
}
|
||||
|
||||
|
|
@ -494,38 +513,27 @@ impl Gvfs {
|
|||
}
|
||||
);
|
||||
}
|
||||
Cmd::NetworkScan(mut uri, sizes, items_tx) => {
|
||||
let original_uri = uri.clone();
|
||||
let mut file = gio::File::for_uri(&uri);
|
||||
if let Ok(file_info) = file.query_info(
|
||||
TARGET_URI_ATTRIBUTE,
|
||||
gio::FileQueryInfoFlags::NONE,
|
||||
gio::Cancellable::NONE,
|
||||
) {
|
||||
if let Some(resolved_uri) = file_info.attribute_as_string(TARGET_URI_ATTRIBUTE) {
|
||||
uri = resolved_uri.into();
|
||||
file = gio::File::for_uri(&uri);
|
||||
}
|
||||
}
|
||||
Cmd::NetworkScan(uri, sizes, items_tx) => {
|
||||
let (resolved_uri, file) = resolve_uri(&uri);
|
||||
|
||||
let needs_mount = uri != "network:///" && match file.find_enclosing_mount(gio::Cancellable::NONE) {
|
||||
let needs_mount = resolved_uri != "network:///" && match file.find_enclosing_mount(gio::Cancellable::NONE) {
|
||||
Ok(_) => false,
|
||||
Err(err) => matches!(err.kind::<gio::IOErrorEnum>(), Some(gio::IOErrorEnum::NotMounted))
|
||||
};
|
||||
|
||||
if needs_mount {
|
||||
let mount_op = mount_op(uri.clone(), event_tx.clone());
|
||||
let mount_op = mount_op(resolved_uri.clone(), event_tx.clone());
|
||||
let event_tx = event_tx.clone();
|
||||
file.mount_enclosing_volume(
|
||||
gio::MountMountFlags::empty(),
|
||||
Some(&mount_op),
|
||||
gio::Cancellable::NONE,
|
||||
move |res| {
|
||||
log::info!("network scan mounted {uri}: result {res:?}");
|
||||
log::info!("network scan mounted {resolved_uri}: result {res:?}");
|
||||
// FIXME sometimes a uri can be mounted and then not recognized as mounted...
|
||||
// seems to be related to uri with a path
|
||||
items_tx.blocking_send(network_scan(&original_uri, sizes)).unwrap();
|
||||
event_tx.send(Event::NetworkResult(uri, match res {
|
||||
items_tx.blocking_send(network_scan(&uri, sizes)).unwrap();
|
||||
event_tx.send(Event::NetworkResult(resolved_uri, match res {
|
||||
Ok(()) => {
|
||||
Ok(true)
|
||||
},
|
||||
|
|
@ -537,9 +545,12 @@ impl Gvfs {
|
|||
}
|
||||
);
|
||||
} else {
|
||||
items_tx.send(network_scan(&original_uri, sizes)).await.unwrap();
|
||||
items_tx.send(network_scan(&uri, sizes)).await.unwrap();
|
||||
}
|
||||
}
|
||||
Cmd::DirInfo(uri, result_tx) => {
|
||||
result_tx.send(dir_info(&uri)).await.unwrap();
|
||||
}
|
||||
Cmd::Unmount(mounter_item) => {
|
||||
let MounterItem::Gvfs(item) = mounter_item else { continue };
|
||||
let ItemKind::Mount = item.kind else { continue };
|
||||
|
|
@ -640,6 +651,14 @@ impl Mounter for Gvfs {
|
|||
items_rx.blocking_recv()
|
||||
}
|
||||
|
||||
fn dir_info(&self, uri: &str) -> Option<(String, String)> {
|
||||
let (result_tx, mut result_rx) = mpsc::channel(1);
|
||||
self.command_tx
|
||||
.send(Cmd::DirInfo(uri.to_string(), result_tx))
|
||||
.unwrap();
|
||||
result_rx.blocking_recv().and_then(|res| res.ok())
|
||||
}
|
||||
|
||||
fn unmount(&self, item: MounterItem) -> Task<()> {
|
||||
let command_tx = self.command_tx.clone();
|
||||
Task::future(async move {
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ pub trait Mounter: Send + Sync {
|
|||
fn mount(&self, item: MounterItem) -> Task<()>;
|
||||
fn network_drive(&self, uri: String) -> Task<()>;
|
||||
fn network_scan(&self, uri: &str, sizes: IconSizes) -> Option<Result<Vec<tab::Item>, String>>;
|
||||
fn dir_info(&self, uri: &str) -> Option<(String, String)>;
|
||||
fn unmount(&self, item: MounterItem) -> Task<()>;
|
||||
fn subscription(&self) -> Subscription<MounterMessage>;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue