Merge branch 'DioxusLabs:master' into master
This commit is contained in:
6 files changed
+93
-22
No files matched your search
@@ -19,13 +19,7 @@ jobs:
|
|||||||
max-parallel: 2
|
max-parallel: 2
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
target:
|
target: [x86_64-pc-windows-gnu, x86_64-pc-windows-msvc]
|
||||||
[
|
|
||||||
i686-pc-windows-gnu,
|
|
||||||
i686-pc-windows-msvc,
|
|
||||||
x86_64-pc-windows-gnu,
|
|
||||||
x86_64-pc-windows-msvc,
|
|
||||||
]
|
|
||||||
cfg_release_channel: [stable]
|
cfg_release_channel: [stable]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -47,12 +41,6 @@ jobs:
|
|||||||
rustup target add ${{ matrix.target }}
|
rustup target add ${{ matrix.target }}
|
||||||
shell: powershell
|
shell: powershell
|
||||||
|
|
||||||
- name: Add mingw32 to path for i686-gnu
|
|
||||||
run: |
|
|
||||||
echo "C:\msys64\mingw32\bin" >> $GITHUB_PATH
|
|
||||||
if: matrix.target == 'i686-pc-windows-gnu' && matrix.channel == 'nightly'
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Add mingw64 to path for x86_64-gnu
|
- name: Add mingw64 to path for x86_64-gnu
|
||||||
run: echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH
|
run: echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH
|
||||||
if: matrix.target == 'x86_64-pc-windows-gnu' && matrix.channel == 'nightly'
|
if: matrix.target == 'x86_64-pc-windows-gnu' && matrix.channel == 'nightly'
|
||||||
|
|||||||
@@ -313,3 +313,42 @@ fn leak_thru_children() {
|
|||||||
dom.handle_message(SchedulerMsg::Immediate(ScopeId(0)));
|
dom.handle_message(SchedulerMsg::Immediate(ScopeId(0)));
|
||||||
dom.work_with_deadline(|| false);
|
dom.work_with_deadline(|| false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pass_thru() {
|
||||||
|
#[inline_props]
|
||||||
|
fn Router<'a>(cx: Scope, children: Element<'a>) -> Element {
|
||||||
|
cx.render(rsx! {
|
||||||
|
&cx.props.children
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn MemoizedThing(cx: Scope) -> Element {
|
||||||
|
rsx!(cx, div { "memoized" })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn app(cx: Scope) -> Element {
|
||||||
|
let thing = cx.use_hook(|_| "asd");
|
||||||
|
rsx!(cx,
|
||||||
|
Router {
|
||||||
|
MemoizedThing {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut dom = new_dom(app, ());
|
||||||
|
let _ = dom.rebuild();
|
||||||
|
|
||||||
|
dom.handle_message(SchedulerMsg::Immediate(ScopeId(0)));
|
||||||
|
dom.work_with_deadline(|| false);
|
||||||
|
|
||||||
|
dom.handle_message(SchedulerMsg::Immediate(ScopeId(0)));
|
||||||
|
dom.work_with_deadline(|| false);
|
||||||
|
|
||||||
|
dom.handle_message(SchedulerMsg::Immediate(ScopeId(0)));
|
||||||
|
dom.work_with_deadline(|| false);
|
||||||
|
|
||||||
|
dom.handle_message(SchedulerMsg::Immediate(ScopeId(0)));
|
||||||
|
dom.work_with_deadline(|| false);
|
||||||
|
}
|
||||||
@@ -61,6 +61,8 @@ pub fn use_state<'a, T: 'static>(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
hook.current_val = hook.slot.borrow().clone();
|
||||||
|
|
||||||
(hook.current_val.as_ref(), hook)
|
(hook.current_val.as_ref(), hook)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ pub struct LinkProps<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
|
pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element {
|
||||||
log::debug!("render Link to {}", cx.props.to);
|
log::trace!("render Link to {}", cx.props.to);
|
||||||
if let Some(service) = cx.consume_context::<RouterService>() {
|
if let Some(service) = cx.consume_context::<RouterService>() {
|
||||||
return cx.render(rsx! {
|
return cx.render(rsx! {
|
||||||
a {
|
a {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use dioxus_core::ScopeState;
|
use dioxus_core::{ScopeId, ScopeState};
|
||||||
use gloo::history::{HistoryResult, Location};
|
use gloo::history::{HistoryResult, Location};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use std::{rc::Rc, str::FromStr};
|
use std::{rc::Rc, str::FromStr};
|
||||||
@@ -8,6 +8,7 @@ use crate::RouterService;
|
|||||||
/// This struct provides is a wrapper around the internal router
|
/// This struct provides is a wrapper around the internal router
|
||||||
/// implementation, with methods for getting information about the current
|
/// implementation, with methods for getting information about the current
|
||||||
/// route.
|
/// route.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct UseRoute {
|
pub struct UseRoute {
|
||||||
router: Rc<RouterService>,
|
router: Rc<RouterService>,
|
||||||
}
|
}
|
||||||
@@ -74,10 +75,32 @@ impl UseRoute {
|
|||||||
/// This hook provides access to information about the current location in the
|
/// This hook provides access to information about the current location in the
|
||||||
/// context of a [`Router`]. If this function is called outside of a `Router`
|
/// context of a [`Router`]. If this function is called outside of a `Router`
|
||||||
/// component it will panic.
|
/// component it will panic.
|
||||||
pub fn use_route(cx: &ScopeState) -> UseRoute {
|
pub fn use_route(cx: &ScopeState) -> &UseRoute {
|
||||||
let router = cx
|
&cx.use_hook(|_| {
|
||||||
.consume_context::<RouterService>()
|
let router = cx
|
||||||
.expect("Cannot call use_route outside the scope of a Router component")
|
.consume_context::<RouterService>()
|
||||||
.clone();
|
.expect("Cannot call use_route outside the scope of a Router component");
|
||||||
UseRoute { router }
|
|
||||||
|
router.subscribe_onchange(cx.scope_id());
|
||||||
|
|
||||||
|
UseRouteListener {
|
||||||
|
router: UseRoute { router },
|
||||||
|
scope: cx.scope_id(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.router
|
||||||
|
}
|
||||||
|
|
||||||
|
// The entire purpose of this struct is to unubscribe this component when it is unmounted.
|
||||||
|
// The UseRoute can be cloned into async contexts, so we can't rely on its drop to unubscribe.
|
||||||
|
// Instead, we hide the drop implementation on this private type exclusive to the hook,
|
||||||
|
// and reveal our cached version of UseRoute to the component.
|
||||||
|
struct UseRouteListener {
|
||||||
|
router: UseRoute,
|
||||||
|
scope: ScopeId,
|
||||||
|
}
|
||||||
|
impl Drop for UseRouteListener {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.router.router.unsubscribe_onchange(self.scope)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use gloo::history::{BrowserHistory, History, HistoryListener, Location};
|
use gloo::history::{BrowserHistory, History, HistoryListener, Location};
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, Ref, RefCell},
|
cell::{Cell, Ref, RefCell},
|
||||||
collections::HashMap,
|
collections::{HashMap, HashSet},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@ pub struct RouterService {
|
|||||||
pub(crate) pending_events: Rc<RefCell<Vec<RouteEvent>>>,
|
pub(crate) pending_events: Rc<RefCell<Vec<RouteEvent>>>,
|
||||||
history: Rc<RefCell<BrowserHistory>>,
|
history: Rc<RefCell<BrowserHistory>>,
|
||||||
slots: Rc<RefCell<Vec<(ScopeId, String)>>>,
|
slots: Rc<RefCell<Vec<(ScopeId, String)>>>,
|
||||||
|
onchange_listeners: Rc<RefCell<HashSet<ScopeId>>>,
|
||||||
root_found: Rc<Cell<Option<ScopeId>>>,
|
root_found: Rc<Cell<Option<ScopeId>>>,
|
||||||
cur_path_params: Rc<RefCell<HashMap<String, String>>>,
|
cur_path_params: Rc<RefCell<HashMap<String, String>>>,
|
||||||
listener: HistoryListener,
|
listener: HistoryListener,
|
||||||
@@ -42,6 +43,7 @@ impl RouterService {
|
|||||||
let location = history.location();
|
let location = history.location();
|
||||||
let path = location.path();
|
let path = location.path();
|
||||||
|
|
||||||
|
let onchange_listeners = Rc::new(RefCell::new(HashSet::new()));
|
||||||
let slots: Rc<RefCell<Vec<(ScopeId, String)>>> = Default::default();
|
let slots: Rc<RefCell<Vec<(ScopeId, String)>>> = Default::default();
|
||||||
let pending_events: Rc<RefCell<Vec<RouteEvent>>> = Default::default();
|
let pending_events: Rc<RefCell<Vec<RouteEvent>>> = Default::default();
|
||||||
let root_found = Rc::new(Cell::new(None));
|
let root_found = Rc::new(Cell::new(None));
|
||||||
@@ -51,6 +53,7 @@ impl RouterService {
|
|||||||
let regen_route = regen_route.clone();
|
let regen_route = regen_route.clone();
|
||||||
let root_found = root_found.clone();
|
let root_found = root_found.clone();
|
||||||
let slots = slots.clone();
|
let slots = slots.clone();
|
||||||
|
let onchange_listeners = onchange_listeners.clone();
|
||||||
move || {
|
move || {
|
||||||
root_found.set(None);
|
root_found.set(None);
|
||||||
// checking if the route is valid is cheap, so we do it
|
// checking if the route is valid is cheap, so we do it
|
||||||
@@ -59,6 +62,11 @@ impl RouterService {
|
|||||||
regen_route(*slot);
|
regen_route(*slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for listener in onchange_listeners.borrow_mut().iter() {
|
||||||
|
log::trace!("regenerating listener {:?}", listener);
|
||||||
|
regen_route(*listener);
|
||||||
|
}
|
||||||
|
|
||||||
// also regenerate the root
|
// also regenerate the root
|
||||||
regen_route(root_scope);
|
regen_route(root_scope);
|
||||||
|
|
||||||
@@ -73,6 +81,7 @@ impl RouterService {
|
|||||||
regen_route,
|
regen_route,
|
||||||
slots,
|
slots,
|
||||||
pending_events,
|
pending_events,
|
||||||
|
onchange_listeners,
|
||||||
cur_path_params: Rc::new(RefCell::new(HashMap::new())),
|
cur_path_params: Rc::new(RefCell::new(HashMap::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,6 +152,16 @@ impl RouterService {
|
|||||||
pub fn current_path_params(&self) -> Ref<HashMap<String, String>> {
|
pub fn current_path_params(&self) -> Ref<HashMap<String, String>> {
|
||||||
self.cur_path_params.borrow()
|
self.cur_path_params.borrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn subscribe_onchange(&self, id: ScopeId) {
|
||||||
|
log::trace!("Subscribing onchange for scope id {:?}", id);
|
||||||
|
self.onchange_listeners.borrow_mut().insert(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unsubscribe_onchange(&self, id: ScopeId) {
|
||||||
|
log::trace!("Subscribing onchange for scope id {:?}", id);
|
||||||
|
self.onchange_listeners.borrow_mut().remove(&id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_route(route: String) -> String {
|
fn clean_route(route: String) -> String {
|
||||||
|
|||||||
Reference in new issue
Block a user