Move desktop dialogs to their own windows
This commit is contained in:
parent
5dad1f0d26
commit
73e1d7ce52
2 changed files with 204 additions and 81 deletions
|
|
@ -85,7 +85,7 @@ optional = true
|
||||||
git = "https://github.com/pop-os/libcosmic.git"
|
git = "https://github.com/pop-os/libcosmic.git"
|
||||||
default-features = false
|
default-features = false
|
||||||
#TODO: a11y feature crashes
|
#TODO: a11y feature crashes
|
||||||
features = ["multi-window", "tokio", "winit", "surface-message"]
|
features = ["autosize","multi-window", "tokio", "winit", "surface-message"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [
|
default = [
|
||||||
|
|
|
||||||
283
src/app.rs
283
src/app.rs
|
|
@ -311,6 +311,7 @@ pub enum Message {
|
||||||
Delete(Option<Entity>),
|
Delete(Option<Entity>),
|
||||||
DesktopConfig(DesktopConfig),
|
DesktopConfig(DesktopConfig),
|
||||||
DesktopViewOptions,
|
DesktopViewOptions,
|
||||||
|
DesktopDialogs(bool),
|
||||||
DialogCancel,
|
DialogCancel,
|
||||||
DialogComplete,
|
DialogComplete,
|
||||||
DragId(window::Id),
|
DragId(window::Id),
|
||||||
|
|
@ -406,6 +407,7 @@ pub enum Message {
|
||||||
UndoTrashStart(Vec<TrashItem>),
|
UndoTrashStart(Vec<TrashItem>),
|
||||||
WindowClose,
|
WindowClose,
|
||||||
WindowCloseRequested(window::Id),
|
WindowCloseRequested(window::Id),
|
||||||
|
WindowMaximize(window::Id, bool),
|
||||||
WindowNew,
|
WindowNew,
|
||||||
WindowUnfocus,
|
WindowUnfocus,
|
||||||
ZoomDefault(Option<Entity>),
|
ZoomDefault(Option<Entity>),
|
||||||
|
|
@ -530,6 +532,63 @@ pub enum DialogPage {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct DialogPages {
|
||||||
|
pages: VecDeque<DialogPage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DialogPages {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
pages: VecDeque::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn front(&self) -> Option<&DialogPage> {
|
||||||
|
self.pages.front()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn front_mut(&mut self) -> Option<&mut DialogPage> {
|
||||||
|
self.pages.front_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_back(&mut self, page: DialogPage) -> Task<Message> {
|
||||||
|
let task = if self.pages.is_empty() {
|
||||||
|
Task::done(cosmic::Action::App(Message::DesktopDialogs(true)))
|
||||||
|
} else {
|
||||||
|
Task::none()
|
||||||
|
};
|
||||||
|
self.pages.push_back(page);
|
||||||
|
task
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_front(&mut self, page: DialogPage) -> Task<Message> {
|
||||||
|
let task = if self.pages.is_empty() {
|
||||||
|
Task::done(cosmic::Action::App(Message::DesktopDialogs(true)))
|
||||||
|
} else {
|
||||||
|
Task::none()
|
||||||
|
};
|
||||||
|
self.pages.push_front(page);
|
||||||
|
task
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn pop_front(&mut self) -> Option<(DialogPage, Task<Message>)> {
|
||||||
|
let page = self.pages.pop_front()?;
|
||||||
|
let task = if self.pages.is_empty() {
|
||||||
|
Task::done(cosmic::Action::App(Message::DesktopDialogs(false)))
|
||||||
|
} else {
|
||||||
|
Task::none()
|
||||||
|
};
|
||||||
|
Some((page, task))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_front(&mut self, page: DialogPage) {
|
||||||
|
if !self.pages.is_empty() {
|
||||||
|
self.pages[0] = page;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FavoriteIndex(usize);
|
pub struct FavoriteIndex(usize);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
|
@ -545,6 +604,7 @@ pub struct MounterData(MounterKey, MounterItem);
|
||||||
pub enum WindowKind {
|
pub enum WindowKind {
|
||||||
Desktop(Entity),
|
Desktop(Entity),
|
||||||
DesktopViewOptions,
|
DesktopViewOptions,
|
||||||
|
Dialogs(widget::Id),
|
||||||
Preview(Option<Entity>, PreviewKind),
|
Preview(Option<Entity>, PreviewKind),
|
||||||
FileDialog(Option<Vec<PathBuf>>),
|
FileDialog(Option<Vec<PathBuf>>),
|
||||||
}
|
}
|
||||||
|
|
@ -571,7 +631,7 @@ impl PartialEq for WatcherWrapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The [`App`] stores application-specific state.
|
// The [`App`] stores application-specific state.
|
||||||
pub struct App {
|
pub struct App {
|
||||||
core: Core,
|
core: Core,
|
||||||
nav_bar_context_id: segmented_button::Entity,
|
nav_bar_context_id: segmented_button::Entity,
|
||||||
|
|
@ -585,7 +645,7 @@ pub struct App {
|
||||||
app_themes: Vec<String>,
|
app_themes: Vec<String>,
|
||||||
compio_tx: mpsc::Sender<Pin<Box<dyn Future<Output = ()> + Send>>>,
|
compio_tx: mpsc::Sender<Pin<Box<dyn Future<Output = ()> + Send>>>,
|
||||||
context_page: ContextPage,
|
context_page: ContextPage,
|
||||||
dialog_pages: VecDeque<DialogPage>,
|
dialog_pages: DialogPages,
|
||||||
dialog_text_input: widget::Id,
|
dialog_text_input: widget::Id,
|
||||||
key_binds: HashMap<KeyBind, Action>,
|
key_binds: HashMap<KeyBind, Action>,
|
||||||
margin: HashMap<window::Id, (f32, f32, f32, f32)>,
|
margin: HashMap<window::Id, (f32, f32, f32, f32)>,
|
||||||
|
|
@ -739,30 +799,31 @@ impl App {
|
||||||
let len = commands.len();
|
let len = commands.len();
|
||||||
|
|
||||||
for (i, mut command) in commands.into_iter().enumerate() {
|
for (i, mut command) in commands.into_iter().enumerate() {
|
||||||
if let Err(err) = spawn_detached(&mut command) {
|
match spawn_detached(&mut command) {
|
||||||
// More than one command: The app doesn't support lists of paths so each command
|
Ok(()) => {
|
||||||
// is associated with one instance
|
for path in paths {
|
||||||
//
|
let _ = recently_used_xbel::update_recently_used(
|
||||||
// One command: Attempted to launch one app with multiple paths
|
&path.into(),
|
||||||
let path = if len > 1 {
|
App::APP_ID.to_string(),
|
||||||
format!("{:?}", paths.get(i))
|
"cosmic-files".to_string(),
|
||||||
} else {
|
None,
|
||||||
format!("{paths:?}")
|
);
|
||||||
};
|
}
|
||||||
log::warn!("failed to open {:?} with {:?}: {}", path, app.id, err);
|
}
|
||||||
|
Err(err) => {
|
||||||
|
// More than one command: The app doesn't support lists of paths so each command
|
||||||
|
// is associated with one instance
|
||||||
|
//
|
||||||
|
// One command: Attempted to launch one app with multiple paths
|
||||||
|
let path = if len > 1 {
|
||||||
|
format!("{:?}", paths.get(i))
|
||||||
|
} else {
|
||||||
|
format!("{paths:?}")
|
||||||
|
};
|
||||||
|
log::warn!("failed to open {:?} with {:?}: {}", path, app.id, err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for path in paths {
|
|
||||||
let _ = recently_used_xbel::update_recently_used(
|
|
||||||
&path.into(),
|
|
||||||
App::APP_ID.to_string(),
|
|
||||||
"cosmic-files".to_string(),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// No app matched for mimes and paths
|
// No app matched for mimes and paths
|
||||||
|
|
@ -2032,7 +2093,7 @@ impl Application for App {
|
||||||
app_themes,
|
app_themes,
|
||||||
compio_tx,
|
compio_tx,
|
||||||
context_page: ContextPage::Preview(None, PreviewKind::Selected),
|
context_page: ContextPage::Preview(None, PreviewKind::Selected),
|
||||||
dialog_pages: VecDeque::new(),
|
dialog_pages: DialogPages::new(),
|
||||||
dialog_text_input: widget::Id::unique(),
|
dialog_text_input: widget::Id::unique(),
|
||||||
key_binds,
|
key_binds,
|
||||||
margin: HashMap::new(),
|
margin: HashMap::new(),
|
||||||
|
|
@ -2324,8 +2385,8 @@ impl Application for App {
|
||||||
let entity = self.tab_model.active();
|
let entity = self.tab_model.active();
|
||||||
|
|
||||||
// Close dialog if open
|
// Close dialog if open
|
||||||
if self.dialog_pages.pop_front().is_some() {
|
if let Some((_page, task)) = self.dialog_pages.pop_front() {
|
||||||
return Task::none();
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close gallery mode if open
|
// Close gallery mode if open
|
||||||
|
|
@ -2463,14 +2524,16 @@ impl Application for App {
|
||||||
let to = destination.0.to_path_buf();
|
let to = destination.0.to_path_buf();
|
||||||
let name = destination.1.to_str().unwrap_or_default().to_string();
|
let name = destination.1.to_str().unwrap_or_default().to_string();
|
||||||
let archive_type = ArchiveType::default();
|
let archive_type = ArchiveType::default();
|
||||||
self.dialog_pages.push_back(DialogPage::Compress {
|
return Task::batch([
|
||||||
paths,
|
self.dialog_pages.push_back(DialogPage::Compress {
|
||||||
to,
|
paths,
|
||||||
name,
|
to,
|
||||||
archive_type,
|
name,
|
||||||
password: None,
|
archive_type,
|
||||||
});
|
password: None,
|
||||||
return widget::text_input::focus(self.dialog_text_input.clone());
|
}),
|
||||||
|
widget::text_input::focus(self.dialog_text_input.clone()),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2575,11 +2638,52 @@ impl Application for App {
|
||||||
self.windows.insert(id, WindowKind::DesktopViewOptions);
|
self.windows.insert(id, WindowKind::DesktopViewOptions);
|
||||||
return command.map(|_id| cosmic::action::none());
|
return command.map(|_id| cosmic::action::none());
|
||||||
}
|
}
|
||||||
|
Message::DesktopDialogs(show) => {
|
||||||
|
if matches!(self.mode, Mode::Desktop) {
|
||||||
|
if show {
|
||||||
|
//TODO: would it be better to make this a layer surface?
|
||||||
|
let mut settings = window::Settings {
|
||||||
|
decorations: false,
|
||||||
|
level: window::Level::AlwaysOnTop,
|
||||||
|
max_size: Some(Size::new(1280.0, 640.0)),
|
||||||
|
min_size: Some(Size::new(320.0, 180.0)),
|
||||||
|
position: window::Position::Centered,
|
||||||
|
resizable: false,
|
||||||
|
size: Size::new(640.0, 320.0),
|
||||||
|
transparent: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
// Use the dialog ID to make it float
|
||||||
|
settings.platform_specific.application_id =
|
||||||
|
"com.system76.CosmicFilesDialog".to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
let (id, command) = window::open(settings);
|
||||||
|
self.windows
|
||||||
|
.insert(id, WindowKind::Dialogs(widget::Id::unique()));
|
||||||
|
return command.map(|_id| cosmic::Action::None);
|
||||||
|
} else {
|
||||||
|
let mut tasks = Vec::new();
|
||||||
|
for (id, kind) in self.windows.iter() {
|
||||||
|
if matches!(kind, WindowKind::Dialogs(_)) {
|
||||||
|
tasks.push(window::close(*id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Task::batch(tasks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Message::DialogCancel => {
|
Message::DialogCancel => {
|
||||||
self.dialog_pages.pop_front();
|
if let Some((_page, task)) = self.dialog_pages.pop_front() {
|
||||||
|
return task;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Message::DialogComplete => {
|
Message::DialogComplete => {
|
||||||
if let Some(dialog_page) = self.dialog_pages.pop_front() {
|
if let Some((dialog_page, task)) = self.dialog_pages.pop_front() {
|
||||||
|
let mut tasks = vec![task];
|
||||||
match dialog_page {
|
match dialog_page {
|
||||||
DialogPage::Compress {
|
DialogPage::Compress {
|
||||||
paths,
|
paths,
|
||||||
|
|
@ -2631,13 +2735,13 @@ impl Application for App {
|
||||||
auth,
|
auth,
|
||||||
auth_tx,
|
auth_tx,
|
||||||
} => {
|
} => {
|
||||||
return Task::perform(
|
tasks.push(Task::perform(
|
||||||
async move {
|
async move {
|
||||||
auth_tx.send(auth).await.unwrap();
|
auth_tx.send(auth).await.unwrap();
|
||||||
cosmic::action::none()
|
cosmic::action::none()
|
||||||
},
|
},
|
||||||
|x| x,
|
|x| x,
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
DialogPage::NetworkError {
|
DialogPage::NetworkError {
|
||||||
mounter_key: _,
|
mounter_key: _,
|
||||||
|
|
@ -2645,10 +2749,8 @@ impl Application for App {
|
||||||
error: _,
|
error: _,
|
||||||
} => {
|
} => {
|
||||||
//TODO: re-use mounter_key?
|
//TODO: re-use mounter_key?
|
||||||
return Task::batch([
|
tasks.push(self.update(Message::NetworkDriveInput(uri)));
|
||||||
self.update(Message::NetworkDriveInput(uri)),
|
tasks.push(self.update(Message::NetworkDriveSubmit));
|
||||||
self.update(Message::NetworkDriveSubmit),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
DialogPage::NewItem { parent, name, dir } => {
|
DialogPage::NewItem { parent, name, dir } => {
|
||||||
let path = parent.join(name);
|
let path = parent.join(name);
|
||||||
|
|
@ -2723,15 +2825,14 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return Task::batch(tasks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::DialogPush(dialog_page) => {
|
Message::DialogPush(dialog_page) => {
|
||||||
self.dialog_pages.push_back(dialog_page);
|
return self.dialog_pages.push_back(dialog_page);
|
||||||
}
|
}
|
||||||
Message::DialogUpdate(dialog_page) => {
|
Message::DialogUpdate(dialog_page) => {
|
||||||
if !self.dialog_pages.is_empty() {
|
self.dialog_pages.update_front(dialog_page);
|
||||||
self.dialog_pages[0] = dialog_page;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Message::DialogUpdateComplete(dialog_page) => {
|
Message::DialogUpdateComplete(dialog_page) => {
|
||||||
return Task::batch([
|
return Task::batch([
|
||||||
|
|
@ -2944,7 +3045,7 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
log::warn!("failed to connect to {:?}: {}", item, error);
|
log::warn!("failed to connect to {:?}: {}", item, error);
|
||||||
self.dialog_pages.push_back(DialogPage::MountError {
|
return self.dialog_pages.push_back(DialogPage::MountError {
|
||||||
mounter_key,
|
mounter_key,
|
||||||
item,
|
item,
|
||||||
error,
|
error,
|
||||||
|
|
@ -2952,13 +3053,15 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Message::NetworkAuth(mounter_key, uri, auth, auth_tx) => {
|
Message::NetworkAuth(mounter_key, uri, auth, auth_tx) => {
|
||||||
self.dialog_pages.push_back(DialogPage::NetworkAuth {
|
return Task::batch([
|
||||||
mounter_key,
|
self.dialog_pages.push_back(DialogPage::NetworkAuth {
|
||||||
uri,
|
mounter_key,
|
||||||
auth,
|
uri,
|
||||||
auth_tx,
|
auth,
|
||||||
});
|
auth_tx,
|
||||||
return widget::text_input::focus(self.dialog_text_input.clone());
|
}),
|
||||||
|
widget::text_input::focus(self.dialog_text_input.clone()),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
Message::NetworkDriveInput(input) => {
|
Message::NetworkDriveInput(input) => {
|
||||||
self.network_drive_input = input;
|
self.network_drive_input = input;
|
||||||
|
|
@ -2993,7 +3096,7 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
log::warn!("failed to connect to {:?}: {}", uri, error);
|
log::warn!("failed to connect to {:?}: {}", uri, error);
|
||||||
self.dialog_pages.push_back(DialogPage::NetworkError {
|
return self.dialog_pages.push_back(DialogPage::NetworkError {
|
||||||
mounter_key,
|
mounter_key,
|
||||||
uri,
|
uri,
|
||||||
error,
|
error,
|
||||||
|
|
@ -3005,12 +3108,14 @@ 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());
|
||||||
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
|
if let Some(tab) = self.tab_model.data_mut::<Tab>(entity) {
|
||||||
if let Some(path) = &tab.location.path_opt() {
|
if let Some(path) = &tab.location.path_opt() {
|
||||||
self.dialog_pages.push_back(DialogPage::NewItem {
|
return Task::batch([
|
||||||
parent: path.to_path_buf(),
|
self.dialog_pages.push_back(DialogPage::NewItem {
|
||||||
name: String::new(),
|
parent: path.to_path_buf(),
|
||||||
dir,
|
name: String::new(),
|
||||||
});
|
dir,
|
||||||
return widget::text_input::focus(self.dialog_text_input.clone());
|
}),
|
||||||
|
widget::text_input::focus(self.dialog_text_input.clone()),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3171,11 +3276,14 @@ impl Application for App {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Message::OpenWithBrowse => match self.dialog_pages.pop_front() {
|
Message::OpenWithBrowse => match self.dialog_pages.pop_front() {
|
||||||
Some(DialogPage::OpenWith {
|
Some((
|
||||||
mime,
|
DialogPage::OpenWith {
|
||||||
store_opt: Some(app),
|
mime,
|
||||||
..
|
store_opt: Some(app),
|
||||||
}) => {
|
..
|
||||||
|
},
|
||||||
|
task,
|
||||||
|
)) => {
|
||||||
let url = format!("mime:///{mime}");
|
let url = format!("mime:///{mime}");
|
||||||
// TODO: Support multiple URLs
|
// TODO: Support multiple URLs
|
||||||
if let Some(mut command) =
|
if let Some(mut command) =
|
||||||
|
|
@ -3191,9 +3299,11 @@ impl Application for App {
|
||||||
app.id
|
app.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return task;
|
||||||
}
|
}
|
||||||
Some(dialog_page) => {
|
Some((dialog_page, task)) => {
|
||||||
self.dialog_pages.push_front(dialog_page);
|
log::warn!("tried to open with browse from the wrong dialog");
|
||||||
|
return Task::batch([task, self.dialog_pages.push_front(dialog_page)]);
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
},
|
},
|
||||||
|
|
@ -3346,16 +3456,17 @@ impl Application for App {
|
||||||
self.progress_operations.clear();
|
self.progress_operations.clear();
|
||||||
}
|
}
|
||||||
Message::PendingError(id, err) => {
|
Message::PendingError(id, err) => {
|
||||||
|
let mut tasks = Vec::new();
|
||||||
if let Some((op, controller)) = self.pending_operations.remove(&id) {
|
if let Some((op, controller)) = self.pending_operations.remove(&id) {
|
||||||
// Only show dialog if not cancelled
|
// Only show dialog if not cancelled
|
||||||
if !controller.is_cancelled() {
|
if !controller.is_cancelled() {
|
||||||
self.dialog_pages.push_back(match err.kind {
|
tasks.push(self.dialog_pages.push_back(match err.kind {
|
||||||
OperationErrorType::Generic(_) => DialogPage::FailedOperation(id),
|
OperationErrorType::Generic(_) => DialogPage::FailedOperation(id),
|
||||||
OperationErrorType::PasswordRequired => DialogPage::ExtractPassword {
|
OperationErrorType::PasswordRequired => DialogPage::ExtractPassword {
|
||||||
id,
|
id,
|
||||||
password: String::from(""),
|
password: String::from(""),
|
||||||
},
|
},
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
// Remove from progress
|
// Remove from progress
|
||||||
self.progress_operations.remove(&id);
|
self.progress_operations.remove(&id);
|
||||||
|
|
@ -3371,7 +3482,8 @@ impl Application for App {
|
||||||
self.progress_operations.clear();
|
self.progress_operations.clear();
|
||||||
}
|
}
|
||||||
// Manually rescan any trash tabs after any operation is completed
|
// Manually rescan any trash tabs after any operation is completed
|
||||||
return self.rescan_trash();
|
tasks.push(self.rescan_trash());
|
||||||
|
return Task::batch(tasks);
|
||||||
}
|
}
|
||||||
Message::PendingPause(id, pause) => {
|
Message::PendingPause(id, pause) => {
|
||||||
if let Some((_, controller)) = self.pending_operations.get(&id) {
|
if let Some((_, controller)) = self.pending_operations.get(&id) {
|
||||||
|
|
@ -3473,6 +3585,7 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
if !selected.is_empty() {
|
if !selected.is_empty() {
|
||||||
//TODO: batch rename
|
//TODO: batch rename
|
||||||
|
let mut tasks = Vec::new();
|
||||||
for path in selected {
|
for path in selected {
|
||||||
let parent = match path.parent() {
|
let parent = match path.parent() {
|
||||||
Some(some) => some.to_path_buf(),
|
Some(some) => some.to_path_buf(),
|
||||||
|
|
@ -3483,20 +3596,21 @@ impl Application for App {
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
let dir = path.is_dir();
|
let dir = path.is_dir();
|
||||||
self.dialog_pages.push_back(DialogPage::RenameItem {
|
tasks.push(self.dialog_pages.push_back(DialogPage::RenameItem {
|
||||||
from: path,
|
from: path,
|
||||||
parent,
|
parent,
|
||||||
name,
|
name,
|
||||||
dir,
|
dir,
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
return widget::text_input::focus(self.dialog_text_input.clone());
|
tasks.push(widget::text_input::focus(self.dialog_text_input.clone()));
|
||||||
|
return Task::batch(tasks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::ReplaceResult(replace_result) => {
|
Message::ReplaceResult(replace_result) => {
|
||||||
if let Some(dialog_page) = self.dialog_pages.pop_front() {
|
if let Some((dialog_page, task)) = self.dialog_pages.pop_front() {
|
||||||
match dialog_page {
|
match dialog_page {
|
||||||
DialogPage::Replace { tx, .. } => {
|
DialogPage::Replace { tx, .. } => {
|
||||||
return Task::perform(
|
return Task::perform(
|
||||||
|
|
@ -3509,7 +3623,7 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
log::warn!("tried to send replace result to the wrong dialog");
|
log::warn!("tried to send replace result to the wrong dialog");
|
||||||
self.dialog_pages.push_front(other);
|
return Task::batch([task, self.dialog_pages.push_front(other)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3715,7 +3829,7 @@ impl Application for App {
|
||||||
commands.push(self.update(Message::PasteContents(to, from)));
|
commands.push(self.update(Message::PasteContents(to, from)));
|
||||||
}
|
}
|
||||||
tab::Command::EmptyTrash => {
|
tab::Command::EmptyTrash => {
|
||||||
self.dialog_pages.push_back(DialogPage::EmptyTrash);
|
return self.dialog_pages.push_back(DialogPage::EmptyTrash);
|
||||||
}
|
}
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
tab::Command::ExecEntryAction(entry, action) => {
|
tab::Command::ExecEntryAction(entry, action) => {
|
||||||
|
|
@ -3949,6 +4063,9 @@ impl Application for App {
|
||||||
Message::WindowCloseRequested(id) => {
|
Message::WindowCloseRequested(id) => {
|
||||||
self.remove_window(&id);
|
self.remove_window(&id);
|
||||||
}
|
}
|
||||||
|
Message::WindowMaximize(id, maximized) => {
|
||||||
|
return window::maximize(id, maximized);
|
||||||
|
}
|
||||||
Message::WindowNew => match env::current_exe() {
|
Message::WindowNew => match env::current_exe() {
|
||||||
Ok(exe) => match process::Command::new(&exe).spawn() {
|
Ok(exe) => match process::Command::new(&exe).spawn() {
|
||||||
Ok(_child) => {}
|
Ok(_child) => {}
|
||||||
|
|
@ -4153,7 +4270,7 @@ impl Application for App {
|
||||||
.and_then(|x| x.path_opt())
|
.and_then(|x| x.path_opt())
|
||||||
.map(ToOwned::to_owned)
|
.map(ToOwned::to_owned)
|
||||||
{
|
{
|
||||||
self.open_file(&[path]);
|
return self.open_file(&[path]).into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NavMenuAction::OpenWith(entity) => {
|
NavMenuAction::OpenWith(entity) => {
|
||||||
|
|
@ -4282,7 +4399,7 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
NavMenuAction::EmptyTrash => {
|
NavMenuAction::EmptyTrash => {
|
||||||
self.dialog_pages.push_front(DialogPage::EmptyTrash);
|
return self.dialog_pages.push_front(DialogPage::EmptyTrash);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Message::Recents => {
|
Message::Recents => {
|
||||||
|
|
@ -5477,9 +5594,11 @@ impl Application for App {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut popover = widget::popover(tab_view);
|
let mut popover = widget::popover(tab_view);
|
||||||
|
/*
|
||||||
if let Some(dialog) = self.dialog() {
|
if let Some(dialog) = self.dialog() {
|
||||||
popover = popover.popup(dialog);
|
popover = popover.popup(dialog);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
tab_column = tab_column.push(popover);
|
tab_column = tab_column.push(popover);
|
||||||
|
|
||||||
// The toaster is added on top of an empty element to ensure that it does not override context menus
|
// The toaster is added on top of an empty element to ensure that it does not override context menus
|
||||||
|
|
@ -5507,6 +5626,10 @@ impl Application for App {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Some(WindowKind::DesktopViewOptions) => self.desktop_view_options(),
|
Some(WindowKind::DesktopViewOptions) => self.desktop_view_options(),
|
||||||
|
Some(WindowKind::Dialogs(id)) => match self.dialog() {
|
||||||
|
Some(element) => return widget::autosize::autosize(element, id.clone()).into(),
|
||||||
|
None => widget::horizontal_space().into(),
|
||||||
|
},
|
||||||
Some(WindowKind::Preview(entity_opt, kind)) => self
|
Some(WindowKind::Preview(entity_opt, kind)) => self
|
||||||
.preview(entity_opt, kind, false)
|
.preview(entity_opt, kind, false)
|
||||||
.map(|x| Message::TabMessage(*entity_opt, x)),
|
.map(|x| Message::TabMessage(*entity_opt, x)),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue