fix: add eject button for context menus on mount point
This commit is contained in:
parent
aba90279e6
commit
6a2bd1faf1
6 changed files with 90 additions and 16 deletions
|
|
@ -291,6 +291,7 @@ type-to-search-enter-path = Enters the path to the directory or file
|
|||
add-to-sidebar = Add to sidebar
|
||||
compress = Compress
|
||||
delete-permanently = Delete permanently
|
||||
eject = Eject
|
||||
extract-here = Extract
|
||||
new-file = New file...
|
||||
new-folder = New folder...
|
||||
|
|
|
|||
58
src/app.rs
58
src/app.rs
|
|
@ -117,6 +117,7 @@ pub enum Action {
|
|||
Delete,
|
||||
EditHistory,
|
||||
EditLocation,
|
||||
Eject,
|
||||
EmptyTrash,
|
||||
#[cfg(feature = "desktop")]
|
||||
ExecEntryAction(usize),
|
||||
|
|
@ -184,6 +185,7 @@ impl Action {
|
|||
Action::EditLocation => {
|
||||
Message::TabMessage(entity_opt, tab::Message::EditLocationEnable)
|
||||
}
|
||||
Action::Eject => Message::Eject,
|
||||
Action::EmptyTrash => Message::TabMessage(None, tab::Message::EmptyTrash),
|
||||
Action::ExtractHere => Message::ExtractHere(entity_opt),
|
||||
Action::ExtractTo => Message::ExtractTo(entity_opt),
|
||||
|
|
@ -304,6 +306,7 @@ pub enum Message {
|
|||
DesktopViewOptions,
|
||||
DialogCancel,
|
||||
DialogComplete,
|
||||
Eject,
|
||||
FileDialogMessage(DialogMessage),
|
||||
DialogPush(DialogPage),
|
||||
DialogUpdate(DialogPage),
|
||||
|
|
@ -1044,17 +1047,36 @@ impl App {
|
|||
) -> Task<Message> {
|
||||
log::info!("rescan_tab {entity:?} {location:?} {selection_paths:?}");
|
||||
let icon_sizes = self.config.tab.icon_sizes;
|
||||
let mounter_items = self.mounter_items.clone();
|
||||
|
||||
Task::perform(
|
||||
async move {
|
||||
let location2 = location.clone();
|
||||
match tokio::task::spawn_blocking(move || location2.scan(icon_sizes)).await {
|
||||
Ok((parent_item_opt, items)) => cosmic::action::app(Message::TabRescan(
|
||||
entity,
|
||||
location,
|
||||
parent_item_opt,
|
||||
items,
|
||||
selection_paths,
|
||||
)),
|
||||
Ok((parent_item_opt, mut items)) => {
|
||||
#[cfg(feature = "gvfs")]
|
||||
{
|
||||
let mounter_paths: Vec<_> = mounter_items
|
||||
.iter()
|
||||
.flat_map(|item| item.1.iter())
|
||||
.filter_map(|item| item.path())
|
||||
.collect();
|
||||
if !mounter_paths.is_empty() {
|
||||
for item in &mut items {
|
||||
item.is_mount_point =
|
||||
item.path_opt().is_some_and(|p| mounter_paths.contains(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cosmic::action::app(Message::TabRescan(
|
||||
entity,
|
||||
location,
|
||||
parent_item_opt,
|
||||
items,
|
||||
selection_paths,
|
||||
))
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("failed to rescan: {}", err);
|
||||
cosmic::action::none()
|
||||
|
|
@ -4136,6 +4158,28 @@ impl Application for App {
|
|||
self.size = Some(size);
|
||||
self.handle_overlap();
|
||||
}
|
||||
Message::Eject => {
|
||||
#[cfg(feature = "gvfs")]
|
||||
{
|
||||
let paths = self.selected_paths(None);
|
||||
if let Some(p) = paths.first() {
|
||||
{
|
||||
for (k, mounter_items) in &self.mounter_items {
|
||||
if let Some(mounter) = MOUNTERS.get(&k) {
|
||||
if let Some(item) = mounter_items
|
||||
.iter()
|
||||
.find(|item| item.path().is_some_and(|path| path == *p))
|
||||
{
|
||||
return mounter
|
||||
.unmount(item.clone())
|
||||
.map(|_| cosmic::action::none());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(all(feature = "wayland", feature = "desktop-applet"))]
|
||||
Message::Focused(id) => {
|
||||
if let Some(w) = self.windows.get(&id) {
|
||||
|
|
|
|||
|
|
@ -650,11 +650,26 @@ impl App {
|
|||
fn rescan_tab(&self) -> Task<Message> {
|
||||
let location = self.tab.location.clone();
|
||||
let icon_sizes = self.tab.config.icon_sizes;
|
||||
let mounter_items = self.mounter_items.clone();
|
||||
Task::perform(
|
||||
async move {
|
||||
let location2 = location.clone();
|
||||
match tokio::task::spawn_blocking(move || location2.scan(icon_sizes)).await {
|
||||
Ok((parent_item_opt, items)) => {
|
||||
Ok((parent_item_opt, mut items)) => {
|
||||
#[cfg(feature = "gvfs")]
|
||||
{
|
||||
let mounter_paths: Vec<_> = mounter_items
|
||||
.iter()
|
||||
.flat_map(|item| item.1.iter())
|
||||
.filter_map(|item| item.path())
|
||||
.collect();
|
||||
if !mounter_paths.is_empty() {
|
||||
for item in &mut items {
|
||||
item.is_mount_point =
|
||||
item.path_opt().is_some_and(|p| mounter_paths.contains(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
cosmic::action::app(Message::TabRescan(location, parent_item_opt, items))
|
||||
}
|
||||
Err(err) => {
|
||||
|
|
|
|||
24
src/menu.rs
24
src/menu.rs
|
|
@ -108,11 +108,13 @@ pub fn context_menu<'a>(
|
|||
let mut selected_trash_only = false;
|
||||
let mut selected_desktop_entry = None;
|
||||
let mut selected_types: Vec<Mime> = vec![];
|
||||
let mut selected_mount_point = 0;
|
||||
if let Some(items) = tab.items_opt() {
|
||||
for item in items.iter() {
|
||||
if item.selected {
|
||||
selected += 1;
|
||||
if item.metadata.is_dir() {
|
||||
selected_mount_point += item.is_mount_point as i32;
|
||||
selected_dir += 1;
|
||||
}
|
||||
match &item.location_opt {
|
||||
|
|
@ -194,8 +196,10 @@ pub fn context_menu<'a>(
|
|||
.push(menu_item(fl!("open-in-new-window"), Action::OpenInNewWindow).into());
|
||||
}
|
||||
children.push(divider::horizontal::light().into());
|
||||
children.push(menu_item(fl!("rename"), Action::Rename).into());
|
||||
children.push(menu_item(fl!("cut"), Action::Cut).into());
|
||||
if selected_mount_point == 0 {
|
||||
children.push(menu_item(fl!("rename"), Action::Rename).into());
|
||||
children.push(menu_item(fl!("cut"), Action::Cut).into());
|
||||
}
|
||||
children.push(menu_item(fl!("copy"), Action::Copy).into());
|
||||
|
||||
children.push(divider::horizontal::light().into());
|
||||
|
|
@ -235,12 +239,16 @@ pub fn context_menu<'a>(
|
|||
children.push(menu_item(fl!("add-to-sidebar"), Action::AddToSidebar).into());
|
||||
}
|
||||
children.push(divider::horizontal::light().into());
|
||||
if modifiers.shift() && !modifiers.control() {
|
||||
children.push(
|
||||
menu_item(fl!("delete-permanently"), Action::PermanentlyDelete).into(),
|
||||
);
|
||||
} else {
|
||||
children.push(menu_item(fl!("move-to-trash"), Action::Delete).into());
|
||||
if selected_mount_point == 0 {
|
||||
if modifiers.shift() && !modifiers.control() {
|
||||
children.push(
|
||||
menu_item(fl!("delete-permanently"), Action::PermanentlyDelete).into(),
|
||||
);
|
||||
} else {
|
||||
children.push(menu_item(fl!("move-to-trash"), Action::Delete).into());
|
||||
}
|
||||
} else if selected == 1 {
|
||||
children.push(menu_item(fl!("eject"), Action::Eject).into());
|
||||
}
|
||||
} else {
|
||||
//TODO: need better designs for menu with no selection
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ fn network_scan(uri: &str, sizes: IconSizes) -> Result<Vec<tab::Item>, String> {
|
|||
|
||||
items.push(tab::Item {
|
||||
name,
|
||||
is_mount_point: false,
|
||||
display_name,
|
||||
metadata,
|
||||
hidden: false,
|
||||
|
|
|
|||
|
|
@ -668,6 +668,7 @@ pub fn item_from_gvfs_info(path: PathBuf, file_info: gio::FileInfo, sizes: IconS
|
|||
Item {
|
||||
name: file_name.clone().to_string(),
|
||||
display_name,
|
||||
is_mount_point: false,
|
||||
metadata: ItemMetadata::GvfsPath {
|
||||
mtime,
|
||||
size_opt,
|
||||
|
|
@ -809,6 +810,7 @@ pub fn item_from_entry(
|
|||
Item {
|
||||
name,
|
||||
display_name,
|
||||
is_mount_point: false,
|
||||
metadata: ItemMetadata::Path {
|
||||
metadata,
|
||||
children_opt,
|
||||
|
|
@ -1090,6 +1092,7 @@ pub fn scan_trash(sizes: IconSizes) -> Vec<Item> {
|
|||
items.push(Item {
|
||||
name,
|
||||
display_name,
|
||||
is_mount_point: false,
|
||||
metadata: ItemMetadata::Trash { metadata, entry },
|
||||
hidden: false,
|
||||
location_opt: None,
|
||||
|
|
@ -1270,6 +1273,7 @@ pub fn scan_desktop(
|
|||
items.push(Item {
|
||||
name,
|
||||
display_name,
|
||||
is_mount_point: false,
|
||||
metadata,
|
||||
hidden: false,
|
||||
location_opt: Some(Location::Trash),
|
||||
|
|
@ -1821,6 +1825,7 @@ impl ItemThumbnail {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct Item {
|
||||
pub name: String,
|
||||
pub is_mount_point: bool,
|
||||
pub display_name: String,
|
||||
pub metadata: ItemMetadata,
|
||||
pub hidden: bool,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue