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))]
|
||||
defined_at: &'static Location<'static>,
|
||||
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_unkeyed:
|
||||
Arc<dyn Fn(StorePath) -> StoreFieldTrigger + Send + Sync>,
|
||||
@@ -113,6 +114,10 @@ impl<T> StoreField for ArcField<T> {
|
||||
(self.path)()
|
||||
}
|
||||
|
||||
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||
(self.path_unkeyed)()
|
||||
}
|
||||
|
||||
fn reader(&self) -> Option<Self::Reader> {
|
||||
(self.read)().map(StoreFieldReader::new)
|
||||
}
|
||||
@@ -137,6 +142,9 @@ where
|
||||
#[cfg(any(debug_assertions, leptos_debuginfo))]
|
||||
defined_at: Location::caller(),
|
||||
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_unkeyed: Arc::new(move |path| {
|
||||
value.get_trigger_unkeyed(path)
|
||||
@@ -163,6 +171,10 @@ where
|
||||
let value = value.clone();
|
||||
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({
|
||||
let value = value.clone();
|
||||
move |path| value.get_trigger(path)
|
||||
@@ -211,6 +223,10 @@ where
|
||||
let value = value.clone();
|
||||
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({
|
||||
let value = value.clone();
|
||||
move |path| value.get_trigger(path)
|
||||
@@ -258,6 +274,10 @@ where
|
||||
let value = value.clone();
|
||||
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({
|
||||
let value = value.clone();
|
||||
move |path| value.get_trigger(path)
|
||||
@@ -306,6 +326,10 @@ where
|
||||
let value = value.clone();
|
||||
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({
|
||||
let value = value.clone();
|
||||
move |path| value.get_trigger(path)
|
||||
@@ -358,6 +382,10 @@ where
|
||||
let value = value.clone();
|
||||
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({
|
||||
let value = value.clone();
|
||||
move |path| value.get_trigger(path)
|
||||
@@ -396,6 +424,7 @@ impl<T> Clone for ArcField<T> {
|
||||
#[cfg(any(debug_assertions, leptos_debuginfo))]
|
||||
defined_at: self.defined_at,
|
||||
path: self.path.clone(),
|
||||
path_unkeyed: self.path_unkeyed.clone(),
|
||||
get_trigger: Arc::clone(&self.get_trigger),
|
||||
get_trigger_unkeyed: Arc::clone(&self.get_trigger_unkeyed),
|
||||
read: Arc::clone(&self.read),
|
||||
|
||||
@@ -76,6 +76,11 @@ where
|
||||
fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||
self.inner.path()
|
||||
}
|
||||
|
||||
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||
self.inner.path_unkeyed()
|
||||
}
|
||||
|
||||
fn reader(&self) -> Option<Self::Reader> {
|
||||
let inner = self.inner.reader()?;
|
||||
Some(Mapped::new_with_guard(inner, |n| n.deref()))
|
||||
|
||||
@@ -73,6 +73,13 @@ where
|
||||
.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> {
|
||||
self.inner.try_get_value().and_then(|inner| inner.reader())
|
||||
}
|
||||
|
||||
@@ -80,6 +80,13 @@ where
|
||||
.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 {
|
||||
self.inner.get_trigger(path)
|
||||
}
|
||||
|
||||
@@ -106,6 +106,13 @@ where
|
||||
.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 {
|
||||
self.inner.get_trigger(path)
|
||||
}
|
||||
@@ -444,6 +451,24 @@ where
|
||||
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 {
|
||||
self.inner.get_trigger(path)
|
||||
}
|
||||
@@ -721,18 +746,19 @@ mod tests {
|
||||
effect::Effect,
|
||||
traits::{GetUntracked, ReadUntracked, Set, Track, Write},
|
||||
};
|
||||
use reactive_stores::Patch;
|
||||
use std::sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Arc,
|
||||
};
|
||||
|
||||
#[derive(Debug, Store, Default)]
|
||||
#[derive(Debug, Store, Default, Patch)]
|
||||
struct Todos {
|
||||
#[store(key: usize = |todo| todo.id)]
|
||||
todos: Vec<Todo>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Store, Default, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Store, Default, Clone, PartialEq, Eq, Patch)]
|
||||
struct Todo {
|
||||
id: usize,
|
||||
label: String,
|
||||
|
||||
@@ -30,7 +30,7 @@ where
|
||||
type Value = T::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() {
|
||||
// don't track the writer for the whole store
|
||||
writer.untrack();
|
||||
|
||||
@@ -38,6 +38,13 @@ pub trait StoreField: Sized {
|
||||
#[track_caller]
|
||||
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.
|
||||
#[track_caller]
|
||||
fn track_field(&self) {
|
||||
@@ -129,7 +136,9 @@ where
|
||||
trigger
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn get_trigger_unkeyed(&self, path: StorePath) -> StoreFieldTrigger {
|
||||
let caller = std::panic::Location::caller();
|
||||
let orig_path = path.clone();
|
||||
|
||||
let mut path = StorePath::with_capacity(orig_path.len());
|
||||
@@ -140,7 +149,13 @@ where
|
||||
let key = self
|
||||
.keys
|
||||
.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);
|
||||
} else {
|
||||
path.push(*segment);
|
||||
@@ -154,6 +169,11 @@ where
|
||||
iter::empty()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||
iter::empty()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn reader(&self) -> Option<Self::Reader> {
|
||||
Plain::try_new(Arc::clone(&self.value))
|
||||
@@ -205,6 +225,14 @@ where
|
||||
.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]
|
||||
fn reader(&self) -> Option<Self::Reader> {
|
||||
self.inner.try_get_value().and_then(|n| n.reader())
|
||||
|
||||
@@ -84,6 +84,13 @@ where
|
||||
.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 {
|
||||
self.inner.get_trigger(path)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user