Prompt for paths asynchronously to avoid double borrow
This commit is contained in:
parent
29d2236ed2
commit
cf23b0e4a2
7 changed files with 70 additions and 35 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -903,6 +903,7 @@ dependencies = [
|
||||||
"async-std",
|
"async-std",
|
||||||
"async-task",
|
"async-task",
|
||||||
"bindgen",
|
"bindgen",
|
||||||
|
"block",
|
||||||
"cc",
|
"cc",
|
||||||
"cocoa",
|
"cocoa",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
|
|
|
@ -37,6 +37,7 @@ simplelog = "0.9"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
block = "0.1"
|
||||||
cocoa = "0.24"
|
cocoa = "0.24"
|
||||||
core-foundation = "0.9"
|
core-foundation = "0.9"
|
||||||
core-graphics = "0.22.2"
|
core-graphics = "0.22.2"
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
platform::{self, WindowOptions},
|
platform::{self, WindowOptions},
|
||||||
presenter::Presenter,
|
presenter::Presenter,
|
||||||
util::post_inc,
|
util::post_inc,
|
||||||
AssetCache, AssetSource, ClipboardItem, FontCache, TextLayoutCache,
|
AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use async_std::sync::Condvar;
|
use async_std::sync::Condvar;
|
||||||
|
@ -570,6 +570,22 @@ impl MutableAppContext {
|
||||||
self.platform.set_menus(menus);
|
self.platform.set_menus(menus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn prompt_for_paths<F>(&self, options: PathPromptOptions, done_fn: F)
|
||||||
|
where
|
||||||
|
F: 'static + FnOnce(Option<Vec<PathBuf>>, &mut MutableAppContext),
|
||||||
|
{
|
||||||
|
let app = self.weak_self.as_ref().unwrap().upgrade().unwrap();
|
||||||
|
let foreground = self.foreground.clone();
|
||||||
|
self.platform().prompt_for_paths(
|
||||||
|
options,
|
||||||
|
Box::new(move |paths| {
|
||||||
|
foreground
|
||||||
|
.spawn(async move { (done_fn)(paths, &mut *app.borrow_mut()) })
|
||||||
|
.detach();
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn dispatch_action<T: 'static + Any>(
|
pub fn dispatch_action<T: 'static + Any>(
|
||||||
&mut self,
|
&mut self,
|
||||||
window_id: usize,
|
window_id: usize,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::{BoolExt as _, Dispatcher, FontSystem, Window};
|
use super::{BoolExt as _, Dispatcher, FontSystem, Window};
|
||||||
use crate::{executor, keymap::Keystroke, platform, ClipboardItem, Event, Menu, MenuItem};
|
use crate::{executor, keymap::Keystroke, platform, ClipboardItem, Event, Menu, MenuItem};
|
||||||
|
use block::ConcreteBlock;
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{
|
appkit::{
|
||||||
NSApplication, NSApplicationActivationPolicy::NSApplicationActivationPolicyRegular,
|
NSApplication, NSApplicationActivationPolicy::NSApplicationActivationPolicyRegular,
|
||||||
|
@ -20,7 +21,7 @@ use objc::{
|
||||||
use ptr::null_mut;
|
use ptr::null_mut;
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
cell::RefCell,
|
cell::{Cell, RefCell},
|
||||||
convert::TryInto,
|
convert::TryInto,
|
||||||
ffi::{c_void, CStr},
|
ffi::{c_void, CStr},
|
||||||
os::raw::c_char,
|
os::raw::c_char,
|
||||||
|
@ -267,31 +268,40 @@ impl platform::Platform for MacPlatform {
|
||||||
fn prompt_for_paths(
|
fn prompt_for_paths(
|
||||||
&self,
|
&self,
|
||||||
options: platform::PathPromptOptions,
|
options: platform::PathPromptOptions,
|
||||||
) -> Option<Vec<std::path::PathBuf>> {
|
done_fn: Box<dyn FnOnce(Option<Vec<std::path::PathBuf>>)>,
|
||||||
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let panel = NSOpenPanel::openPanel(nil);
|
let panel = NSOpenPanel::openPanel(nil);
|
||||||
panel.setCanChooseDirectories_(options.directories.to_objc());
|
panel.setCanChooseDirectories_(options.directories.to_objc());
|
||||||
panel.setCanChooseFiles_(options.files.to_objc());
|
panel.setCanChooseFiles_(options.files.to_objc());
|
||||||
panel.setAllowsMultipleSelection_(options.multiple.to_objc());
|
panel.setAllowsMultipleSelection_(options.multiple.to_objc());
|
||||||
panel.setResolvesAliases_(false.to_objc());
|
panel.setResolvesAliases_(false.to_objc());
|
||||||
let response = panel.runModal();
|
let done_fn = Cell::new(Some(done_fn));
|
||||||
if response == NSModalResponse::NSModalResponseOk {
|
let block = ConcreteBlock::new(move |response: NSModalResponse| {
|
||||||
let mut result = Vec::new();
|
let result = if response == NSModalResponse::NSModalResponseOk {
|
||||||
let urls = panel.URLs();
|
let mut result = Vec::new();
|
||||||
for i in 0..urls.count() {
|
let urls = panel.URLs();
|
||||||
let url = urls.objectAtIndex(i);
|
for i in 0..urls.count() {
|
||||||
let string = url.absoluteString();
|
let url = urls.objectAtIndex(i);
|
||||||
let string = std::ffi::CStr::from_ptr(string.UTF8String())
|
let string = url.absoluteString();
|
||||||
.to_string_lossy()
|
let string = std::ffi::CStr::from_ptr(string.UTF8String())
|
||||||
.to_string();
|
.to_string_lossy()
|
||||||
if let Some(path) = string.strip_prefix("file://") {
|
.to_string();
|
||||||
result.push(PathBuf::from(path));
|
if let Some(path) = string.strip_prefix("file://") {
|
||||||
|
result.push(PathBuf::from(path));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Some(result)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(done_fn) = done_fn.take() {
|
||||||
|
(done_fn)(result);
|
||||||
}
|
}
|
||||||
Some(result)
|
});
|
||||||
} else {
|
let block = block.copy();
|
||||||
None
|
let _: () = msg_send![panel, beginWithCompletionHandler: block];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,11 @@ pub trait Platform {
|
||||||
executor: Rc<executor::Foreground>,
|
executor: Rc<executor::Foreground>,
|
||||||
) -> Box<dyn Window>;
|
) -> Box<dyn Window>;
|
||||||
fn key_window_id(&self) -> Option<usize>;
|
fn key_window_id(&self) -> Option<usize>;
|
||||||
fn prompt_for_paths(&self, options: PathPromptOptions) -> Option<Vec<PathBuf>>;
|
fn prompt_for_paths(
|
||||||
|
&self,
|
||||||
|
options: PathPromptOptions,
|
||||||
|
done_fn: Box<dyn FnOnce(Option<Vec<std::path::PathBuf>>)>,
|
||||||
|
);
|
||||||
fn quit(&self);
|
fn quit(&self);
|
||||||
fn write_to_clipboard(&self, item: ClipboardItem);
|
fn write_to_clipboard(&self, item: ClipboardItem);
|
||||||
fn read_from_clipboard(&self) -> Option<ClipboardItem>;
|
fn read_from_clipboard(&self) -> Option<ClipboardItem>;
|
||||||
|
|
|
@ -70,8 +70,11 @@ impl super::Platform for Platform {
|
||||||
|
|
||||||
fn quit(&self) {}
|
fn quit(&self) {}
|
||||||
|
|
||||||
fn prompt_for_paths(&self, _: super::PathPromptOptions) -> Option<Vec<std::path::PathBuf>> {
|
fn prompt_for_paths(
|
||||||
None
|
&self,
|
||||||
|
_: super::PathPromptOptions,
|
||||||
|
_: Box<dyn FnOnce(Option<Vec<std::path::PathBuf>>)>,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_to_clipboard(&self, item: ClipboardItem) {
|
fn write_to_clipboard(&self, item: ClipboardItem) {
|
||||||
|
|
|
@ -29,19 +29,19 @@ pub struct OpenParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open(settings: &Receiver<Settings>, ctx: &mut MutableAppContext) {
|
fn open(settings: &Receiver<Settings>, ctx: &mut MutableAppContext) {
|
||||||
if let Some(paths) = ctx.platform().prompt_for_paths(PathPromptOptions {
|
let settings = settings.clone();
|
||||||
files: true,
|
ctx.prompt_for_paths(
|
||||||
directories: true,
|
PathPromptOptions {
|
||||||
multiple: true,
|
files: true,
|
||||||
}) {
|
directories: true,
|
||||||
ctx.dispatch_global_action(
|
multiple: true,
|
||||||
"workspace:open_paths",
|
},
|
||||||
OpenParams {
|
move |paths, ctx| {
|
||||||
paths,
|
if let Some(paths) = paths {
|
||||||
settings: settings.clone(),
|
ctx.dispatch_global_action("workspace:open_paths", OpenParams { paths, settings });
|
||||||
},
|
}
|
||||||
);
|
},
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_paths(params: &OpenParams, app: &mut MutableAppContext) {
|
fn open_paths(params: &OpenParams, app: &mut MutableAppContext) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue