Commit 6534170de7c765b99af9ce22f47aeb88d40b3ba6

Authored by Georg Hopp
1 parent 73d74786

remove example code

1   -[package]
2   -name = "mogwai-list"
3   -version = "0.0.0"
4   -authors = ["Georg Hopp <georg@steffers.org>"]
5   -workspace = ".."
6   -edition = "2018"
7   -
8   -[lib]
9   -crate-type = ["cdylib", "rlib"]
10   -
11   -[features]
12   -default = ["console_error_panic_hook"]
13   -
14   -[dependencies]
15   -artshop-common = { path = "../common" }
16   -katex = { version = "0.4", default-features = false, features = ["wasm-js"] }
17   -pulldown-cmark = "0.9"
18   -console_log = "^0.1"
19   -log = "^0.4"
20   -serde = { version = "^1.0", features = ["derive"] }
21   -serde_json = "^1.0"
22   -wasm-bindgen = "^0.2"
23   -wasm-bindgen-futures = "^0.4"
24   -
25   -# The `console_error_panic_hook` crate provides better debugging of panics by
26   -# logging them with `console.error`. This is great for development, but requires
27   -# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
28   -# code size when deploying.
29   -console_error_panic_hook = { version = "0.1.6", optional = true }
30   -wee_alloc = { version = "0.4.2", optional = true }
31   -js-sys = "^0.3"
32   -
33   -[dependencies.mogwai]
34   -version = "^0.5"
35   -
36   -[dependencies.web-sys]
37   -version = "^0.3"
38   -features = [
39   - "Document",
40   - "DomParser",
41   - "Headers",
42   - "HtmlElement",
43   - "HtmlInputElement",
44   - "MouseEvent",
45   - "Node",
46   - "Request",
47   - "RequestInit",
48   - "RequestMode",
49   - "Response",
50   - "SupportedType",
51   - "Window",
52   -]
53   -
54   -[dev-dependencies]
55   -wasm-bindgen-test = "0.2"
1   -#![allow(unused_braces)]
2   -use log::Level;
3   -use mogwai::{futures, prelude::*};
4   -use std::panic;
5   -use wasm_bindgen::prelude::*;
6   -
7   -/// An item widget.
8   -/// Keeps track of clicks.
9   -#[derive(Clone, Debug)]
10   -struct Item {
11   - id: usize,
12   - clicks: Model<u32>,
13   -}
14   -
15   -/// An item's update messages.
16   -#[derive(Clone)]
17   -enum ItemMsg {
18   - /// The user clicked
19   - Click,
20   - /// The user requested this item be removed
21   - Remove,
22   -}
23   -
24   -/// One item's logic loop.
25   -async fn item_logic(
26   - id: usize,
27   - clicks: Model<u32>,
28   - mut from_view: broadcast::Receiver<ItemMsg>,
29   - to_list: broadcast::Sender<ListMsg>,
30   -) {
31   - loop {
32   - match from_view.recv().await {
33   - Ok(ItemMsg::Click) => {
34   - clicks.visit_mut(|c| *c += 1).await;
35   - }
36   - Ok(ItemMsg::Remove) => {
37   - to_list.broadcast(ListMsg::RemoveItem(id)).await.unwrap();
38   - break;
39   - }
40   - Err(_) => break,
41   - }
42   - }
43   - log::info!("item {} logic loop is done", id);
44   -}
45   -
46   -// ANCHOR: item_view
47   -fn item_view(
48   - clicks: impl Stream<Item = u32> + Sendable,
49   - to_logic: broadcast::Sender<ItemMsg>,
50   -) -> ViewBuilder<Dom> {
51   - builder! {
52   - <li>
53   - <button
54   - style:cursor="pointer"
55   - on:click=to_logic.sink().contra_map(|_| ItemMsg::Click)>
56   - "Increment"
57   - </button>
58   - <button
59   - style:cursor="pointer"
60   - on:click=to_logic.sink().contra_map(|_| ItemMsg::Remove)>
61   - "Remove"
62   - </button>
63   - " "
64   - <span>
65   - {
66   - ("", clicks.map(|clicks| match clicks {
67   - 1 => "1 click".to_string(),
68   - n => format!("{} clicks", n),
69   - }))
70   - }
71   - </span>
72   - </li>
73   - }
74   -}
75   -// ANCHOR_END: item_view
76   -
77   -/// Create a new item component.
78   -fn item(id: usize, clicks: Model<u32>, to_list: broadcast::Sender<ListMsg>) -> Component<Dom> {
79   - let (tx, rx) = broadcast::bounded(1);
80   - Component::from(item_view(clicks.stream(), tx)).with_logic(item_logic(id, clicks, rx, to_list))
81   -}
82   -
83   -#[derive(Clone)]
84   -enum ListMsg {
85   - /// Create a new item
86   - NewItem,
87   - /// Remove the item with the given id
88   - RemoveItem(usize),
89   -}
90   -
91   -// ANCHOR: list_logic_coms
92   -/// Launch the logic loop of our list of items.
93   -async fn list_logic(
94   - input: broadcast::Receiver<ListMsg>,
95   - tx_patch_children: mpmc::Sender<ListPatch<ViewBuilder<Dom>>>,
96   -) {
97   - // Set up our communication from items to this logic loop by
98   - // * creating a list patch model
99   - // * creating a channel to go from item to list logic (aka here)
100   - // * creating a side-effect stream (for_each) that runs for each item patch
101   - // * map patches of Item to patches of builders and send that to our view
102   - // through tx_patch_children
103   - let mut items: ListPatchModel<Item> = ListPatchModel::new();
104   - let (to_list, from_items) = broadcast::bounded::<ListMsg>(1);
105   - let to_list = to_list.clone();
106   - let all_item_patches = items.stream().map(move |patch| {
107   - log::info!("mapping patch for item: {:?}", patch);
108   - let to_list = to_list.clone();
109   - patch.map(move |Item { id, clicks }: Item| {
110   - let to_list = to_list.clone();
111   - let component = item(id, clicks, to_list);
112   - let builder: ViewBuilder<Dom> = component.into();
113   - builder
114   - })
115   - }).for_each(move |patch| {
116   - let tx_patch_children = tx_patch_children.clone();
117   - async move {
118   - tx_patch_children.send(patch).await.unwrap();
119   - }
120   - });
121   - mogwai::spawn(all_item_patches);
122   - // ANCHOR_END: list_logic_coms
123   - // ANCHOR: list_logic_loop
124   - // Combine the input from our view with the input from our items
125   - let mut input = futures::stream::select_all(vec![input, from_items]);
126   - let mut next_id = 0;
127   - loop {
128   - match input.next().await {
129   - Some(ListMsg::NewItem) => {
130   - log::info!("creating a new item");
131   - let item: Item = Item {
132   - id: next_id,
133   - clicks: Model::new(0),
134   - };
135   - next_id += 1;
136   - // patch our items easily and _item_patch_stream's for_each runs automatically,
137   - // keeping the list of item views in sync
138   - items.list_patch_push(item);
139   - }
140   - Some(ListMsg::RemoveItem(id)) => {
141   - log::info!("removing item: {}", id);
142   - let mut may_index = None;
143   - 'find_item_by_id: for (item, index) in items.read().await.iter().zip(0..) {
144   - if item.id == id {
145   - may_index = Some(index);
146   - break 'find_item_by_id;
147   - }
148   - }
149   -
150   - if let Some(index) = may_index {
151   - // patch our items to remove the item at the index
152   - let _ = items.list_patch_remove(index);
153   - }
154   - }
155   - _ => {
156   - log::error!("Leaving list logic loop - this shouldn't happen");
157   - break;
158   - },
159   - }
160   - }
161   - // ANCHOR_END: list_logic_loop
162   -}
163   -
164   -// ANCHOR: list_view
165   -fn list_view<T>(to_logic: broadcast::Sender<ListMsg>, children: T) -> ViewBuilder<Dom>
166   -where
167   - T: Stream<Item = ListPatch<ViewBuilder<Dom>>> + Sendable,
168   -{
169   - builder! {
170   - <fieldset>
171   - <legend>"A List of Gizmos"</legend>
172   - <button style:cursor="pointer" on:click=to_logic.sink().contra_map(|_| ListMsg::NewItem)>
173   - "Create a new item"
174   - </button>
175   - <fieldset>
176   - <legend>"Items"</legend>
177   - <ol patch:children=children>
178   - </ol>
179   - </fieldset>
180   - </fieldset>
181   - }
182   -}
183   -// ANCHOR_END: list_view
184   -
185   -/// Create our list component.
186   -fn list() -> Component<Dom> {
187   - let (logic_tx, logic_rx) = broadcast::bounded(1);
188   - let (item_patch_tx, item_patch_rx) = mpmc::bounded(1);
189   - Component::from(list_view(logic_tx, item_patch_rx))
190   - .with_logic(list_logic(logic_rx, item_patch_tx))
191   -}
192   -
193   -#[wasm_bindgen]
194   -pub fn main(parent_id: Option<String>) -> Result<(), JsValue> {
195   - panic::set_hook(Box::new(console_error_panic_hook::hook));
196   - console_log::init_with_level(Level::Trace).unwrap();
197   - let component = list();
198   - let view = component.build().unwrap();
199   -
200   - if let Some(id) = parent_id {
201   - let parent = mogwai::utils::document().get_element_by_id(&id).unwrap();
202   - view.run_in_container(&parent)
203   - } else {
204   - view.run()
205   - }
206   -}
Please register or login to post a comment