diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index b65eaa86a..d500ca6b5 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -84,11 +84,11 @@ pub use crate::innerlude::{ /// This includes types like [`Scope`], [`Element`], and [`Component`]. pub mod prelude { pub use crate::innerlude::{ - consume_context, current_scope_id, fc_to_builder, has_context, provide_context, - provide_root_context, schedule_update_any, suspend, throw, AnyValue, Component, Element, - Event, EventHandler, Fragment, IntoAttributeValue, LazyNodes, Properties, Scope, ScopeId, - ScopeState, Scoped, TaskId, Template, TemplateAttribute, TemplateNode, Throw, VNode, - VirtualDom, + consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, has_context, + provide_context, provide_context_to_scope, provide_root_context, schedule_update_any, + suspend, throw, AnyValue, Component, Element, Event, EventHandler, Fragment, + IntoAttributeValue, LazyNodes, Properties, Scope, ScopeId, ScopeState, Scoped, TaskId, + Template, TemplateAttribute, TemplateNode, Throw, VNode, VirtualDom, }; } diff --git a/packages/core/src/scope_context.rs b/packages/core/src/scope_context.rs index 13263f529..a724bb27a 100644 --- a/packages/core/src/scope_context.rs +++ b/packages/core/src/scope_context.rs @@ -268,6 +268,15 @@ pub fn consume_context() -> Option { with_current_scope(|cx| cx.consume_context::()).flatten() } +/// Consume context from the current scope +pub fn consume_context_from_scope(scope_id: ScopeId) -> Option { + with_runtime(|rt| { + rt.get_context(scope_id) + .and_then(|cx| cx.consume_context::()) + }) + .flatten() +} + /// Check if the current scope has a context pub fn has_context() -> Option { with_current_scope(|cx| cx.has_context::()).flatten() @@ -278,6 +287,11 @@ pub fn provide_context(value: T) -> Option { with_current_scope(|cx| cx.provide_context(value)) } +/// Provide context to the the given scope +pub fn provide_context_to_scope(scope_id: ScopeId, value: T) -> Option { + with_runtime(|rt| rt.get_context(scope_id).map(|cx| cx.provide_context(value))).flatten() +} + /// Provide a context to the root scope pub fn provide_root_context(value: T) -> Option { with_current_scope(|cx| cx.provide_root_context(value)) diff --git a/packages/signals/src/lib.rs b/packages/signals/src/lib.rs index 4340b6484..a49a38a18 100644 --- a/packages/signals/src/lib.rs +++ b/packages/signals/src/lib.rs @@ -70,6 +70,10 @@ impl Signal { } } + pub fn origin_scope(&self) -> ScopeId { + self.inner.origin_scope() + } + pub fn read(&self) -> Ref { let inner = self.inner.read(); if let Some(current_scope_id) = current_scope_id() { diff --git a/packages/signals/src/rt.rs b/packages/signals/src/rt.rs index 0605fb951..ca5d5ec9f 100644 --- a/packages/signals/src/rt.rs +++ b/packages/signals/src/rt.rs @@ -2,7 +2,11 @@ use std::cell::{Ref, RefMut}; use std::rc::Rc; -use dioxus_core::prelude::{consume_context, provide_root_context}; +use dioxus_core::prelude::{ + consume_context, consume_context_from_scope, current_scope_id, provide_context_to_scope, + provide_root_context, +}; +use dioxus_core::ScopeId; use dioxus_copy::{CopyHandle, Owner, Store}; @@ -26,8 +30,19 @@ fn current_owner() -> Rc { } } +fn owner_in_scope(scope: ScopeId) -> Rc { + match consume_context_from_scope(scope) { + Some(rt) => rt, + None => { + let owner = Rc::new(current_store().owner()); + provide_context_to_scope(scope, owner).expect("in a virtual dom") + } + } +} + pub struct CopyValue { pub value: CopyHandle, + origin_scope: ScopeId, } impl CopyValue { @@ -36,9 +51,23 @@ impl CopyValue { Self { value: owner.insert(value), + origin_scope: current_scope_id().expect("in a virtual dom"), } } + pub fn new_in_scope(value: T, scope: ScopeId) -> Self { + let owner = owner_in_scope(scope); + + Self { + value: owner.insert(value), + origin_scope: scope, + } + } + + pub fn origin_scope(&self) -> ScopeId { + self.origin_scope + } + pub fn try_read(&self) -> Option> { self.value.try_read() }