mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-26 22:20:19 +00:00
Merge branch 'master' into jk/debugging-diff
This commit is contained in:
commit
1978f195b3
2 changed files with 65 additions and 68 deletions
|
@ -39,16 +39,17 @@ pub fn use_state<'a, T: 'static>(
|
|||
let setter = Rc::new({
|
||||
crate::to_owned![update_callback, slot];
|
||||
move |new| {
|
||||
let mut slot = slot.borrow_mut();
|
||||
{
|
||||
let mut slot = slot.borrow_mut();
|
||||
|
||||
// if there's only one reference (weak or otherwise), we can just swap the values
|
||||
// Typically happens when the state is set multiple times - we don't want to create a new Rc for each new value
|
||||
if let Some(val) = Rc::get_mut(&mut slot) {
|
||||
*val = new;
|
||||
} else {
|
||||
*slot = Rc::new(new);
|
||||
// if there's only one reference (weak or otherwise), we can just swap the values
|
||||
// Typically happens when the state is set multiple times - we don't want to create a new Rc for each new value
|
||||
if let Some(val) = Rc::get_mut(&mut slot) {
|
||||
*val = new;
|
||||
} else {
|
||||
*slot = Rc::new(new);
|
||||
}
|
||||
}
|
||||
|
||||
update_callback();
|
||||
}
|
||||
});
|
||||
|
@ -92,7 +93,7 @@ impl<T: 'static> UseState<T> {
|
|||
/// }
|
||||
/// })
|
||||
/// }
|
||||
/// ```
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn current(&self) -> Rc<T> {
|
||||
self.slot.borrow().clone()
|
||||
|
@ -137,10 +138,10 @@ impl<T: 'static> UseState<T> {
|
|||
/// # use dioxus_hooks::*;
|
||||
/// fn component(cx: Scope) -> Element {
|
||||
/// let (value, set_value) = use_state(&cx, || 0);
|
||||
///
|
||||
///
|
||||
/// // to increment the value
|
||||
/// set_value.modify(|v| v + 1);
|
||||
///
|
||||
///
|
||||
/// // usage in async
|
||||
/// cx.spawn({
|
||||
/// let set_value = set_value.to_owned();
|
||||
|
@ -153,8 +154,10 @@ impl<T: 'static> UseState<T> {
|
|||
/// }
|
||||
/// ```
|
||||
pub fn modify(&self, f: impl FnOnce(&T) -> T) {
|
||||
let current = self.slot.borrow();
|
||||
let new_val = f(current.as_ref());
|
||||
let new_val = {
|
||||
let current = self.slot.borrow();
|
||||
f(current.as_ref())
|
||||
};
|
||||
(self.setter)(new_val);
|
||||
}
|
||||
|
||||
|
@ -176,7 +179,7 @@ impl<T: 'static> UseState<T> {
|
|||
/// # use dioxus_hooks::*;
|
||||
/// fn component(cx: Scope) -> Element {
|
||||
/// let (value, set_value) = use_state(&cx, || 0);
|
||||
///
|
||||
///
|
||||
/// let as_rc = set_value.get();
|
||||
/// assert_eq!(as_rc.as_ref(), &0);
|
||||
///
|
||||
|
@ -201,7 +204,7 @@ impl<T: 'static> UseState<T> {
|
|||
/// }
|
||||
/// })
|
||||
/// }
|
||||
/// ```
|
||||
/// ```
|
||||
pub fn needs_update(&self) {
|
||||
(self.update_callback)();
|
||||
}
|
||||
|
|
|
@ -28,17 +28,54 @@ impl WebsysDom {
|
|||
pub fn new(cfg: WebConfig, sender_callback: Rc<dyn Fn(SchedulerMsg)>) -> Self {
|
||||
// eventually, we just want to let the interpreter do all the work of decoding events into our event type
|
||||
let callback: Box<dyn FnMut(&Event)> = Box::new(move |event: &web_sys::Event| {
|
||||
if let Ok(synthetic_event) = decode_trigger(event) {
|
||||
let mut target = event
|
||||
.target()
|
||||
.expect("missing target")
|
||||
.dyn_into::<Element>()
|
||||
.expect("not a valid element");
|
||||
|
||||
let typ = event.type_();
|
||||
|
||||
let decoded: anyhow::Result<UserEvent> = loop {
|
||||
match target.get_attribute("data-dioxus-id").map(|f| f.parse()) {
|
||||
Some(Ok(id)) => {
|
||||
break Ok(UserEvent {
|
||||
name: event_name_from_typ(&typ),
|
||||
data: virtual_event_from_websys_event(event.clone()),
|
||||
element: Some(ElementId(id)),
|
||||
scope_id: None,
|
||||
priority: dioxus_core::EventPriority::Medium,
|
||||
});
|
||||
}
|
||||
Some(Err(e)) => {
|
||||
break Err(e.into());
|
||||
}
|
||||
None => {
|
||||
// walk the tree upwards until we actually find an event target
|
||||
if let Some(parent) = target.parent_element() {
|
||||
target = parent;
|
||||
} else {
|
||||
break Ok(UserEvent {
|
||||
name: event_name_from_typ(&typ),
|
||||
data: virtual_event_from_websys_event(event.clone()),
|
||||
element: None,
|
||||
scope_id: None,
|
||||
priority: dioxus_core::EventPriority::Low,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(synthetic_event) = decoded {
|
||||
// Try to prevent default if the attribute is set
|
||||
if let Some(target) = event.target() {
|
||||
if let Some(node) = target.dyn_ref::<HtmlElement>() {
|
||||
if let Some(name) = node.get_attribute("dioxus-prevent-default") {
|
||||
if name == synthetic_event.name
|
||||
|| name.trim_start_matches("on") == synthetic_event.name
|
||||
{
|
||||
log::trace!("Preventing default");
|
||||
event.prevent_default();
|
||||
}
|
||||
if let Some(node) = target.dyn_ref::<HtmlElement>() {
|
||||
if let Some(name) = node.get_attribute("dioxus-prevent-default") {
|
||||
if name == synthetic_event.name
|
||||
|| name.trim_start_matches("on") == synthetic_event.name
|
||||
{
|
||||
log::trace!("Preventing default");
|
||||
event.prevent_default();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -274,49 +311,6 @@ fn virtual_event_from_websys_event(event: web_sys::Event) -> Arc<dyn Any + Send
|
|||
}
|
||||
}
|
||||
|
||||
/// This function decodes a websys event and produces an EventTrigger
|
||||
/// With the websys implementation, we attach a unique key to the nodes
|
||||
fn decode_trigger(event: &web_sys::Event) -> anyhow::Result<UserEvent> {
|
||||
let mut target = event
|
||||
.target()
|
||||
.expect("missing target")
|
||||
.dyn_into::<Element>()
|
||||
.expect("not a valid element");
|
||||
|
||||
let typ = event.type_();
|
||||
|
||||
loop {
|
||||
match target.get_attribute("data-dioxus-id").map(|f| f.parse()) {
|
||||
Some(Ok(id)) => {
|
||||
return Ok(UserEvent {
|
||||
name: event_name_from_typ(&typ),
|
||||
data: virtual_event_from_websys_event(event.clone()),
|
||||
element: Some(ElementId(id)),
|
||||
scope_id: None,
|
||||
priority: dioxus_core::EventPriority::Medium,
|
||||
});
|
||||
}
|
||||
Some(Err(e)) => {
|
||||
return Err(e.into());
|
||||
}
|
||||
None => {
|
||||
// walk the tree upwards until we actually find an event target
|
||||
if let Some(parent) = target.parent_element() {
|
||||
target = parent;
|
||||
} else {
|
||||
return Ok(UserEvent {
|
||||
name: event_name_from_typ(&typ),
|
||||
data: virtual_event_from_websys_event(event.clone()),
|
||||
element: None,
|
||||
scope_id: None,
|
||||
priority: dioxus_core::EventPriority::Low,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load_document() -> Document {
|
||||
web_sys::window()
|
||||
.expect("should have access to the Window")
|
||||
|
|
Loading…
Reference in a new issue