Skip to content

Commit ca0dd4a

Browse files
authored
Merge pull request #95 from DioxusLabs/jk/filedragindrop
File Drag and Drop support
2 parents 0369fe7 + 6bc45b1 commit ca0dd4a

File tree

5 files changed

+88
-74
lines changed

5 files changed

+88
-74
lines changed

examples/filedragdrop.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use dioxus::prelude::*;
2+
3+
fn main() {
4+
dioxus::desktop::launch_with_props(app, (), |c| {
5+
c.with_file_drop_handler(|w, e| {
6+
println!("{:?}", e);
7+
false
8+
})
9+
});
10+
}
11+
12+
fn app(cx: Scope) -> Element {
13+
cx.render(rsx!(
14+
div {
15+
h1 { "drag an file here" }
16+
}
17+
))
18+
}

examples/manual_edits.rs

Lines changed: 0 additions & 39 deletions
This file was deleted.

packages/desktop/src/cfg.rs

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,42 @@
1-
use dioxus_core::DomEdit;
21
use wry::{
3-
application::{event_loop::EventLoop, window::WindowBuilder},
4-
webview::WebView,
2+
application::{
3+
event_loop::EventLoop,
4+
window::{Window, WindowBuilder},
5+
},
6+
http::{Request as HttpRequest, Response as HttpResponse},
7+
webview::{FileDropEvent, WebView},
8+
Result as WryResult,
59
};
610

711
pub(crate) type DynEventHandlerFn = dyn Fn(&mut EventLoop<()>, &mut WebView);
812

9-
pub struct DesktopConfig<'a> {
13+
pub struct DesktopConfig {
1014
pub window: WindowBuilder,
11-
pub(crate) manual_edits: Option<Vec<DomEdit<'a>>>,
15+
pub file_drop_handler: Option<Box<dyn Fn(&Window, FileDropEvent) -> bool>>,
16+
pub protocos: Vec<WryProtocl>,
1217
pub(crate) pre_rendered: Option<String>,
1318
pub(crate) event_handler: Option<Box<DynEventHandlerFn>>,
1419
}
1520

