flams_flodown/
module_picker.rs1use 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}