Merge branch 'upstream' into disable-browser-shortcuts

This commit is contained in:
Evan Almloff committed 2023-04-12 09:09:36 -05:00
commit bc014f7107
7 files changed
+113 -12

No files matched your search

+36
View File
@@ -0,0 +1,36 @@
//! Comparison example with leptos' counter example
//! https://github.com/leptos-rs/leptos/blob/main/examples/counters/src/lib.rs
use dioxus::prelude::*;
fn main() {
dioxus_desktop::launch(app);
}
fn app(cx: Scope) -> Element {
let counters = use_state(cx, || vec![0, 0, 0]);
let sum: usize = counters.iter().copied().sum();
render! {
div {
button { onclick: move |_| counters.make_mut().push(0), "Add counter" }
button { onclick: move |_| { counters.make_mut().pop(); }, "Remove counter" }
p { "Total: {sum}" }
for (i, counter) in counters.iter().enumerate() {
li {
button { onclick: move |_| counters.make_mut()[i] -= 1, "-1" }
input {
value: "{counter}",
oninput: move |e| {
if let Ok(value) = e.value.parse::<usize>() {
counters.make_mut()[i] = value;
}
}
}
button { onclick: move |_| counters.make_mut()[i] += 1, "+1" }
button { onclick: move |_| { counters.make_mut().remove(i); }, "x" }
}
}
}
}
}
+4 -2
View File
@@ -36,8 +36,8 @@ use tao::{
}; };
pub use wry; pub use wry;
pub use wry::application as tao; pub use wry::application as tao;
use wry::application::window::WindowId;
use wry::webview::WebView; use wry::webview::WebView;
use wry::{application::window::WindowId, webview::WebContext};
/// Launch the WebView and run the event loop. /// Launch the WebView and run the event loop.
/// ///
@@ -281,7 +281,7 @@ fn create_new_window(
event_handlers: &WindowEventHandlers, event_handlers: &WindowEventHandlers,
shortcut_manager: ShortcutRegistry, shortcut_manager: ShortcutRegistry,
) -> WebviewHandler { ) -> WebviewHandler {
let webview = webview::build(&mut cfg, event_loop, proxy.clone()); let (webview, web_context) = webview::build(&mut cfg, event_loop, proxy.clone());
dom.base_scope().provide_context(DesktopContext::new( dom.base_scope().provide_context(DesktopContext::new(
webview.clone(), webview.clone(),
@@ -299,6 +299,7 @@ fn create_new_window(
webview, webview,
dom, dom,
waker: waker::tao_waker(proxy, id), waker: waker::tao_waker(proxy, id),
web_context,
} }
} }
@@ -306,6 +307,7 @@ struct WebviewHandler {
dom: VirtualDom, dom: VirtualDom,
webview: Rc<wry::webview::WebView>, webview: Rc<wry::webview::WebView>,
waker: Waker, waker: Waker,
web_context: WebContext,
} }
/// Poll the virtualdom until it's pending /// Poll the virtualdom until it's pending
+7 -4
View File
@@ -7,13 +7,13 @@ use tao::event_loop::{EventLoopProxy, EventLoopWindowTarget};
pub use wry; pub use wry;
pub use wry::application as tao; pub use wry::application as tao;
use wry::application::window::Window; use wry::application::window::Window;
use wry::webview::{WebView, WebViewBuilder}; use wry::webview::{WebContext, WebView, WebViewBuilder};
pub fn build( pub fn build(
cfg: &mut Config, cfg: &mut Config,
event_loop: &EventLoopWindowTarget<UserWindowEvent>, event_loop: &EventLoopWindowTarget<UserWindowEvent>,
proxy: EventLoopProxy<UserWindowEvent>, proxy: EventLoopProxy<UserWindowEvent>,
) -> Rc<WebView> { ) -> (Rc<WebView>, WebContext) {
let builder = cfg.window.clone(); let builder = cfg.window.clone();
let window = builder.build(event_loop).unwrap(); let window = builder.build(event_loop).unwrap();
let file_handler = cfg.file_drop_handler.take(); let file_handler = cfg.file_drop_handler.take();
@@ -33,6 +33,8 @@ pub fn build(
)); ));
} }
let mut web_context = WebContext::new(cfg.data_dir.clone());
let mut webview = WebViewBuilder::new(window) let mut webview = WebViewBuilder::new(window)
.unwrap() .unwrap()
.with_transparent(cfg.window.window.transparent) .with_transparent(cfg.window.window.transparent)
@@ -52,7 +54,8 @@ pub fn build(
.as_ref() .as_ref()
.map(|handler| handler(window, evet)) .map(|handler| handler(window, evet))
.unwrap_or_default() .unwrap_or_default()
}); })
.with_web_context(&mut web_context);
#[cfg(windows)] #[cfg(windows)]
{ {
@@ -89,5 +92,5 @@ pub fn build(
webview = webview.with_devtools(true); webview = webview.with_devtools(true);
} }
Rc::new(webview.build().unwrap()) (Rc::new(webview.build().unwrap()), web_context)
} }
+15 -1
View File
@@ -23,6 +23,8 @@ pub enum Segment {
// This will be true if there are static styles // This will be true if there are static styles
inside_style_tag: bool, inside_style_tag: bool,
}, },
/// A marker for where to insert a dynamic inner html
InnerHtmlMarker,
} }
impl std::fmt::Write for StringChain { impl std::fmt::Write for StringChain {
@@ -69,6 +71,9 @@ impl StringCache {
write!(chain, "<{tag}")?; write!(chain, "<{tag}")?;
// we need to collect the styles and write them at the end // we need to collect the styles and write them at the end
let mut styles = Vec::new(); let mut styles = Vec::new();
// we need to collect the inner html and write it at the end
let mut inner_html = None;
// we need to keep track of if we have dynamic attrs to know if we need to insert a style and inner_html marker
let mut has_dynamic_attrs = false; let mut has_dynamic_attrs = false;
for attr in *attrs { for attr in *attrs {
match attr { match attr {
@@ -77,7 +82,9 @@ impl StringCache {
value, value,
namespace, namespace,
} => { } => {
if let Some("style") = namespace { if *name == "dangerous_inner_html" {
inner_html = Some(value);
} else if let Some("style") = namespace {
styles.push((name, value)); styles.push((name, value));
} else { } else {
write!(chain, " {name}=\"{value}\"")?; write!(chain, " {name}=\"{value}\"")?;
@@ -110,6 +117,13 @@ impl StringCache {
write!(chain, "/>")?; write!(chain, "/>")?;
} else { } else {
write!(chain, ">")?; write!(chain, ">")?;
// Write the static inner html, or insert a marker if dynamic inner html is possible
if let Some(inner_html) = inner_html {
chain.write_str(inner_html)?;
} else if has_dynamic_attrs {
chain.segments.push(Segment::InnerHtmlMarker);
}
for child in *children { for child in *children {
Self::recurse(child, cur_path, root_idx, chain)?; Self::recurse(child, cur_path, root_idx, chain)?;
} }
+21 -2
View File
@@ -70,6 +70,8 @@ impl Renderer {
.or_insert_with(|| Rc::new(StringCache::from_template(template).unwrap())) .or_insert_with(|| Rc::new(StringCache::from_template(template).unwrap()))
.clone(); .clone();
let mut inner_html = None;
// We need to keep track of the dynamic styles so we can insert them into the right place // We need to keep track of the dynamic styles so we can insert them into the right place
let mut accumulated_dynamic_styles = Vec::new(); let mut accumulated_dynamic_styles = Vec::new();
@@ -77,7 +79,9 @@ impl Renderer {
match segment { match segment {
Segment::Attr(idx) => { Segment::Attr(idx) => {
let attr = &template.dynamic_attrs[*idx]; let attr = &template.dynamic_attrs[*idx];
if attr.namespace == Some("style") { if attr.name == "dangerous_inner_html" {
inner_html = Some(attr);
} else if attr.namespace == Some("style") {
accumulated_dynamic_styles.push(attr); accumulated_dynamic_styles.push(attr);
} else { } else {
match attr.value { match attr.value {
@@ -165,6 +169,19 @@ impl Renderer {
accumulated_dynamic_styles.clear(); accumulated_dynamic_styles.clear();
} }
} }
Segment::InnerHtmlMarker => {
if let Some(inner_html) = inner_html.take() {
let inner_html = &inner_html.value;
match inner_html {
AttributeValue::Text(value) => write!(buf, "{}", value)?,
AttributeValue::Bool(value) => write!(buf, "{}", value)?,
AttributeValue::Float(f) => write!(buf, "{}", f)?,
AttributeValue::Int(i) => write!(buf, "{}", i)?,
_ => {}
}
}
}
} }
} }
@@ -208,7 +225,9 @@ fn to_string_works() {
StyleMarker { StyleMarker {
inside_style_tag: false, inside_style_tag: false,
}, },
PreRendered(">Hello world 1 --&gt;".into(),), PreRendered(">".into()),
InnerHtmlMarker,
PreRendered("Hello world 1 --&gt;".into(),),
Node(0,), Node(0,),
PreRendered( PreRendered(
"&lt;-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>".into(), "&lt;-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>".into(),
+26
View File
@@ -0,0 +1,26 @@
use dioxus::prelude::*;
#[test]
fn static_inner_html() {
fn app(cx: Scope) -> Element {
render! { div { dangerous_inner_html: "<div>1234</div>" } }
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
assert_eq!(dioxus_ssr::render(&dom), r#"<div><div>1234</div></div>"#);
}
#[test]
fn dynamic_inner_html() {
fn app(cx: Scope) -> Element {
let inner_html = "<div>1234</div>";
render! { div { dangerous_inner_html: "{inner_html}" } }
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
assert_eq!(dioxus_ssr::render(&dom), r#"<div><div>1234</div></div>"#);
}
+4 -3
View File
@@ -49,15 +49,16 @@ impl Config {
/// Set the name of the element that Dioxus will use as the root. /// Set the name of the element that Dioxus will use as the root.
/// ///
/// This is akint to calling React.render() on the element with the specified name. /// This is akin to calling React.render() on the element with the specified name.
pub fn rootname(mut self, name: impl Into<String>) -> Self { pub fn rootname(mut self, name: impl Into<String>) -> Self {
self.rootname = name.into(); self.rootname = name.into();
self self
} }
/// Set the name of the element that Dioxus will use as the root. /// Sets a string cache for wasm bindgen to [intern](https://docs.rs/wasm-bindgen/0.2.84/wasm_bindgen/fn.intern.html). This can help reduce the time it takes for wasm bindgen to pass
/// strings from rust to javascript. This can significantly improve pefromance when passing strings to javascript, but can have a negative impact on startup time.
/// ///
/// This is akint to calling React.render() on the element with the specified name. /// > Currently this cache is only used when creating static elements and attributes.
pub fn with_string_cache(mut self, cache: Vec<String>) -> Self { pub fn with_string_cache(mut self, cache: Vec<String>) -> Self {
self.cached_strings = cache; self.cached_strings = cache;
self self