16-
impl<'a> DesktopConfig<'a> {
21+
pub type WryProtocl = (
22+
String,
23+
Box<dyn Fn(&HttpRequest) -> WryResult<HttpResponse> + 'static>,
24+
);
25+
26+
impl DesktopConfig {
1727
/// Initializes a new `WindowBuilder` with default values.
1828
#[inline]
1929
pub fn new() -> Self {
2030
let window = WindowBuilder::new().with_title("Dioxus app");
2131
Self {
2232
event_handler: None,
2333
window,
34+
protocos: Vec::new(),
35+
file_drop_handler: None,
2436
pre_rendered: None,
25-
manual_edits: None,
2637
}
2738
}
2839

29-
pub fn with_edits(&mut self, edits: Vec<DomEdit<'a>>) -> &mut Self {
30-
self.manual_edits = Some(edits);
31-
self
32-
}
33-
3440
pub fn with_prerendered(&mut self, content: String) -> &mut Self {
3541
self.pre_rendered = Some(content);
3642
self
@@ -56,9 +62,25 @@ impl<'a> DesktopConfig<'a> {
5662
self.event_handler = Some(Box::new(handler));
5763
self
5864
}
65+
66+
pub fn with_file_drop_handler(
67+
&mut self,
68+
handler: impl Fn(&Window, FileDropEvent) -> bool + 'static,
69+
) -> &mut Self {
70+
self.file_drop_handler = Some(Box::new(handler));
71+
self
72+
}
73+
74+
pub fn with_custom_protocol<F>(mut self, name: String, handler: F) -> Self
75+
where
76+
F: Fn(&HttpRequest) -> WryResult<HttpResponse> + 'static,
77+
{
78+
self.protocos.push((name, Box::new(handler)));
79+
self
80+
}
5981
}
6082

61-
impl<'a> Default for DesktopConfig<'a> {
83+
impl Default for DesktopConfig {
6284
fn default() -> Self {
6385
Self::new()
6486
}

packages/desktop/src/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@
1515
<script type="text/javascript" src="index.js">
1616
</script>
1717

18-
</html>
18+
</html>

packages/desktop/src/lib.rs

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ pub fn launch(root: Component) {
116116
/// ```
117117
pub fn launch_cfg(
118118
root: Component,
119-
config_builder: impl for<'a, 'b> FnOnce(&'b mut DesktopConfig<'a>) -> &'b mut DesktopConfig<'a>,
119+
config_builder: impl FnOnce(&mut DesktopConfig) -> &mut DesktopConfig,
120120
) {
121121
launch_with_props(root, (), config_builder)
122122
}
@@ -147,7 +147,7 @@ pub fn launch_cfg(
147147
pub fn launch_with_props<P: 'static + Send>(
148148
root: Component<P>,
149149
props: P,
150-
builder: impl for<'a, 'b> FnOnce(&'b mut DesktopConfig<'a>) -> &'b mut DesktopConfig<'a>,
150+
builder: impl FnOnce(&mut DesktopConfig) -> &mut DesktopConfig,
151151
) {
152152
let mut cfg = DesktopConfig::new();
153153
builder(&mut cfg);
@@ -170,9 +170,11 @@ pub fn launch_with_props<P: 'static + Send>(
170170
let (is_ready, sender) = (desktop.is_ready.clone(), desktop.sender.clone());
171171

172172
let proxy = proxy.clone();
173-
let webview = WebViewBuilder::new(window)
173+
let file_handler = cfg.file_drop_handler.take();
174+
175+
let mut webview = WebViewBuilder::new(window)
174176
.unwrap()
175-
.with_url("wry://index.html/")
177+
.with_url("dioxus://index.html/")
176178
.unwrap()
177179
.with_rpc_handler(move |_window: &Window, req: RpcRequest| {
178180
match req.method.as_str() {
@@ -189,26 +191,37 @@ pub fn launch_with_props<P: 'static + Send>(
189191
}
190192
None
191193
})
192-
.with_custom_protocol("wry".into(), move |request| {
193-
// Any content that that uses the `wry://` scheme will be shuttled through this handler as a "special case"
194+
.with_custom_protocol("dioxus".into(), move |request| {
195+
// Any content that that uses the `dioxus://` scheme will be shuttled through this handler as a "special case"
194196
// For now, we only serve two pieces of content which get included as bytes into the final binary.
195-
let path = request.uri().replace("wry://", "");
196-
let (data, meta) = match path.as_str() {
197-
"index.html" | "index.html/" | "/index.html" => {
198-
(include_bytes!("./index.html").to_vec(), "text/html")
199-
}
200-
"index.html/index.js" => {
201-
(include_bytes!("./index.js").to_vec(), "text/javascript")
202-
}
203-
_ => (include_bytes!("./index.html").to_vec(), "text/html"),
204-
};
205-
206-
wry::http::ResponseBuilder::new().mimetype(meta).body(data)
197+
let path = request.uri().replace("dioxus://", "");
198+
199+
if path.trim_end_matches('/') == "index.html" {
200+
wry::http::ResponseBuilder::new()
201+
.mimetype("text/html")
202+
.body(include_bytes!("./index.html").to_vec())
203+
} else if path.trim_end_matches('/') == "index.html/index.js" {
204+
wry::http::ResponseBuilder::new()
205+
.mimetype("text/javascript")
206+
.body(include_bytes!("./index.js").to_vec())
207+
} else {
208+
wry::http::ResponseBuilder::new()
209+
.status(wry::http::status::StatusCode::NOT_FOUND)
210+
.body(format!("Not found: {}", path).as_bytes().to_vec())
211+
}
207212
})
208-
.build()
209-
.unwrap();
213+
.with_file_drop_handler(move |window, evet| {
214+
if let Some(handler) = file_handler.as_ref() {
215+
return handler(window, evet);
216+
}
217+
false
218+
});
219+
220+
for (name, handler) in cfg.protocos.drain(..) {
221+
webview = webview.with_custom_protocol(name, handler)
222+
}
210223

211-
desktop.webviews.insert(window_id, webview);
224+
desktop.webviews.insert(window_id, webview.build().unwrap());
212225
}
213226

214227
Event::WindowEvent {

0 commit comments

Comments
 (0)