dioxus_keys/
lib.rs

1use std::ops::{Deref, DerefMut};
2
3use dioxus_lib::prelude::*;
4
5mod macros;
6
7#[allow(async_fn_in_trait)]
8pub trait DataKey {
9    type Value: Clone + 'static;
10    async fn init();
11    async fn on_change();
12    async fn on_drop();
13    fn read() -> impl Deref<Target = Self::Value> {
14        Self::try_read().unwrap()
15    }
16    fn peek() -> impl Deref<Target = Self::Value> {
17        Self::try_read().unwrap()
18    }
19    fn write() -> impl DerefMut<Target = Self::Value> {
20        Self::try_write().unwrap()
21    }
22    fn try_read() -> Option<impl Deref<Target = Self::Value>>;
23    fn try_peek() -> Option<impl Deref<Target = Self::Value>>;
24    fn try_write() -> Option<impl DerefMut<Target = Self::Value>>;
25}
26
27pub fn use_init_key<K: DataKey<Value = V>, V>(_key: K) -> Resource<()> {
28    use_effect(move || {
29        let val = K::try_read();
30        if val.is_some() {
31            spawn(async { K::on_change().await });
32        }
33    });
34
35    use_drop(|| {
36        spawn(async { K::on_drop().await });
37    });
38
39    use_resource(|| async { K::init().await })
40}
41
42//
43// struct ExampleKey;
44//
45// type Val = Vec<u8>;
46// const PATH: &str = "some path";
47// const SERIALIZE: fn(&Val) -> &[u8] = |val| val;
48// const DESERIALIZE: fn(&[u8]) -> Val = |contents| contents.to_vec();
49//
50// static DATA: Global<Signal<Option<Option<Val>>, SyncStorage>> =
51//     Global::new(|| Signal::new_maybe_sync(None));
52//
53// impl DataKey for ExampleKey {
54//     type Value = Option<Val>;
55//
56//     async fn init() {
57//         let path = PathBuf::from(PATH);
58//         if path.try_exists().unwrap() {
59//             let mut file = File::open(path).await.unwrap();
60//             let mut contents = Vec::new();
61//             file.read_to_end(&mut contents).await.unwrap();
62//             *DATA.resolve().write() = Some(Some((DESERIALIZE)(&contents)));
63//         } else {
64//             *DATA.resolve().write() = Some(None);
65//         }
66//     }
67//
68//     async fn on_change() {
69//         let resolve = DATA.resolve();
70//         let read = resolve.read();
71//         let Some(data) = read.deref().as_ref() else {
72//             return;
73//         };
74//
75//         if let Some(data) = data {
76//             let mut file = File::create(PathBuf::from(PATH)).await.unwrap();
77//             file.write_all((SERIALIZE)(data)).await.unwrap();
78//         } else {
79//             let _ = remove_file(PATH).await;
80//         }
81//     }
82//
83//     async fn on_drop() {}
84//
85//     fn try_read() -> Option<impl Deref<Target = Self::Value>> {
86//         SyncStorage::try_map(DATA.resolve().read_unchecked(), |v| v.as_ref())
87//     }
88//
89//     fn try_write() -> Option<impl DerefMut<Target = Self::Value>> {
90//         Signal::<Option<Self::Value>, SyncStorage>::try_map_mut(
91//             DATA.resolve().write_unchecked(),
92//             |v| v.as_mut(),
93//         )
94//     }
95// }