feat: handle opening network location in new window
This commit is contained in:
parent
c7e9828d7b
commit
08367c9ea6
5 changed files with 43 additions and 65 deletions
75
src/app.rs
75
src/app.rs
|
|
@ -105,6 +105,7 @@ pub struct Flags {
|
||||||
pub state: State,
|
pub state: State,
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
pub locations: Vec<Location>,
|
pub locations: Vec<Location>,
|
||||||
|
pub uris: Vec<url::Url>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
|
@ -893,7 +894,6 @@ impl App {
|
||||||
) -> (Entity, Task<Message>) {
|
) -> (Entity, Task<Message>) {
|
||||||
#[cfg(feature = "gvfs")]
|
#[cfg(feature = "gvfs")]
|
||||||
if let Location::Network(ref uri, ref name, Some(ref path)) = location {
|
if let Location::Network(ref uri, ref name, Some(ref path)) = location {
|
||||||
dbg!(path, self.mounter_items.len());
|
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
|
|
||||||
if let Some(key) = self
|
if let Some(key) = self
|
||||||
|
|
@ -904,30 +904,18 @@ impl App {
|
||||||
found |= item.path().is_some_and(|p| path.starts_with(p))
|
found |= item.path().is_some_and(|p| path.starts_with(p))
|
||||||
|| item.name() == *name
|
|| item.name() == *name
|
||||||
|| item.uri() == *uri;
|
|| item.uri() == *uri;
|
||||||
dbg!(
|
|
||||||
item.is_mounted(),
|
|
||||||
item.path(),
|
|
||||||
path,
|
|
||||||
name,
|
|
||||||
item.name(),
|
|
||||||
item.uri(),
|
|
||||||
uri
|
|
||||||
);
|
|
||||||
(!item.is_mounted() && found).then(|| *k)
|
(!item.is_mounted() && found).then(|| *k)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.or(if found {
|
.or(if found {
|
||||||
dbg!("found so skip...");
|
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
dbg!("not found...");
|
|
||||||
// TODO do we need to choose the correct mounter?
|
// TODO do we need to choose the correct mounter?
|
||||||
self.mounter_items.iter().map(|(k, _)| *k).next()
|
self.mounter_items.iter().map(|(k, _)| *k).next()
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
if let Some(mounter) = MOUNTERS.get(&key) {
|
if let Some(mounter) = MOUNTERS.get(&key) {
|
||||||
let location = location.clone();
|
let location = location.clone();
|
||||||
dbg!(&location);
|
|
||||||
return (
|
return (
|
||||||
Entity::null(),
|
Entity::null(),
|
||||||
mounter.network_drive(uri.clone()).map(move |_| {
|
mounter.network_drive(uri.clone()).map(move |_| {
|
||||||
|
|
@ -937,12 +925,9 @@ impl App {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
dbg!("huh...");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg!(&location);
|
|
||||||
let mut tab = Tab::new(
|
let mut tab = Tab::new(
|
||||||
location.clone(),
|
location.clone(),
|
||||||
self.config.tab,
|
self.config.tab,
|
||||||
|
|
@ -1119,7 +1104,6 @@ impl App {
|
||||||
location: Location,
|
location: Location,
|
||||||
selection_paths: Option<Vec<PathBuf>>,
|
selection_paths: Option<Vec<PathBuf>>,
|
||||||
) -> Task<Message> {
|
) -> Task<Message> {
|
||||||
dbg!("rescan", &location);
|
|
||||||
log::info!("rescan_tab {entity:?} {location:?} {selection_paths:?}");
|
log::info!("rescan_tab {entity:?} {location:?} {selection_paths:?}");
|
||||||
let icon_sizes = self.config.tab.icon_sizes;
|
let icon_sizes = self.config.tab.icon_sizes;
|
||||||
let mounter_items = self.mounter_items.clone();
|
let mounter_items = self.mounter_items.clone();
|
||||||
|
|
@ -2101,6 +2085,17 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
commands.push(app.open_tab(location, true, None));
|
commands.push(app.open_tab(location, true, None));
|
||||||
}
|
}
|
||||||
|
for location in flags.uris {
|
||||||
|
if let Some(e) = app.nav_model.iter().find(|e| {
|
||||||
|
app.nav_model.data::<Location>(*e).is_some_and(
|
||||||
|
|l| matches!(l, Location::Network(ref uri, ..) if *uri == location.to_string()),
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
commands.push(cosmic::task::message(cosmic::Action::App(
|
||||||
|
Message::NetworkDriveOpenEntityAfterMount { entity: e },
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if app.tab_model.iter().next().is_none() {
|
if app.tab_model.iter().next().is_none() {
|
||||||
if let Ok(current_dir) = env::current_dir() {
|
if let Ok(current_dir) = env::current_dir() {
|
||||||
|
|
@ -2226,14 +2221,11 @@ impl Application for App {
|
||||||
fn on_nav_select(&mut self, entity: Entity) -> Task<Self::Message> {
|
fn on_nav_select(&mut self, entity: Entity) -> Task<Self::Message> {
|
||||||
self.nav_model.activate(entity);
|
self.nav_model.activate(entity);
|
||||||
if let Some(location) = self.nav_model.data::<Location>(entity) {
|
if let Some(location) = self.nav_model.data::<Location>(entity) {
|
||||||
dbg!(&location);
|
|
||||||
|
|
||||||
let should_open = match location {
|
let should_open = match location {
|
||||||
#[cfg(feature = "gvfs")]
|
#[cfg(feature = "gvfs")]
|
||||||
Location::Network(uri, name, Some(path))
|
Location::Network(uri, name, Some(path))
|
||||||
if !path.try_exists().unwrap_or_default() =>
|
if !path.try_exists().unwrap_or_default() =>
|
||||||
{
|
{
|
||||||
dbg!(&location, path, self.mounter_items.len(), uri, path);
|
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
|
|
||||||
if let Some(key) = self
|
if let Some(key) = self
|
||||||
|
|
@ -2244,7 +2236,6 @@ impl Application for App {
|
||||||
found |= item.path().is_some_and(|p| path.starts_with(&p))
|
found |= item.path().is_some_and(|p| path.starts_with(&p))
|
||||||
|| item.name() == *name
|
|| item.name() == *name
|
||||||
|| item.uri() == *uri;
|
|| item.uri() == *uri;
|
||||||
dbg!(item.is_mounted(), item.path());
|
|
||||||
(!item.is_mounted() && found).then(|| *k)
|
(!item.is_mounted() && found).then(|| *k)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
@ -2256,9 +2247,6 @@ impl Application for App {
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
if let Some(mounter) = MOUNTERS.get(&key) {
|
if let Some(mounter) = MOUNTERS.get(&key) {
|
||||||
dbg!(&location);
|
|
||||||
// TODO can we detect an error and handle failure?
|
|
||||||
let location = location.clone();
|
|
||||||
return mounter.network_drive(uri.clone()).map(move |_| {
|
return mounter.network_drive(uri.clone()).map(move |_| {
|
||||||
cosmic::Action::App(Message::NetworkDriveOpenEntityAfterMount {
|
cosmic::Action::App(Message::NetworkDriveOpenEntityAfterMount {
|
||||||
entity,
|
entity,
|
||||||
|
|
@ -2299,7 +2287,6 @@ impl Application for App {
|
||||||
_ => true,
|
_ => true,
|
||||||
};
|
};
|
||||||
|
|
||||||
dbg!(should_open);
|
|
||||||
if should_open {
|
if should_open {
|
||||||
let message = Message::TabMessage(None, tab::Message::Location(location.clone()));
|
let message = Message::TabMessage(None, tab::Message::Location(location.clone()));
|
||||||
return self.update(message);
|
return self.update(message);
|
||||||
|
|
@ -2422,15 +2409,12 @@ impl Application for App {
|
||||||
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
||||||
|
|
||||||
for path in self.selected_paths(entity_opt) {
|
for path in self.selected_paths(entity_opt) {
|
||||||
dbg!(&path);
|
|
||||||
let is_network = self.tab_model.data::<Tab>(entity).and_then(|tab| {
|
let is_network = self.tab_model.data::<Tab>(entity).and_then(|tab| {
|
||||||
let in_current_tab =
|
let in_current_tab = tab
|
||||||
tab.location.path_opt().zip(path.parent()).is_some_and(
|
.location
|
||||||
|(t_path, parent)| {
|
.path_opt()
|
||||||
dbg!(&parent, &t_path);
|
.zip(path.parent())
|
||||||
parent == t_path
|
.is_some_and(|(t_path, parent)| parent == t_path);
|
||||||
},
|
|
||||||
);
|
|
||||||
let tab = if in_current_tab {
|
let tab = if in_current_tab {
|
||||||
self.tab_model
|
self.tab_model
|
||||||
.data::<Tab>(self.tab_model.active())
|
.data::<Tab>(self.tab_model.active())
|
||||||
|
|
@ -2438,15 +2422,23 @@ impl Application for App {
|
||||||
} else {
|
} else {
|
||||||
tab
|
tab
|
||||||
};
|
};
|
||||||
dbg!(in_current_tab, &tab.location);
|
|
||||||
let name = Location::Path(path.clone()).title();
|
let name = Location::Path(path.clone()).title();
|
||||||
if let Location::Network(uri, _, _) = tab.location.clone() {
|
if let Location::Network(uri, _, _) = tab
|
||||||
|
.items_opt
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|items| items.iter().find(|i| i.path_opt() == Some(&path)))
|
||||||
|
.unwrap()
|
||||||
|
.location_opt
|
||||||
|
.clone()
|
||||||
|
.unwrap()
|
||||||
|
.clone()
|
||||||
|
{
|
||||||
Some((uri, name, path.clone()))
|
Some((uri, name, path.clone()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dbg!(&is_network);
|
|
||||||
let name = Location::Path(path.clone()).title();
|
let name = Location::Path(path.clone()).title();
|
||||||
let favorite = if let Some((uri, _, _)) = is_network.clone() {
|
let favorite = if let Some((uri, _, _)) = is_network.clone() {
|
||||||
Favorite::Network { uri, name, path }
|
Favorite::Network { uri, name, path }
|
||||||
|
|
@ -2455,7 +2447,6 @@ impl Application for App {
|
||||||
};
|
};
|
||||||
if !favorites.iter().any(|f| f == &favorite) {
|
if !favorites.iter().any(|f| f == &favorite) {
|
||||||
favorites.push(favorite);
|
favorites.push(favorite);
|
||||||
dbg!(&favorites);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
config_set!(favorites, favorites);
|
config_set!(favorites, favorites);
|
||||||
|
|
@ -3147,7 +3138,6 @@ impl Application for App {
|
||||||
Message::OpenInNewTab(entity_opt) => {
|
Message::OpenInNewTab(entity_opt) => {
|
||||||
return Task::batch(self.selected_paths(entity_opt).into_iter().filter_map(
|
return Task::batch(self.selected_paths(entity_opt).into_iter().filter_map(
|
||||||
|path| {
|
|path| {
|
||||||
dbg!(&path);
|
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
Some(self.open_tab(Location::Path(path), false, None))
|
Some(self.open_tab(Location::Path(path), false, None))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -3686,7 +3676,6 @@ impl Application for App {
|
||||||
for tab_command in tab_commands {
|
for tab_command in tab_commands {
|
||||||
match tab_command {
|
match tab_command {
|
||||||
tab::Command::Action(action) => {
|
tab::Command::Action(action) => {
|
||||||
dbg!(&action);
|
|
||||||
commands.push(self.update(action.message(Some(entity))));
|
commands.push(self.update(action.message(Some(entity))));
|
||||||
}
|
}
|
||||||
tab::Command::AddNetworkDrive => {
|
tab::Command::AddNetworkDrive => {
|
||||||
|
|
@ -3694,7 +3683,6 @@ impl Application for App {
|
||||||
self.set_show_context(true);
|
self.set_show_context(true);
|
||||||
}
|
}
|
||||||
tab::Command::AddToSidebar(path) => {
|
tab::Command::AddToSidebar(path) => {
|
||||||
dbg!("add to sidebar");
|
|
||||||
let mut favorites = self.config.favorites.clone();
|
let mut favorites = self.config.favorites.clone();
|
||||||
let favorite = Favorite::from_path(path);
|
let favorite = Favorite::from_path(path);
|
||||||
if !favorites.iter().any(|f| f == &favorite) {
|
if !favorites.iter().any(|f| f == &favorite) {
|
||||||
|
|
@ -3740,7 +3728,6 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
tab::Command::OpenFile(paths) => self.open_file(&paths),
|
tab::Command::OpenFile(paths) => self.open_file(&paths),
|
||||||
tab::Command::OpenInNewTab(path) => {
|
tab::Command::OpenInNewTab(path) => {
|
||||||
dbg!(&path);
|
|
||||||
commands.push(self.open_tab(Location::Path(path.clone()), false, None));
|
commands.push(self.open_tab(Location::Path(path.clone()), false, None));
|
||||||
}
|
}
|
||||||
tab::Command::OpenInNewWindow(path) => match env::current_exe() {
|
tab::Command::OpenInNewWindow(path) => match env::current_exe() {
|
||||||
|
|
@ -4206,7 +4193,6 @@ impl Application for App {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Some(Location::Path(ref path)) => {
|
Some(Location::Path(ref path)) => {
|
||||||
dbg!(path);
|
|
||||||
return self.open_tab(Location::Path(path.clone()), false, None);
|
return self.open_tab(Location::Path(path.clone()), false, None);
|
||||||
}
|
}
|
||||||
Some(Location::Recents) => {
|
Some(Location::Recents) => {
|
||||||
|
|
@ -4232,6 +4218,9 @@ impl Application for App {
|
||||||
Location::Trash => {
|
Location::Trash => {
|
||||||
command.arg("--trash");
|
command.arg("--trash");
|
||||||
}
|
}
|
||||||
|
Location::Network(uri, _, Some(_)) => {
|
||||||
|
command.arg(uri);
|
||||||
|
}
|
||||||
Location::Network(..) => {
|
Location::Network(..) => {
|
||||||
command.arg("--network");
|
command.arg("--network");
|
||||||
}
|
}
|
||||||
|
|
@ -4470,7 +4459,6 @@ impl Application for App {
|
||||||
return self.on_nav_select(entity);
|
return self.on_nav_select(entity);
|
||||||
}
|
}
|
||||||
Message::NetworkDriveOpenTabAfterMount { location } => {
|
Message::NetworkDriveOpenTabAfterMount { location } => {
|
||||||
dbg!("location");
|
|
||||||
return self.open_tab(location, false, None);
|
return self.open_tab(location, false, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6049,7 +6037,6 @@ pub(crate) mod test_utils {
|
||||||
nested: usize,
|
nested: usize,
|
||||||
name_len: usize,
|
name_len: usize,
|
||||||
) -> io::Result<(TempDir, Tab)> {
|
) -> io::Result<(TempDir, Tab)> {
|
||||||
dbg!("new tab...");
|
|
||||||
let fs = simple_fs(files, hidden, dirs, nested, name_len)?;
|
let fs = simple_fs(files, hidden, dirs, nested, name_len)?;
|
||||||
let path = fs.path();
|
let path = fs.path();
|
||||||
|
|
||||||
|
|
|
||||||
11
src/lib.rs
11
src/lib.rs
|
|
@ -80,6 +80,7 @@ pub fn desktop() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
state,
|
state,
|
||||||
mode: app::Mode::Desktop,
|
mode: app::Mode::Desktop,
|
||||||
locations,
|
locations,
|
||||||
|
uris: Vec::new()
|
||||||
};
|
};
|
||||||
cosmic::app::run::<App>(settings, flags)?;
|
cosmic::app::run::<App>(settings, flags)?;
|
||||||
|
|
||||||
|
|
@ -98,6 +99,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
let mut daemonize = true;
|
let mut daemonize = true;
|
||||||
let mut locations = Vec::new();
|
let mut locations = Vec::new();
|
||||||
|
let mut uris = Vec::new();
|
||||||
for arg in env::args().skip(1) {
|
for arg in env::args().skip(1) {
|
||||||
let location = if &arg == "--no-daemon" {
|
let location = if &arg == "--no-daemon" {
|
||||||
daemonize = false;
|
daemonize = false;
|
||||||
|
|
@ -111,14 +113,18 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
} else {
|
} else {
|
||||||
//TODO: support more URLs
|
//TODO: support more URLs
|
||||||
let path = match url::Url::parse(&arg) {
|
let path = match url::Url::parse(&arg) {
|
||||||
Ok(url) => match url.to_file_path() {
|
Ok(url) if url.scheme() == "file" => match url.to_file_path() {
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
log::warn!("invalid argument {:?}", arg);
|
log::warn!("invalid argument {:?}", arg);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(_) => PathBuf::from(arg),
|
Ok(url) => {
|
||||||
|
uris.push(url);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ => PathBuf::from(arg),
|
||||||
};
|
};
|
||||||
match fs::canonicalize(&path) {
|
match fs::canonicalize(&path) {
|
||||||
Ok(absolute) => Location::Path(absolute),
|
Ok(absolute) => Location::Path(absolute),
|
||||||
|
|
@ -160,6 +166,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
state,
|
state,
|
||||||
mode: app::Mode::App,
|
mode: app::Mode::App,
|
||||||
locations,
|
locations,
|
||||||
|
uris
|
||||||
};
|
};
|
||||||
cosmic::app::run::<App>(settings, flags)?;
|
cosmic::app::run::<App>(settings, flags)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -335,7 +335,6 @@ pub fn context_menu<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(_, Location::Network(..)) => {
|
(_, Location::Network(..)) => {
|
||||||
dbg!(selected, &tab.mode);
|
|
||||||
if selected > 0 {
|
if selected > 0 {
|
||||||
if selected_dir == 1 && selected == 1 || selected_dir == 0 {
|
if selected_dir == 1 && selected == 1 || selected_dir == 0 {
|
||||||
children.push(menu_item(fl!("open"), Action::Open).into());
|
children.push(menu_item(fl!("open"), Action::Open).into());
|
||||||
|
|
|
||||||
|
|
@ -69,11 +69,7 @@ fn items(monitor: &gio::VolumeMonitor, sizes: IconSizes) -> MounterItems {
|
||||||
items
|
items
|
||||||
}
|
}
|
||||||
|
|
||||||
fn network_scan(
|
fn network_scan(uri: &str, sizes: IconSizes) -> Result<Vec<tab::Item>, String> {
|
||||||
uri: &str,
|
|
||||||
sizes: IconSizes,
|
|
||||||
path: Option<&Path>,
|
|
||||||
) -> Result<Vec<tab::Item>, String> {
|
|
||||||
let file = gio::File::for_uri(uri);
|
let file = gio::File::for_uri(uri);
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
for info_res in file
|
for info_res in file
|
||||||
|
|
@ -84,18 +80,9 @@ fn network_scan(
|
||||||
let name = info.name().to_string_lossy().to_string();
|
let name = info.name().to_string_lossy().to_string();
|
||||||
let display_name = info.display_name().to_string();
|
let display_name = info.display_name().to_string();
|
||||||
|
|
||||||
|
let uri = file.child(info.name()).uri().to_string();
|
||||||
//TODO: what is the best way to resolve shortcuts?
|
//TODO: what is the best way to resolve shortcuts?
|
||||||
let location = Location::Network(
|
let location = Location::Network(uri, display_name.clone(), file.child(info.name()).path());
|
||||||
if let Some(target_uri) = info.attribute_string(gio::FILE_ATTRIBUTE_STANDARD_TARGET_URI)
|
|
||||||
{
|
|
||||||
target_uri.to_string()
|
|
||||||
} else {
|
|
||||||
file.child(info.name()).uri().to_string()
|
|
||||||
},
|
|
||||||
display_name.clone(),
|
|
||||||
file.child(info.name()).path(),
|
|
||||||
);
|
|
||||||
|
|
||||||
//TODO: support dir or file
|
//TODO: support dir or file
|
||||||
let metadata = ItemMetadata::SimpleDir { entries: 0 };
|
let metadata = ItemMetadata::SimpleDir { entries: 0 };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3036,7 +3036,6 @@ impl Tab {
|
||||||
}
|
}
|
||||||
if !item.selected {
|
if !item.selected {
|
||||||
self.clicked = click_i_opt;
|
self.clicked = click_i_opt;
|
||||||
dbg!(&item.location_opt);
|
|
||||||
item.selected = true;
|
item.selected = true;
|
||||||
}
|
}
|
||||||
self.select_range = Some((i, i));
|
self.select_range = Some((i, i));
|
||||||
|
|
@ -3137,7 +3136,6 @@ impl Tab {
|
||||||
}
|
}
|
||||||
LocationMenuAction::AddToSidebar(ancestor_index) => {
|
LocationMenuAction::AddToSidebar(ancestor_index) => {
|
||||||
if let Some(path) = path_for_index(ancestor_index) {
|
if let Some(path) = path_for_index(ancestor_index) {
|
||||||
dbg!(&path);
|
|
||||||
commands.push(Command::AddToSidebar(path));
|
commands.push(Command::AddToSidebar(path));
|
||||||
} else {
|
} else {
|
||||||
log::warn!(
|
log::warn!(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue