flams_flodown/
module_picker.rs

1use flams_backend_types::archives::{ArchiveData, ArchiveGroupData, DirectoryData};
2use flams_web_utils::components::{
3    Header, LazySubtree, Leaf, Tree, wait_and_then, wait_and_then_fn,
4};
5use ftml_uris::{ArchiveId, ModuleUri, NamedUri};
6use leptos::prelude::*;
7
8pub fn picker(sig: RwSignal<rustc_hash::FxHashSet<ModuleUri>>) -> impl IntoView {
9    wait_and_then_fn(
10        || flams_router_backend::server_fns::group_entries(None),
11        move |(groups, archives)| archives_and_groups(groups, archives, sig).into_any(),
12    )
13}
14
15fn archives_and_groups(
16    groups: Vec<ArchiveGroupData>,
17    archives: Vec<ArchiveData>,
18    sig: RwSignal<rustc_hash::FxHashSet<ModuleUri>>,
19) -> impl IntoView {
20    view! {
21      {groups.into_iter().map(|g| group(g,sig)).collect_view()}
22      {archives.into_iter().map(|m| archive(m,sig)).collect_view()}
23    }
24}
25
26fn group(a: ArchiveGroupData, sig: RwSignal<rustc_hash::FxHashSet<ModuleUri>>) -> AnyView {
27    let header = view!(
28      <thaw::Icon icon=icondata_bi::BiLibraryRegular/>" "
29      {a.id.last().to_string()}
30    );
31    let id = a.id;
32    let f = move || flams_router_backend::server_fns::group_entries(Some(id.clone()));
33    view! {
34      <LazySubtree>
35        <Header slot>{header}</Header>
36        {
37          wait_and_then(f.clone(),
38          move |(groups,archives)|
39            view!(<Tree>{archives_and_groups(groups, archives,sig)}</Tree>).into_any()
40          )
41        }
42      </LazySubtree>
43    }
44    .into_any()
45}
46
47fn archive(a: ArchiveData, sig: RwSignal<rustc_hash::FxHashSet<ModuleUri>>) -> AnyView {
48    let header = view!(
49      <thaw::Icon icon=icondata_bi::BiBookSolid/>" "
50      {a.id.last().to_string()}
51    );
52    let id = a.id;
53    view! {
54      <LazySubtree>
55        <Header slot>{header}</Header>
56        {
57          let id = id.clone();
58          let nid = id.clone();
59          wait_and_then(move || flams_router_backend::server_fns::archive_modules(id.clone(),None),move |(dirs,mods)|
60            view!(<Tree>{dirs_and_mods(&nid,dirs,mods,sig)}</Tree>).into_any()
61          )
62        }
63      </LazySubtree>
64    }.into_any()
65}
66
67fn dirs_and_mods(
68    archive: &ArchiveId,
69    dirs: Vec<DirectoryData>,
70    mods: Vec<ModuleUri>,
71    sig: RwSignal<std::collections::HashSet<ModuleUri, rustc_hash::FxBuildHasher>>,
72) -> AnyView {
73    view! {
74      {dirs.into_iter().map(|d| dir(archive.clone(),d,sig)).collect_view()}
75      {mods.into_iter().map(|m| module(m,sig)).collect_view()}
76    }
77    .into_any()
78}
79
80fn dir(
81    archive: ArchiveId,
82    d: DirectoryData,
83    sig: RwSignal<rustc_hash::FxHashSet<ModuleUri>>,
84) -> AnyView {
85    let pathstr = unsafe { d.rel_path.split('/').last().unwrap_unchecked() }.to_string();
86    let header = view!(
87      <thaw::Icon icon=icondata_bi::BiFolderRegular/>" "
88      {pathstr}
89    );
90    let id = archive.clone();
91    let rel_path = d.rel_path;
92    let f = move || {
93        flams_router_backend::server_fns::archive_modules(id.clone(), Some(rel_path.clone()))
94    };
95    view! {
96      <LazySubtree>
97        <Header slot>{header}</Header>
98        {
99          let archive = archive.clone();
100          wait_and_then(
101              f.clone(),
102              move |(dirs,mods)|
103            view!(<Tree>{dirs_and_mods(&archive,dirs,mods,sig)}</Tree>).into_any()
104          )
105        }
106      </LazySubtree>
107    }
108    .into_any()
109}
110
111fn module(uri: ModuleUri, sig: RwSignal<rustc_hash::FxHashSet<ModuleUri>>) -> AnyView {
112    use thaw::Checkbox;
113    let name = uri.name().last().to_string();
114    let selected = RwSignal::new(false);
115    let uricl = uri.clone();
116    let mut changed = false;
117    let _ = Effect::new(move || {
118        sig.track();
119        selected.track();
120        if changed {
121            changed = false;
122            return;
123        }
124        if sig.with(|s| s.contains(&uricl) && !selected.get_untracked()) {
125            selected.set(true);
126            changed = true;
127        }
128        if selected.get() && !changed {
129            changed = true;
130            sig.update(|s| {
131                s.insert(uri.clone());
132            });
133        }
134    });
135    view!(
136        <Leaf><Checkbox checked=selected label=name/></Leaf>
137    )
138    .into_any()
139}