mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 14:44:12 +00:00
Merge pull request #95 from DioxusLabs/jk/filedragindrop
File Drag and Drop support
This commit is contained in:
commit
ca0dd4aa71
5 changed files with 87 additions and 73 deletions
18
examples/filedragdrop.rs
Normal file
18
examples/filedragdrop.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::desktop::launch_with_props(app, (), |c| {
|
||||
c.with_file_drop_handler(|w, e| {
|
||||
println!("{:?}", e);
|
||||
false
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx!(
|
||||
div {
|
||||
h1 { "drag an file here" }
|
||||
}
|
||||
))
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
Example: Manual Edits
|
||||
|
||||
It's possible to manually provide a stream of DomEdits to a Dioxus Renderer. All renderers are designed to accept a stream
|
||||
of DomEdits that abstract over a stack machine. This allows the VirtualDOM to exist entirely separately from the RealDOM,
|
||||
though features like NodeRefs and NativeEvents might not work properly everywhere.
|
||||
*/
|
||||
|
||||
use dioxus::core::*;
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
use DomEdit::*;
|
||||
|
||||
let edits = vec![
|
||||
// create a container and push it onto the stack
|
||||
CreateElement {
|
||||
tag: "div",
|
||||
root: 0,
|
||||
},
|
||||
// create an element and push it onto the stack
|
||||
CreateElement { tag: "h1", root: 2 },
|
||||
// create a text node and push it onto the stack
|
||||
CreateTextNode {
|
||||
text: "hello world",
|
||||
root: 3,
|
||||
},
|
||||
// append the text node to the h1 element
|
||||
AppendChildren { many: 1 },
|
||||
// append the h1 element to the container
|
||||
AppendChildren { many: 1 },
|
||||
// append the container to the default render element ("dioxusroot" if used with default config)
|
||||
AppendChildren { many: 1 },
|
||||
];
|
||||
|
||||
let app: Component = |cx| cx.render(rsx!(div { "some app" }));
|
||||
|
||||
dioxus_desktop::launch_with_props(app, (), |c| c.with_edits(edits));
|
||||
}
|
|
@ -1,19 +1,29 @@
|
|||
use dioxus_core::DomEdit;
|
||||
use wry::{
|
||||
application::{event_loop::EventLoop, window::WindowBuilder},
|
||||
webview::WebView,
|
||||
application::{
|
||||
event_loop::EventLoop,
|
||||
window::{Window, WindowBuilder},
|
||||
},
|
||||
http::{Request as HttpRequest, Response as HttpResponse},
|
||||
webview::{FileDropEvent, WebView},
|
||||
Result as WryResult,
|
||||
};
|
||||
|
||||
pub(crate) type DynEventHandlerFn = dyn Fn(&mut EventLoop<()>, &mut WebView);
|
||||
|
||||
pub struct DesktopConfig<'a> {
|
||||
pub struct DesktopConfig {
|
||||
pub window: WindowBuilder,
|
||||
pub(crate) manual_edits: Option<Vec<DomEdit<'a>>>,
|
||||
pub file_drop_handler: Option<Box<dyn Fn(&Window, FileDropEvent) -> bool>>,
|
||||
pub protocos: Vec<WryProtocl>,
|
||||
pub(crate) pre_rendered: Option<String>,
|
||||
pub(crate) event_handler: Option<Box<DynEventHandlerFn>>,
|
||||
}
|
||||
|
||||
impl<'a> DesktopConfig<'a> {
|
||||
pub type WryProtocl = (
|
||||
String,
|
||||
Box<dyn Fn(&HttpRequest) -> WryResult<HttpResponse> + 'static>,
|
||||
);
|
||||
|
||||
impl DesktopConfig {
|
||||
/// Initializes a new `WindowBuilder` with default values.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
|
@ -21,16 +31,12 @@ impl<'a> DesktopConfig<'a> {
|
|||
Self {
|
||||
event_handler: None,
|
||||
window,
|
||||
protocos: Vec::new(),
|
||||
file_drop_handler: None,
|
||||
pre_rendered: None,
|
||||
manual_edits: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_edits(&mut self, edits: Vec<DomEdit<'a>>) -> &mut Self {
|
||||
self.manual_edits = Some(edits);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_prerendered(&mut self, content: String) -> &mut Self {
|
||||
self.pre_rendered = Some(content);
|
||||
self
|
||||
|
@ -56,9 +62,25 @@ impl<'a> DesktopConfig<'a> {
|
|||
self.event_handler = Some(Box::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_file_drop_handler(
|
||||
&mut self,
|
||||
handler: impl Fn(&Window, FileDropEvent) -> bool + 'static,
|
||||
) -> &mut Self {
|
||||
self.file_drop_handler = Some(Box::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_custom_protocol<F>(mut self, name: String, handler: F) -> Self
|
||||
where
|
||||
F: Fn(&HttpRequest) -> WryResult<HttpResponse> + 'static,
|
||||
{
|
||||
self.protocos.push((name, Box::new(handler)));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Default for DesktopConfig<'a> {
|
||||
impl Default for DesktopConfig {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
<script type="text/javascript" src="index.js">
|
||||
</script>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -116,7 +116,7 @@ pub fn launch(root: Component) {
|
|||
/// ```
|
||||
pub fn launch_cfg(
|
||||
root: Component,
|
||||
config_builder: impl for<'a, 'b> FnOnce(&'b mut DesktopConfig<'a>) -> &'b mut DesktopConfig<'a>,
|
||||
config_builder: impl FnOnce(&mut DesktopConfig) -> &mut DesktopConfig,
|
||||
) {
|
||||
launch_with_props(root, (), config_builder)
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ pub fn launch_cfg(
|
|||
pub fn launch_with_props<P: 'static + Send>(
|
||||
root: Component<P>,
|
||||
props: P,
|
||||
builder: impl for<'a, 'b> FnOnce(&'b mut DesktopConfig<'a>) -> &'b mut DesktopConfig<'a>,
|
||||
builder: impl FnOnce(&mut DesktopConfig) -> &mut DesktopConfig,
|
||||
) {
|
||||
let mut cfg = DesktopConfig::new();
|
||||
builder(&mut cfg);
|
||||
|
@ -170,9 +170,11 @@ pub fn launch_with_props<P: 'static + Send>(
|
|||
let (is_ready, sender) = (desktop.is_ready.clone(), desktop.sender.clone());
|
||||
|
||||
let proxy = proxy.clone();
|
||||
let webview = WebViewBuilder::new(window)
|
||||
let file_handler = cfg.file_drop_handler.take();
|
||||
|
||||
let mut webview = WebViewBuilder::new(window)
|
||||
.unwrap()
|
||||
.with_url("wry://index.html/")
|
||||
.with_url("dioxus://index.html/")
|
||||
.unwrap()
|
||||
.with_rpc_handler(move |_window: &Window, req: RpcRequest| {
|
||||
match req.method.as_str() {
|
||||
|
@ -189,26 +191,37 @@ pub fn launch_with_props<P: 'static + Send>(
|
|||
}
|
||||
None
|
||||
})
|
||||
.with_custom_protocol("wry".into(), move |request| {
|
||||
// Any content that that uses the `wry://` scheme will be shuttled through this handler as a "special case"
|
||||
.with_custom_protocol("dioxus".into(), move |request| {
|
||||
// Any content that that uses the `dioxus://` scheme will be shuttled through this handler as a "special case"
|
||||
// For now, we only serve two pieces of content which get included as bytes into the final binary.
|
||||
let path = request.uri().replace("wry://", "");
|
||||
let (data, meta) = match path.as_str() {
|
||||
"index.html" | "index.html/" | "/index.html" => {
|
||||
(include_bytes!("./index.html").to_vec(), "text/html")
|
||||
}
|
||||
"index.html/index.js" => {
|
||||
(include_bytes!("./index.js").to_vec(), "text/javascript")
|
||||
}
|
||||
_ => (include_bytes!("./index.html").to_vec(), "text/html"),
|
||||
};
|
||||
let path = request.uri().replace("dioxus://", "");
|
||||
|
||||
wry::http::ResponseBuilder::new().mimetype(meta).body(data)
|
||||
if path.trim_end_matches('/') == "index.html" {
|
||||
wry::http::ResponseBuilder::new()
|
||||
.mimetype("text/html")
|
||||
.body(include_bytes!("./index.html").to_vec())
|
||||
} else if path.trim_end_matches('/') == "index.html/index.js" {
|
||||
wry::http::ResponseBuilder::new()
|
||||
.mimetype("text/javascript")
|
||||
.body(include_bytes!("./index.js").to_vec())
|
||||
} else {
|
||||
wry::http::ResponseBuilder::new()
|
||||
.status(wry::http::status::StatusCode::NOT_FOUND)
|
||||
.body(format!("Not found: {}", path).as_bytes().to_vec())
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.unwrap();
|
||||
.with_file_drop_handler(move |window, evet| {
|
||||
if let Some(handler) = file_handler.as_ref() {
|
||||
return handler(window, evet);
|
||||
}
|
||||
false
|
||||
});
|
||||
|
||||
desktop.webviews.insert(window_id, webview);
|
||||
for (name, handler) in cfg.protocos.drain(..) {
|
||||
webview = webview.with_custom_protocol(name, handler)
|
||||
}
|
||||
|
||||
desktop.webviews.insert(window_id, webview.build().unwrap());
|
||||
}
|
||||
|
||||
Event::WindowEvent {
|
||||
|
|
Loading…
Reference in a new issue