rustolio_web/hooks/
query.rs1use std::{rc::Rc, str::FromStr};
12
13use crate::prelude::*;
14
15use super::SignalBase;
16
17#[derive(Debug, PartialEq, Eq)]
18pub struct QuerySignal<T> {
19 key: Signal<Rc<str>>,
20 signal: Signal<T>,
21}
22
23impl<T> Clone for QuerySignal<T> {
25 fn clone(&self) -> Self {
26 *self
27 }
28}
29impl<T> Copy for QuerySignal<T> {}
30
31impl<T> SignalBase<T> for QuerySignal<T> {
32 fn base(&self) -> Signal<T> {
33 self.signal.base()
34 }
35}
36impl<T> SignalGetter<T> for QuerySignal<T> where T: Clone + 'static {}
37impl<T> SignalSetter<T> for QuerySignal<T> where T: PartialEq + 'static {}
38impl<T> SignalUpdater<T> for QuerySignal<T> where T: 'static {}
39
40impl<T> QuerySignal<T> {
41 pub fn remove(&self) -> rustolio_utils::Result<()> {
46 url()?.search_params().delete(&self.key.peek());
47 Ok(())
48 }
49}
50
51impl<T> QuerySignal<T>
52where
53 T: ToString + FromStr + Clone + 'static,
54{
55 pub fn new(key: impl ToString, fallback: T) -> rustolio_utils::Result<Self> {
56 let key: Signal<Rc<str>> = Signal::new(key.to_string().into());
57
58 let stored_value = url()?
59 .search_params()
60 .get(&key.peek())
61 .and_then(|v| T::from_str(&v).ok())
62 .unwrap_or(fallback);
63
64 let signal = Signal::always_mutable(stored_value);
65 Effect::new_result(move || {
66 let key = key.peek();
67 let value = signal.value().to_string();
68
69 let url = url()?;
70 url.search_params().set(&key, &value);
71 url.push_to_history()?;
72
73 Ok(())
74 });
75
76 Ok(Self { signal, key })
77 }
78}