use leptos::{ prelude::Update, reactive_graph::{ computed::Memo, signal::{ReadSignal, RwSignal, WriteSignal}, traits::{GetUntracked, Set, With, WithUntracked}, wrappers::read::Signal, }, }; pub enum VecModel where T: 'static, { T(Signal, WriteSignal, Option>), Option( Signal>, WriteSignal>, Option>>, ), Vec( Signal>, WriteSignal>, Option>>, ), } impl Default for VecModel { fn default() -> Self { Self::new(Default::default()) } } impl Clone for VecModel { fn clone(&self) -> Self { *self } } impl Copy for VecModel {} impl VecModel { fn new(value: T) -> Self { Self::new_option(Some(value)) } fn new_option(value: Option) -> Self { let rw_signal = RwSignal::new(value); rw_signal.into() } fn new_vec(value: Vec) -> Self { let rw_signal = RwSignal::new(value); rw_signal.into() } pub fn is_vec(&self) -> bool { if let VecModel::Vec(_, _, _) = self { true } else { false } } pub fn with( &self, fun: impl FnOnce((Option<&T>, Option<&Option>, Option<&Vec>)) -> O, ) -> O { match self { Self::T(read, _, _) => read.with(|value| fun((Some(value), None, None))), Self::Option(read, _, _) => read.with(|value| fun((None, Some(value), None))), Self::Vec(read, _, _) => read.with(|value| fun((None, None, Some(value)))), } } pub fn with_untracked( &self, fun: impl FnOnce((Option<&T>, Option<&Option>, Option<&Vec>)) -> O, ) -> O { match self { Self::T(read, _, _) => read.with_untracked(|value| fun((Some(value), None, None))), Self::Option(read, _, _) => read.with_untracked(|value| fun((None, Some(value), None))), Self::Vec(read, _, _) => read.with_untracked(|value| fun((None, None, Some(value)))), } } } impl VecModel { pub fn set(&self, mut value: Vec) { match self { Self::T(read, write, on_write) => { let value = if value.is_empty() { Default::default() } else { value.remove(0) }; write.set(value); if let Some(on_write) = on_write.as_ref() { on_write.set(read.get_untracked()); } } Self::Option(read, write, on_write) => { let value = if value.is_empty() { None } else { Some(value.remove(0)) }; write.set(value); if let Some(on_write) = on_write.as_ref() { on_write.set(read.get_untracked()); } } Self::Vec(read, write, on_write) => { write.set(value); if let Some(on_write) = on_write.as_ref() { on_write.set(read.get_untracked()); } } } } pub fn update( &self, fun: impl FnOnce((Option<&mut T>, Option<&mut Option>, Option<&mut Vec>)), ) { match self { Self::T(read, write, on_write) => { write.update(move |write| { fun((Some(write), None, None)); }); if let Some(on_write) = on_write.as_ref() { on_write.set(read.get_untracked()); } } Self::Option(read, write, on_write) => { write.update(move |write| { fun((None, Some(write), None)); }); if let Some(on_write) = on_write.as_ref() { on_write.set(read.get_untracked()); } } Self::Vec(read, write, on_write) => { write.update(move |write| { fun((None, None, Some(write))); }); if let Some(on_write) = on_write.as_ref() { on_write.set(read.get_untracked()); } } } } } impl From for VecModel { fn from(value: T) -> Self { Self::new(value) } } impl From> for VecModel { fn from(value: Option) -> Self { Self::new_option(value) } } impl From> for VecModel { fn from(value: Vec) -> Self { Self::new_vec(value) } } impl From> for VecModel { fn from(rw_signal: RwSignal) -> Self { let (read, write) = rw_signal.split(); Self::T(read.into(), write, None) } } impl From>> for VecModel { fn from(rw_signal: RwSignal>) -> Self { let (read, write) = rw_signal.split(); Self::Option(read.into(), write, None) } } impl From>> for VecModel { fn from(rw_signal: RwSignal>) -> Self { let (read, write) = rw_signal.split(); Self::Vec(read.into(), write, None) } } impl From<(Signal, WriteSignal)> for VecModel { fn from((read, write): (Signal, WriteSignal)) -> Self { Self::T(read, write, None) } } impl From<(Signal>, WriteSignal>)> for VecModel { fn from((read, write): (Signal>, WriteSignal>)) -> Self { Self::Option(read, write, None) } } impl From<(Signal>, WriteSignal>)> for VecModel { fn from((read, write): (Signal>, WriteSignal>)) -> Self { Self::Vec(read, write, None) } } impl From<(ReadSignal, WriteSignal)> for VecModel { fn from((read, write): (ReadSignal, WriteSignal)) -> Self { Self::T(read.into(), write, None) } } impl From<(ReadSignal>, WriteSignal>)> for VecModel { fn from((read, write): (ReadSignal>, WriteSignal>)) -> Self { Self::Option(read.into(), write, None) } } impl From<(ReadSignal>, WriteSignal>)> for VecModel { fn from((read, write): (ReadSignal>, WriteSignal>)) -> Self { Self::Vec(read.into(), write, None) } } impl From<(Memo, WriteSignal)> for VecModel { fn from((read, write): (Memo, WriteSignal)) -> Self { Self::T(read.into(), write, None) } } impl From<(Memo>, WriteSignal>)> for VecModel { fn from((read, write): (Memo>, WriteSignal>)) -> Self { Self::Option(read.into(), write, None) } } impl From<(Memo>, WriteSignal>)> for VecModel { fn from((read, write): (Memo>, WriteSignal>)) -> Self { Self::Vec(read.into(), write, None) } } impl From<(Option, WriteSignal)> for VecModel { fn from((read, write): (Option, WriteSignal)) -> Self { let mut model = Self::new(read.unwrap_or_default()); if let VecModel::T(_, _, on_write) = &mut model { *on_write = Some(write); } model } } impl From<(Option>, WriteSignal>)> for VecModel { fn from((read, write): (Option>, WriteSignal>)) -> Self { let mut model = Self::new_option(read.unwrap_or_default()); if let VecModel::Option(_, _, on_write) = &mut model { *on_write = Some(write); } model } } impl From<(Option>, WriteSignal>)> for VecModel { fn from((read, write): (Option>, WriteSignal>)) -> Self { let mut model = Self::new_vec(read.unwrap_or_default()); if let VecModel::Vec(_, _, on_write) = &mut model { *on_write = Some(write); } model } }