mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-27 11:04:40 -05:00
@@ -29,6 +29,7 @@ where
|
|||||||
#[cfg(any(debug_assertions, leptos_debuginfo))]
|
#[cfg(any(debug_assertions, leptos_debuginfo))]
|
||||||
defined_at: &'static Location<'static>,
|
defined_at: &'static Location<'static>,
|
||||||
path: Arc<dyn Fn() -> StorePath + Send + Sync>,
|
path: Arc<dyn Fn() -> StorePath + Send + Sync>,
|
||||||
|
path_unkeyed: Arc<dyn Fn() -> StorePath + Send + Sync>,
|
||||||
get_trigger: Arc<dyn Fn(StorePath) -> StoreFieldTrigger + Send + Sync>,
|
get_trigger: Arc<dyn Fn(StorePath) -> StoreFieldTrigger + Send + Sync>,
|
||||||
get_trigger_unkeyed:
|
get_trigger_unkeyed:
|
||||||
Arc<dyn Fn(StorePath) -> StoreFieldTrigger + Send + Sync>,
|
Arc<dyn Fn(StorePath) -> StoreFieldTrigger + Send + Sync>,
|
||||||
@@ -113,6 +114,10 @@ impl<T> StoreField for ArcField<T> {
|
|||||||
(self.path)()
|
(self.path)()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
|
(self.path_unkeyed)()
|
||||||
|
}
|
||||||
|
|
||||||
fn reader(&self) -> Option<Self::Reader> {
|
fn reader(&self) -> Option<Self::Reader> {
|
||||||
(self.read)().map(StoreFieldReader::new)
|
(self.read)().map(StoreFieldReader::new)
|
||||||
}
|
}
|
||||||
@@ -137,6 +142,9 @@ where
|
|||||||
#[cfg(any(debug_assertions, leptos_debuginfo))]
|
#[cfg(any(debug_assertions, leptos_debuginfo))]
|
||||||
defined_at: Location::caller(),
|
defined_at: Location::caller(),
|
||||||
path: Arc::new(move || value.path().into_iter().collect()),
|
path: Arc::new(move || value.path().into_iter().collect()),
|
||||||
|
path_unkeyed: Arc::new(move || {
|
||||||
|
value.path_unkeyed().into_iter().collect()
|
||||||
|
}),
|
||||||
get_trigger: Arc::new(move |path| value.get_trigger(path)),
|
get_trigger: Arc::new(move |path| value.get_trigger(path)),
|
||||||
get_trigger_unkeyed: Arc::new(move |path| {
|
get_trigger_unkeyed: Arc::new(move |path| {
|
||||||
value.get_trigger_unkeyed(path)
|
value.get_trigger_unkeyed(path)
|
||||||
@@ -163,6 +171,10 @@ where
|
|||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
move || value.path().into_iter().collect()
|
move || value.path().into_iter().collect()
|
||||||
}),
|
}),
|
||||||
|
path_unkeyed: Arc::new({
|
||||||
|
let value = value.clone();
|
||||||
|
move || value.path_unkeyed().into_iter().collect()
|
||||||
|
}),
|
||||||
get_trigger: Arc::new({
|
get_trigger: Arc::new({
|
||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
move |path| value.get_trigger(path)
|
move |path| value.get_trigger(path)
|
||||||
@@ -211,6 +223,10 @@ where
|
|||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
move || value.path().into_iter().collect()
|
move || value.path().into_iter().collect()
|
||||||
}),
|
}),
|
||||||
|
path_unkeyed: Arc::new({
|
||||||
|
let value = value.clone();
|
||||||
|
move || value.path_unkeyed().into_iter().collect()
|
||||||
|
}),
|
||||||
get_trigger: Arc::new({
|
get_trigger: Arc::new({
|
||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
move |path| value.get_trigger(path)
|
move |path| value.get_trigger(path)
|
||||||
@@ -258,6 +274,10 @@ where
|
|||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
move || value.path().into_iter().collect()
|
move || value.path().into_iter().collect()
|
||||||
}),
|
}),
|
||||||
|
path_unkeyed: Arc::new({
|
||||||
|
let value = value.clone();
|
||||||
|
move || value.path_unkeyed().into_iter().collect()
|
||||||
|
}),
|
||||||
get_trigger: Arc::new({
|
get_trigger: Arc::new({
|
||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
move |path| value.get_trigger(path)
|
move |path| value.get_trigger(path)
|
||||||
@@ -306,6 +326,10 @@ where
|
|||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
move || value.path().into_iter().collect()
|
move || value.path().into_iter().collect()
|
||||||
}),
|
}),
|
||||||
|
path_unkeyed: Arc::new({
|
||||||
|
let value = value.clone();
|
||||||
|
move || value.path_unkeyed().into_iter().collect()
|
||||||
|
}),
|
||||||
get_trigger: Arc::new({
|
get_trigger: Arc::new({
|
||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
move |path| value.get_trigger(path)
|
move |path| value.get_trigger(path)
|
||||||
@@ -358,6 +382,10 @@ where
|
|||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
move || value.path().into_iter().collect()
|
move || value.path().into_iter().collect()
|
||||||
}),
|
}),
|
||||||
|
path_unkeyed: Arc::new({
|
||||||
|
let value = value.clone();
|
||||||
|
move || value.path_unkeyed().into_iter().collect()
|
||||||
|
}),
|
||||||
get_trigger: Arc::new({
|
get_trigger: Arc::new({
|
||||||
let value = value.clone();
|
let value = value.clone();
|
||||||
move |path| value.get_trigger(path)
|
move |path| value.get_trigger(path)
|
||||||
@@ -396,6 +424,7 @@ impl<T> Clone for ArcField<T> {
|
|||||||
#[cfg(any(debug_assertions, leptos_debuginfo))]
|
#[cfg(any(debug_assertions, leptos_debuginfo))]
|
||||||
defined_at: self.defined_at,
|
defined_at: self.defined_at,
|
||||||
path: self.path.clone(),
|
path: self.path.clone(),
|
||||||
|
path_unkeyed: self.path_unkeyed.clone(),
|
||||||
get_trigger: Arc::clone(&self.get_trigger),
|
get_trigger: Arc::clone(&self.get_trigger),
|
||||||
get_trigger_unkeyed: Arc::clone(&self.get_trigger_unkeyed),
|
get_trigger_unkeyed: Arc::clone(&self.get_trigger_unkeyed),
|
||||||
read: Arc::clone(&self.read),
|
read: Arc::clone(&self.read),
|
||||||
|
|||||||
@@ -76,6 +76,11 @@ where
|
|||||||
fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
self.inner.path()
|
self.inner.path()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
|
self.inner.path_unkeyed()
|
||||||
|
}
|
||||||
|
|
||||||
fn reader(&self) -> Option<Self::Reader> {
|
fn reader(&self) -> Option<Self::Reader> {
|
||||||
let inner = self.inner.reader()?;
|
let inner = self.inner.reader()?;
|
||||||
Some(Mapped::new_with_guard(inner, |n| n.deref()))
|
Some(Mapped::new_with_guard(inner, |n| n.deref()))
|
||||||
|
|||||||
@@ -73,6 +73,13 @@ where
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
|
self.inner
|
||||||
|
.try_get_value()
|
||||||
|
.map(|inner| inner.path_unkeyed().into_iter().collect::<Vec<_>>())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
fn reader(&self) -> Option<Self::Reader> {
|
fn reader(&self) -> Option<Self::Reader> {
|
||||||
self.inner.try_get_value().and_then(|inner| inner.reader())
|
self.inner.try_get_value().and_then(|inner| inner.reader())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,13 @@ where
|
|||||||
.chain(iter::once(self.index.into()))
|
.chain(iter::once(self.index.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
|
self.inner
|
||||||
|
.path_unkeyed()
|
||||||
|
.into_iter()
|
||||||
|
.chain(iter::once(self.index.into()))
|
||||||
|
}
|
||||||
|
|
||||||
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
|
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
|
||||||
self.inner.get_trigger(path)
|
self.inner.get_trigger(path)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,6 +106,13 @@ where
|
|||||||
.chain(iter::once(self.path_segment))
|
.chain(iter::once(self.path_segment))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
|
self.inner
|
||||||
|
.path_unkeyed()
|
||||||
|
.into_iter()
|
||||||
|
.chain(iter::once(self.path_segment))
|
||||||
|
}
|
||||||
|
|
||||||
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
|
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
|
||||||
self.inner.get_trigger(path)
|
self.inner.get_trigger(path)
|
||||||
}
|
}
|
||||||
@@ -444,6 +451,24 @@ where
|
|||||||
inner.into_iter().chain(this)
|
inner.into_iter().chain(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
|
let inner =
|
||||||
|
self.inner.path_unkeyed().into_iter().collect::<StorePath>();
|
||||||
|
let keys = self
|
||||||
|
.inner
|
||||||
|
.keys()
|
||||||
|
.expect("using keys on a store with no keys");
|
||||||
|
let this = keys
|
||||||
|
.with_field_keys(
|
||||||
|
inner.clone(),
|
||||||
|
|keys| (keys.get(&self.key), vec![]),
|
||||||
|
|| self.inner.latest_keys(),
|
||||||
|
)
|
||||||
|
.flatten()
|
||||||
|
.map(|(_, idx)| StorePathSegment(idx));
|
||||||
|
inner.into_iter().chain(this)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
|
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
|
||||||
self.inner.get_trigger(path)
|
self.inner.get_trigger(path)
|
||||||
}
|
}
|
||||||
@@ -721,18 +746,19 @@ mod tests {
|
|||||||
effect::Effect,
|
effect::Effect,
|
||||||
traits::{GetUntracked, ReadUntracked, Set, Track, Write},
|
traits::{GetUntracked, ReadUntracked, Set, Track, Write},
|
||||||
};
|
};
|
||||||
|
use reactive_stores::Patch;
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
atomic::{AtomicUsize, Ordering},
|
atomic::{AtomicUsize, Ordering},
|
||||||
Arc,
|
Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Store, Default)]
|
#[derive(Debug, Store, Default, Patch)]
|
||||||
struct Todos {
|
struct Todos {
|
||||||
#[store(key: usize = |todo| todo.id)]
|
#[store(key: usize = |todo| todo.id)]
|
||||||
todos: Vec<Todo>,
|
todos: Vec<Todo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Store, Default, Clone, PartialEq, Eq)]
|
#[derive(Debug, Store, Default, Clone, PartialEq, Eq, Patch)]
|
||||||
struct Todo {
|
struct Todo {
|
||||||
id: usize,
|
id: usize,
|
||||||
label: String,
|
label: String,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ where
|
|||||||
type Value = T::Value;
|
type Value = T::Value;
|
||||||
|
|
||||||
fn patch(&self, new: Self::Value) {
|
fn patch(&self, new: Self::Value) {
|
||||||
let path = self.path().into_iter().collect::<StorePath>();
|
let path = self.path_unkeyed().into_iter().collect::<StorePath>();
|
||||||
if let Some(mut writer) = self.writer() {
|
if let Some(mut writer) = self.writer() {
|
||||||
// don't track the writer for the whole store
|
// don't track the writer for the whole store
|
||||||
writer.untrack();
|
writer.untrack();
|
||||||
|
|||||||
@@ -38,6 +38,13 @@ pub trait StoreField: Sized {
|
|||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn path(&self) -> impl IntoIterator<Item = StorePathSegment>;
|
fn path(&self) -> impl IntoIterator<Item = StorePathSegment>;
|
||||||
|
|
||||||
|
/// The path of this field (see [`StorePath`]). Uses unkeyed indices for any keyed fields.
|
||||||
|
#[track_caller]
|
||||||
|
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
|
// TODO remove default impl next time we do a breaking release
|
||||||
|
self.path()
|
||||||
|
}
|
||||||
|
|
||||||
/// Reactively tracks this field.
|
/// Reactively tracks this field.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn track_field(&self) {
|
fn track_field(&self) {
|
||||||
@@ -129,7 +136,9 @@ where
|
|||||||
trigger
|
trigger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
fn get_trigger_unkeyed(&self, path: StorePath) -> StoreFieldTrigger {
|
fn get_trigger_unkeyed(&self, path: StorePath) -> StoreFieldTrigger {
|
||||||
|
let caller = std::panic::Location::caller();
|
||||||
let orig_path = path.clone();
|
let orig_path = path.clone();
|
||||||
|
|
||||||
let mut path = StorePath::with_capacity(orig_path.len());
|
let mut path = StorePath::with_capacity(orig_path.len());
|
||||||
@@ -140,7 +149,13 @@ where
|
|||||||
let key = self
|
let key = self
|
||||||
.keys
|
.keys
|
||||||
.get_key_for_index(&(path.clone(), segment.0))
|
.get_key_for_index(&(path.clone(), segment.0))
|
||||||
.expect("could not find key for index");
|
.unwrap_or_else(|| {
|
||||||
|
panic!(
|
||||||
|
"could not find key for index {:?} at {}",
|
||||||
|
&(path.clone(), segment.0),
|
||||||
|
caller
|
||||||
|
)
|
||||||
|
});
|
||||||
path.push(key);
|
path.push(key);
|
||||||
} else {
|
} else {
|
||||||
path.push(*segment);
|
path.push(*segment);
|
||||||
@@ -154,6 +169,11 @@ where
|
|||||||
iter::empty()
|
iter::empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
|
iter::empty()
|
||||||
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn reader(&self) -> Option<Self::Reader> {
|
fn reader(&self) -> Option<Self::Reader> {
|
||||||
Plain::try_new(Arc::clone(&self.value))
|
Plain::try_new(Arc::clone(&self.value))
|
||||||
@@ -205,6 +225,14 @@ where
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
|
self.inner
|
||||||
|
.try_get_value()
|
||||||
|
.map(|n| n.path_unkeyed().into_iter().collect::<Vec<_>>())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn reader(&self) -> Option<Self::Reader> {
|
fn reader(&self) -> Option<Self::Reader> {
|
||||||
self.inner.try_get_value().and_then(|n| n.reader())
|
self.inner.try_get_value().and_then(|n| n.reader())
|
||||||
|
|||||||
@@ -84,6 +84,13 @@ where
|
|||||||
.chain(iter::once(self.path_segment))
|
.chain(iter::once(self.path_segment))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||||
|
self.inner
|
||||||
|
.path_unkeyed()
|
||||||
|
.into_iter()
|
||||||
|
.chain(iter::once(self.path_segment))
|
||||||
|
}
|
||||||
|
|
||||||
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
|
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
|
||||||
self.inner.get_trigger(path)
|
self.inner.get_trigger(path)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user