feat: handle opening network location in new window

This commit is contained in:
Ashley Wulber 2025-07-14 18:10:14 -04:00 committed by Jeremy Soller
parent c7e9828d7b
commit 08367c9ea6
5 changed files with 43 additions and 65 deletions

View file

@ -105,6 +105,7 @@ pub struct Flags {
pub state: State,
pub mode: Mode,
pub locations: Vec<Location>,
pub uris: Vec<url::Url>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@ -893,7 +894,6 @@ impl App {
) -> (Entity, Task<Message>) {
#[cfg(feature = "gvfs")]
if let Location::Network(ref uri, ref name, Some(ref path)) = location {
dbg!(path, self.mounter_items.len());
let mut found = false;
if let Some(key) = self
@ -904,30 +904,18 @@ impl App {
found |= item.path().is_some_and(|p| path.starts_with(p))
|| item.name() == *name
|| item.uri() == *uri;
dbg!(
item.is_mounted(),
item.path(),
path,
name,
item.name(),
item.uri(),
uri
);
(!item.is_mounted() && found).then(|| *k)
})
})
.or(if found {
dbg!("found so skip...");
None
} else {
dbg!("not found...");
// TODO do we need to choose the correct mounter?
self.mounter_items.iter().map(|(k, _)| *k).next()
})
{
if let Some(mounter) = MOUNTERS.get(&key) {
let location = location.clone();
dbg!(&location);
return (
Entity::null(),
mounter.network_drive(uri.clone()).map(move |_| {
@ -937,12 +925,9 @@ impl App {
}),
);
}
} else {
dbg!("huh...");
}
}
dbg!(&location);
let mut tab = Tab::new(
location.clone(),
self.config.tab,
@ -1119,7 +1104,6 @@ impl App {
location: Location,
selection_paths: Option<Vec<PathBuf>>,
) -> Task<Message> {
dbg!("rescan", &location);
log::info!("rescan_tab {entity:?} {location:?} {selection_paths:?}");
let icon_sizes = self.config.tab.icon_sizes;
let mounter_items = self.mounter_items.clone();
@ -2101,6 +2085,17 @@ impl Application for App {
}
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 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> {
self.nav_model.activate(entity);
if let Some(location) = self.nav_model.data::<Location>(entity) {
dbg!(&location);
let should_open = match location {
#[cfg(feature = "gvfs")]
Location::Network(uri, name, Some(path))
if !path.try_exists().unwrap_or_default() =>
{
dbg!(&location, path, self.mounter_items.len(), uri, path);
let mut found = false;
if let Some(key) = self
@ -2244,7 +2236,6 @@ impl Application for App {
found |= item.path().is_some_and(|p| path.starts_with(&p))
|| item.name() == *name
|| item.uri() == *uri;
dbg!(item.is_mounted(), item.path());
(!item.is_mounted() && found).then(|| *k)
})
})
@ -2256,9 +2247,6 @@ impl Application for App {
})
{
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 |_| {
cosmic::Action::App(Message::NetworkDriveOpenEntityAfterMount {
entity,
@ -2299,7 +2287,6 @@ impl Application for App {
_ => true,
};
dbg!(should_open);
if should_open {
let message = Message::TabMessage(None, tab::Message::Location(location.clone()));
return self.update(message);
@ -2422,15 +2409,12 @@ impl Application for App {
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
for path in self.selected_paths(entity_opt) {
dbg!(&path);
let is_network = self.tab_model.data::<Tab>(entity).and_then(|tab| {
let in_current_tab =
tab.location.path_opt().zip(path.parent()).is_some_and(
|(t_path, parent)| {
dbg!(&parent, &t_path);
parent == t_path
},
);
let in_current_tab = tab
.location
.path_opt()
.zip(path.parent())
.is_some_and(|(t_path, parent)| parent == t_path);
let tab = if in_current_tab {
self.tab_model
.data::<Tab>(self.tab_model.active())
@ -2438,15 +2422,23 @@ impl Application for App {
} else {
tab
};
dbg!(in_current_tab, &tab.location);
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()))
} else {
None
}
});
dbg!(&is_network);
let name = Location::Path(path.clone()).title();
let favorite = if let Some((uri, _, _)) = is_network.clone() {
Favorite::Network { uri, name, path }
@ -2455,7 +2447,6 @@ impl Application for App {
};
if !favorites.iter().any(|f| f == &favorite) {
favorites.push(favorite);
dbg!(&favorites);
}
}
config_set!(favorites, favorites);
@ -3147,7 +3138,6 @@ impl Application for App {
Message::OpenInNewTab(entity_opt) => {
return Task::batch(self.selected_paths(entity_opt).into_iter().filter_map(
|path| {
dbg!(&path);
if path.is_dir() {
Some(self.open_tab(Location::Path(path), false, None))
} else {
@ -3686,7 +3676,6 @@ impl Application for App {
for tab_command in tab_commands {
match tab_command {
tab::Command::Action(action) => {
dbg!(&action);
commands.push(self.update(action.message(Some(entity))));
}
tab::Command::AddNetworkDrive => {
@ -3694,7 +3683,6 @@ impl Application for App {
self.set_show_context(true);
}
tab::Command::AddToSidebar(path) => {
dbg!("add to sidebar");
let mut favorites = self.config.favorites.clone();
let favorite = Favorite::from_path(path);
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::OpenInNewTab(path) => {
dbg!(&path);
commands.push(self.open_tab(Location::Path(path.clone()), false, None));
}
tab::Command::OpenInNewWindow(path) => match env::current_exe() {
@ -4206,7 +4193,6 @@ impl Application for App {
);
}
Some(Location::Path(ref path)) => {
dbg!(path);
return self.open_tab(Location::Path(path.clone()), false, None);
}
Some(Location::Recents) => {
@ -4232,6 +4218,9 @@ impl Application for App {
Location::Trash => {
command.arg("--trash");
}
Location::Network(uri, _, Some(_)) => {
command.arg(uri);
}
Location::Network(..) => {
command.arg("--network");
}
@ -4470,7 +4459,6 @@ impl Application for App {
return self.on_nav_select(entity);
}
Message::NetworkDriveOpenTabAfterMount { location } => {
dbg!("location");
return self.open_tab(location, false, None);
}
}
@ -6049,7 +6037,6 @@ pub(crate) mod test_utils {
nested: usize,
name_len: usize,
) -> io::Result<(TempDir, Tab)> {
dbg!("new tab...");
let fs = simple_fs(files, hidden, dirs, nested, name_len)?;
let path = fs.path();

View file

@ -80,6 +80,7 @@ pub fn desktop() -> Result<(), Box<dyn std::error::Error>> {
state,
mode: app::Mode::Desktop,
locations,
uris: Vec::new()
};
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 locations = Vec::new();
let mut uris = Vec::new();
for arg in env::args().skip(1) {
let location = if &arg == "--no-daemon" {
daemonize = false;
@ -111,14 +113,18 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
} else {
//TODO: support more URLs
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,
Err(()) => {
log::warn!("invalid argument {:?}", arg);
continue;
}
},
Err(_) => PathBuf::from(arg),
Ok(url) => {
uris.push(url);
continue;
}
_ => PathBuf::from(arg),
};
match fs::canonicalize(&path) {
Ok(absolute) => Location::Path(absolute),
@ -160,6 +166,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
state,
mode: app::Mode::App,
locations,
uris
};
cosmic::app::run::<App>(settings, flags)?;

View file

@ -335,7 +335,6 @@ pub fn context_menu<'a>(
}
}
(_, Location::Network(..)) => {
dbg!(selected, &tab.mode);
if selected > 0 {
if selected_dir == 1 && selected == 1 || selected_dir == 0 {
children.push(menu_item(fl!("open"), Action::Open).into());

View file

@ -69,11 +69,7 @@ fn items(monitor: &gio::VolumeMonitor, sizes: IconSizes) -> MounterItems {
items
}
fn network_scan(
uri: &str,
sizes: IconSizes,
path: Option<&Path>,
) -> Result<Vec<tab::Item>, String> {
fn network_scan(uri: &str, sizes: IconSizes) -> Result<Vec<tab::Item>, String> {
let file = gio::File::for_uri(uri);
let mut items = Vec::new();
for info_res in file
@ -84,18 +80,9 @@ fn network_scan(
let name = info.name().to_string_lossy().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?
let location = Location::Network(
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(),
);
let location = Location::Network(uri, display_name.clone(), file.child(info.name()).path());
//TODO: support dir or file
let metadata = ItemMetadata::SimpleDir { entries: 0 };

View file

@ -3036,7 +3036,6 @@ impl Tab {
}
if !item.selected {
self.clicked = click_i_opt;
dbg!(&item.location_opt);
item.selected = true;
}
self.select_range = Some((i, i));
@ -3137,7 +3136,6 @@ impl Tab {
}
LocationMenuAction::AddToSidebar(ancestor_index) => {
if let Some(path) = path_for_index(ancestor_index) {
dbg!(&path);
commands.push(Command::AddToSidebar(path));
} else {
log::warn!(