Add empty trash, fixes #118
This commit is contained in:
parent
99c378873a
commit
1116eaa05a
5 changed files with 91 additions and 15 deletions
|
|
@ -5,7 +5,18 @@ filesystem = Filesystem
|
||||||
home = Home
|
home = Home
|
||||||
trash = Trash
|
trash = Trash
|
||||||
|
|
||||||
# New File/Folder Dialog
|
# List view
|
||||||
|
name = Name
|
||||||
|
modified = Modified
|
||||||
|
size = Size
|
||||||
|
|
||||||
|
# Dialogs
|
||||||
|
|
||||||
|
## Empty Trash Dialog
|
||||||
|
empty-trash = Empty trash
|
||||||
|
empty-trash-warning = Are you sure you want to permanently delete all the items in Trash?
|
||||||
|
|
||||||
|
## 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
|
||||||
file-name = File name
|
file-name = File name
|
||||||
|
|
@ -16,7 +27,7 @@ name-hidden = Names starting with "." will be hidden.
|
||||||
name-invalid = Name cannot be "{$filename}".
|
name-invalid = Name cannot be "{$filename}".
|
||||||
name-no-slashes = Name cannot contain slashes.
|
name-no-slashes = Name cannot contain slashes.
|
||||||
|
|
||||||
# Open/Save Dialog
|
## Open/Save Dialog
|
||||||
cancel = Cancel
|
cancel = Cancel
|
||||||
open = Open
|
open = Open
|
||||||
open-file = Open file
|
open-file = Open file
|
||||||
|
|
@ -28,20 +39,15 @@ open-multiple-folders = Open multiple folders
|
||||||
save = Save
|
save = Save
|
||||||
save-file = Save file
|
save-file = Save file
|
||||||
|
|
||||||
# Rename Dialog
|
## Rename Dialog
|
||||||
rename-file = Rename file
|
rename-file = Rename file
|
||||||
rename-folder = Rename folder
|
rename-folder = Rename folder
|
||||||
|
|
||||||
# Replace Dialog
|
## Replace Dialog
|
||||||
replace = Replace
|
replace = Replace
|
||||||
replace-title = {$filename} already exists in this location.
|
replace-title = {$filename} already exists in this location.
|
||||||
replace-warning = Do you want to replace it with the one you are saving? Replacing it will overwrite its content.
|
replace-warning = Do you want to replace it with the one you are saving? Replacing it will overwrite its content.
|
||||||
|
|
||||||
# List view
|
|
||||||
name = Name
|
|
||||||
modified = Modified
|
|
||||||
size = Size
|
|
||||||
|
|
||||||
# Context Pages
|
# Context Pages
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
|
||||||
15
src/app.rs
15
src/app.rs
|
|
@ -247,6 +247,7 @@ impl ContextPage {
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum DialogPage {
|
pub enum DialogPage {
|
||||||
|
EmptyTrash,
|
||||||
FailedOperation(u64),
|
FailedOperation(u64),
|
||||||
NewItem {
|
NewItem {
|
||||||
parent: PathBuf,
|
parent: PathBuf,
|
||||||
|
|
@ -1034,6 +1035,9 @@ impl Application for App {
|
||||||
Message::DialogComplete => {
|
Message::DialogComplete => {
|
||||||
if let Some(dialog_page) = self.dialog_pages.pop_front() {
|
if let Some(dialog_page) = self.dialog_pages.pop_front() {
|
||||||
match dialog_page {
|
match dialog_page {
|
||||||
|
DialogPage::EmptyTrash => {
|
||||||
|
self.operation(Operation::EmptyTrash);
|
||||||
|
}
|
||||||
DialogPage::FailedOperation(id) => {
|
DialogPage::FailedOperation(id) => {
|
||||||
log::warn!("TODO: retry operation {}", id);
|
log::warn!("TODO: retry operation {}", id);
|
||||||
}
|
}
|
||||||
|
|
@ -1488,6 +1492,9 @@ impl Application for App {
|
||||||
self.rescan_tab(entity, tab_path),
|
self.rescan_tab(entity, tab_path),
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
tab::Command::EmptyTrash => {
|
||||||
|
self.dialog_pages.push_back(DialogPage::EmptyTrash);
|
||||||
|
}
|
||||||
tab::Command::FocusButton(id) => {
|
tab::Command::FocusButton(id) => {
|
||||||
commands.push(widget::button::focus(id));
|
commands.push(widget::button::focus(id));
|
||||||
}
|
}
|
||||||
|
|
@ -1758,6 +1765,14 @@ impl Application for App {
|
||||||
let cosmic_theme::Spacing { space_xxs, .. } = theme::active().cosmic().spacing;
|
let cosmic_theme::Spacing { space_xxs, .. } = theme::active().cosmic().spacing;
|
||||||
|
|
||||||
let dialog = match dialog_page {
|
let dialog = match dialog_page {
|
||||||
|
DialogPage::EmptyTrash => widget::dialog(fl!("empty-trash"))
|
||||||
|
.body(fl!("empty-trash-warning"))
|
||||||
|
.primary_action(
|
||||||
|
widget::button::suggested(fl!("empty-trash")).on_press(Message::DialogComplete),
|
||||||
|
)
|
||||||
|
.secondary_action(
|
||||||
|
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
||||||
|
),
|
||||||
DialogPage::FailedOperation(id) => {
|
DialogPage::FailedOperation(id) => {
|
||||||
//TODO: try next dialog page (making sure index is used by Dialog messages)?
|
//TODO: try next dialog page (making sure index is used by Dialog messages)?
|
||||||
let (operation, err) = self.failed_operations.get(id)?;
|
let (operation, err) = self.failed_operations.get(id)?;
|
||||||
|
|
|
||||||
|
|
@ -618,6 +618,9 @@ impl Application for App {
|
||||||
tab::Command::DropFiles(_, _) => {
|
tab::Command::DropFiles(_, _) => {
|
||||||
log::warn!("DropFiles not supported in dialog");
|
log::warn!("DropFiles not supported in dialog");
|
||||||
}
|
}
|
||||||
|
tab::Command::EmptyTrash => {
|
||||||
|
log::warn!("EmptyTrash not supported in dialog");
|
||||||
|
}
|
||||||
tab::Command::FocusButton(id) => {
|
tab::Command::FocusButton(id) => {
|
||||||
commands.push(widget::button::focus(id));
|
commands.push(widget::button::focus(id));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ pub enum Operation {
|
||||||
Delete {
|
Delete {
|
||||||
paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
},
|
},
|
||||||
|
/// Empty the trash
|
||||||
|
EmptyTrash,
|
||||||
/// Move items
|
/// Move items
|
||||||
Move {
|
Move {
|
||||||
paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
|
|
@ -100,6 +102,31 @@ impl Operation {
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Self::EmptyTrash => {
|
||||||
|
#[cfg(any(
|
||||||
|
target_os = "windows",
|
||||||
|
all(
|
||||||
|
unix,
|
||||||
|
not(target_os = "macos"),
|
||||||
|
not(target_os = "ios"),
|
||||||
|
not(target_os = "android")
|
||||||
|
)
|
||||||
|
))]
|
||||||
|
{
|
||||||
|
tokio::task::spawn_blocking(|| {
|
||||||
|
let items = trash::os_limited::list()?;
|
||||||
|
trash::os_limited::purge_all(items)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.map_err(err_str)?
|
||||||
|
.map_err(err_str)?;
|
||||||
|
}
|
||||||
|
let _ = msg_tx
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.send(Message::PendingProgress(id, 100.0))
|
||||||
|
.await;
|
||||||
|
}
|
||||||
Self::Move { paths, to } => {
|
Self::Move { paths, to } => {
|
||||||
let msg_tx = msg_tx.clone();
|
let msg_tx = msg_tx.clone();
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
|
|
|
||||||
37
src/tab.rs
37
src/tab.rs
|
|
@ -429,6 +429,7 @@ impl Location {
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Action(Action),
|
Action(Action),
|
||||||
ChangeLocation(String, Location),
|
ChangeLocation(String, Location),
|
||||||
|
EmptyTrash,
|
||||||
FocusButton(widget::Id),
|
FocusButton(widget::Id),
|
||||||
FocusTextInput(widget::Id),
|
FocusTextInput(widget::Id),
|
||||||
OpenFile(PathBuf),
|
OpenFile(PathBuf),
|
||||||
|
|
@ -449,6 +450,7 @@ pub enum Message {
|
||||||
ContextMenu(Option<Point>),
|
ContextMenu(Option<Point>),
|
||||||
Drag(Option<Rectangle>),
|
Drag(Option<Rectangle>),
|
||||||
EditLocation(Option<Location>),
|
EditLocation(Option<Location>),
|
||||||
|
EmptyTrash,
|
||||||
GoNext,
|
GoNext,
|
||||||
GoPrevious,
|
GoPrevious,
|
||||||
ItemDown,
|
ItemDown,
|
||||||
|
|
@ -1081,6 +1083,9 @@ impl Tab {
|
||||||
}
|
}
|
||||||
self.edit_location = edit_location;
|
self.edit_location = edit_location;
|
||||||
}
|
}
|
||||||
|
Message::EmptyTrash => {
|
||||||
|
commands.push(Command::EmptyTrash);
|
||||||
|
}
|
||||||
Message::GoNext => {
|
Message::GoNext => {
|
||||||
if let Some(history_i) = self.history_i.checked_add(1) {
|
if let Some(history_i) = self.history_i.checked_add(1) {
|
||||||
if let Some(location) = self.history.get(history_i) {
|
if let Some(location) = self.history.get(history_i) {
|
||||||
|
|
@ -2270,12 +2275,32 @@ impl Tab {
|
||||||
.on_scroll(Message::Scroll)
|
.on_scroll(Message::Scroll)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill);
|
.height(Length::Fill);
|
||||||
let mut tab_view = widget::container(widget::column::with_children(vec![
|
let mut tab_column = widget::column::with_children(vec![location_view, scrollable.into()]);
|
||||||
location_view,
|
if let Location::Trash = self.location {
|
||||||
scrollable.into(),
|
if let Some(items) = self.items_opt() {
|
||||||
]))
|
if !items.is_empty() {
|
||||||
.height(Length::Fill)
|
let cosmic_theme::Spacing {
|
||||||
.width(Length::Fill);
|
space_xxs,
|
||||||
|
space_xs,
|
||||||
|
..
|
||||||
|
} = theme::active().cosmic().spacing;
|
||||||
|
|
||||||
|
tab_column = tab_column.push(
|
||||||
|
widget::layer_container(widget::row::with_children(vec![
|
||||||
|
widget::horizontal_space(Length::Fill).into(),
|
||||||
|
widget::button::standard(fl!("empty-trash"))
|
||||||
|
.on_press(Message::EmptyTrash)
|
||||||
|
.into(),
|
||||||
|
]))
|
||||||
|
.padding([space_xxs, space_xs])
|
||||||
|
.layer(cosmic_theme::Layer::Primary),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut tab_view = widget::container(tab_column)
|
||||||
|
.height(Length::Fill)
|
||||||
|
.width(Length::Fill);
|
||||||
|
|
||||||
if self.dnd_hovered.as_ref().map(|(l, _)| l) == Some(&tab_location) {
|
if self.dnd_hovered.as_ref().map(|(l, _)| l) == Some(&tab_location) {
|
||||||
tab_view = tab_view.style(cosmic::theme::Container::custom(|t| {
|
tab_view = tab_view.style(cosmic::theme::Container::custom(|t| {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue