Showing
5 changed files
with
86 additions
and
40 deletions
@@ -3,28 +3,38 @@ use web_sys::{HtmlInputElement, ImageBitmap, HtmlCanvasElement, CanvasRenderingC | @@ -3,28 +3,38 @@ use web_sys::{HtmlInputElement, ImageBitmap, HtmlCanvasElement, CanvasRenderingC | ||
3 | 3 | ||
4 | use super::upload::Upload; | 4 | use super::upload::Upload; |
5 | 5 | ||
6 | +#[derive(Clone, Debug)] | ||
7 | +pub(super) enum UploadLogic { | ||
8 | + Add(DomEvent), | ||
9 | + Remove(usize), | ||
10 | +} | ||
11 | + | ||
6 | pub(super) async fn upload_preview_logic( mut rx_canvas :broadcast::Receiver<Dom> | 12 | pub(super) async fn upload_preview_logic( mut rx_canvas :broadcast::Receiver<Dom> |
7 | - , upload :Upload ) { | ||
8 | - while let Some(dom) = rx_canvas.next().await { | ||
9 | - match dom.inner_read() { | ||
10 | - Either::Left(c) => { | ||
11 | - let canvas = c.to_owned().dyn_into::<HtmlCanvasElement>().unwrap(); | ||
12 | - let context = canvas | ||
13 | - . get_context("2d").unwrap().unwrap() | ||
14 | - . dyn_into::<CanvasRenderingContext2d>().unwrap(); | ||
15 | - context | ||
16 | - . draw_image_with_image_bitmap_and_dw_and_dh( | ||
17 | - &upload.bitmap() | ||
18 | - , 0.0, 0.0 | ||
19 | - , canvas.width() as f64, canvas.height() as f64 ) | ||
20 | - . unwrap(); | ||
21 | - }, | ||
22 | - _ => (), | 13 | + , mut rx_click :broadcast::Receiver<DomEvent> |
14 | + , upload :Upload ) { | ||
15 | + if let Some(dom) = rx_canvas.next().await { | ||
16 | + if let Either::Left(c) = dom.inner_read() { | ||
17 | + let canvas = c.to_owned().dyn_into::<HtmlCanvasElement>().unwrap(); | ||
18 | + let context = canvas | ||
19 | + . get_context("2d").unwrap().unwrap() | ||
20 | + . dyn_into::<CanvasRenderingContext2d>().unwrap(); | ||
21 | + context | ||
22 | + . draw_image_with_image_bitmap_and_dw_and_dh( | ||
23 | + &upload.bitmap() | ||
24 | + , 0.0, 0.0 | ||
25 | + , canvas.width() as f64, canvas.height() as f64 ) | ||
26 | + . unwrap(); | ||
23 | } | 27 | } |
24 | } | 28 | } |
29 | + | ||
30 | + while let Some(event) = rx_click.next().await { | ||
31 | + upload.tx_logic . try_broadcast(UploadLogic::Remove(upload.id)) | ||
32 | + . unwrap(); | ||
33 | + } | ||
25 | } | 34 | } |
26 | 35 | ||
27 | -pub(super) async fn upload_logic( mut rx_logic: broadcast::Receiver<DomEvent> | 36 | +pub(super) async fn upload_logic( mut rx_logic :broadcast::Receiver<UploadLogic> |
37 | + , tx_logic :broadcast::Sender<UploadLogic> | ||
28 | , tx_previews: mpmc::Sender<ListPatch<ViewBuilder<Dom>>> | 38 | , tx_previews: mpmc::Sender<ListPatch<ViewBuilder<Dom>>> |
29 | ) { | 39 | ) { |
30 | let mut uploads: ListPatchModel<Upload> = ListPatchModel::new(); | 40 | let mut uploads: ListPatchModel<Upload> = ListPatchModel::new(); |
@@ -37,20 +47,39 @@ pub(super) async fn upload_logic( mut rx_logic: broadcast::Receiver<DomEvent> | @@ -37,20 +47,39 @@ pub(super) async fn upload_logic( mut rx_logic: broadcast::Receiver<DomEvent> | ||
37 | } | 47 | } |
38 | })); | 48 | })); |
39 | 49 | ||
50 | + let mut next_id = 0; | ||
51 | + | ||
40 | while let Some(msg) = rx_logic.next().await { | 52 | while let Some(msg) = rx_logic.next().await { |
41 | - match msg.clone_inner() { | ||
42 | - Either::Left(val) => { | ||
43 | - let filelist = val.dyn_into::<Event>().unwrap() | ||
44 | - . target().unwrap() | ||
45 | - . dyn_into::<HtmlInputElement>().unwrap() | ||
46 | - . files().unwrap(); | ||
47 | - | ||
48 | - for index in 0..filelist.length() { | ||
49 | - let file = filelist.item(index).unwrap(); | ||
50 | - uploads.list_patch_push(Upload::new(file).await); | 53 | + match msg { |
54 | + UploadLogic::Add(event) => | ||
55 | + if let Either::Left(inner) = event.clone_inner() { | ||
56 | + let filelist = inner.dyn_into::<Event>().unwrap() | ||
57 | + . target().unwrap() | ||
58 | + . dyn_into::<HtmlInputElement>().unwrap() | ||
59 | + . files().unwrap(); | ||
60 | + | ||
61 | + for index in 0..filelist.length() { | ||
62 | + let file = filelist.item(index).unwrap(); | ||
63 | + let tx_logic = tx_logic.clone(); | ||
64 | + uploads.list_patch_push( Upload::new(next_id, file, tx_logic) | ||
65 | + . await); | ||
66 | + next_id += 1; | ||
67 | + } | ||
68 | + }, | ||
69 | + UploadLogic::Remove(id) => { | ||
70 | + let mut found = None; | ||
71 | + | ||
72 | + for (upload, index) in uploads.read().await.iter().zip(0..) { | ||
73 | + if upload.id == id { | ||
74 | + found = Some(index); | ||
75 | + break; | ||
76 | + } | ||
77 | + } | ||
78 | + | ||
79 | + if let Some(index) = found { | ||
80 | + uploads.list_patch_remove(index).unwrap(); | ||
51 | } | 81 | } |
52 | }, | 82 | }, |
53 | - _ => (), | ||
54 | } | 83 | } |
55 | } | 84 | } |
56 | } | 85 | } |
@@ -10,8 +10,8 @@ pub(crate) async fn new() -> Component<Dom> { | @@ -10,8 +10,8 @@ pub(crate) async fn new() -> Component<Dom> { | ||
10 | let (tx_logic, rx_logic) = broadcast::bounded(1); | 10 | let (tx_logic, rx_logic) = broadcast::bounded(1); |
11 | let (tx_previews, rx_previews) = mpmc::bounded(1); | 11 | let (tx_previews, rx_previews) = mpmc::bounded(1); |
12 | 12 | ||
13 | - let view = upload_view(tx_logic, rx_previews); | ||
14 | - let logic = upload_logic(rx_logic, tx_previews); | 13 | + let view = upload_view(tx_logic.clone(), rx_previews); |
14 | + let logic = upload_logic(rx_logic, tx_logic, tx_previews); | ||
15 | 15 | ||
16 | Component::from(view).with_logic(logic) | 16 | Component::from(view).with_logic(logic) |
17 | } | 17 | } |
1 | use mogwai::{prelude::*, utils::window}; | 1 | use mogwai::{prelude::*, utils::window}; |
2 | use web_sys::{File, ImageBitmap, ReadableStream}; | 2 | use web_sys::{File, ImageBitmap, ReadableStream}; |
3 | 3 | ||
4 | -use super::{view::upload_preview_view, logic::upload_preview_logic}; | 4 | +use super::{view::upload_preview_view, logic::{upload_preview_logic, UploadLogic}}; |
5 | 5 | ||
6 | #[derive(Clone, Debug)] | 6 | #[derive(Clone, Debug)] |
7 | pub(super) struct Upload { | 7 | pub(super) struct Upload { |
8 | - file :File, | ||
9 | - bitmap :ImageBitmap, | 8 | + pub(super) id :usize, |
9 | + file :File, | ||
10 | + bitmap :ImageBitmap, | ||
11 | + pub(super) tx_logic :broadcast::Sender<UploadLogic>, | ||
10 | } | 12 | } |
11 | 13 | ||
12 | impl Upload { | 14 | impl Upload { |
13 | - pub(super) async fn new(file :File) -> Upload { | 15 | + pub(super) async fn new( id :usize |
16 | + , file :File | ||
17 | + , tx_logic :broadcast::Sender<UploadLogic> | ||
18 | + ) -> Upload { | ||
14 | let bitmap = window() | 19 | let bitmap = window() |
15 | . create_image_bitmap_with_blob(&file.clone().into()) | 20 | . create_image_bitmap_with_blob(&file.clone().into()) |
16 | . unwrap(); | 21 | . unwrap(); |
@@ -18,7 +23,7 @@ impl Upload { | @@ -18,7 +23,7 @@ impl Upload { | ||
18 | . await.unwrap() | 23 | . await.unwrap() |
19 | . dyn_into::<ImageBitmap>().unwrap(); | 24 | . dyn_into::<ImageBitmap>().unwrap(); |
20 | 25 | ||
21 | - Self { file, bitmap } | 26 | + Self { id, file, bitmap, tx_logic } |
22 | } | 27 | } |
23 | 28 | ||
24 | pub(super) fn mime_type(&self) -> String { | 29 | pub(super) fn mime_type(&self) -> String { |
@@ -37,13 +42,15 @@ impl Upload { | @@ -37,13 +42,15 @@ impl Upload { | ||
37 | impl From<Upload> for Component<Dom> { | 42 | impl From<Upload> for Component<Dom> { |
38 | fn from(upload: Upload) -> Self { | 43 | fn from(upload: Upload) -> Self { |
39 | let (tx_canvas, rx_canvas) = broadcast::bounded(1); | 44 | let (tx_canvas, rx_canvas) = broadcast::bounded(1); |
45 | + let (tx_click, rx_click) = broadcast::bounded(1); | ||
40 | 46 | ||
41 | let view = upload_preview_view( tx_canvas | 47 | let view = upload_preview_view( tx_canvas |
48 | + , tx_click | ||
42 | , upload.file.name() | 49 | , upload.file.name() |
43 | , upload.file.size() | 50 | , upload.file.size() |
44 | , upload.file.type_() | 51 | , upload.file.type_() |
45 | , upload.file.last_modified() ); | 52 | , upload.file.last_modified() ); |
46 | - let logic = upload_preview_logic(rx_canvas, upload); | 53 | + let logic = upload_preview_logic(rx_canvas, rx_click, upload); |
47 | 54 | ||
48 | Component::from(view).with_logic(logic) | 55 | Component::from(view).with_logic(logic) |
49 | } | 56 | } |
1 | use mogwai::prelude::*; | 1 | use mogwai::prelude::*; |
2 | 2 | ||
3 | +use crate::component::upload::logic::UploadLogic; | ||
4 | + | ||
3 | pub(super) fn upload_preview_view( tx_canvas :broadcast::Sender<Dom> | 5 | pub(super) fn upload_preview_view( tx_canvas :broadcast::Sender<Dom> |
6 | + , tx_click :broadcast::Sender<DomEvent> | ||
4 | , filename :String | 7 | , filename :String |
5 | , size :f64 | 8 | , size :f64 |
6 | , mime_type :String | 9 | , mime_type :String |
7 | - , mtime :f64 ) -> ViewBuilder<Dom> { | 10 | + , mtime :f64 |
11 | + ) -> ViewBuilder<Dom> { | ||
8 | let post_build = move |dom: &mut Dom| { | 12 | let post_build = move |dom: &mut Dom| { |
9 | tx_canvas.try_broadcast(dom.clone()).unwrap(); | 13 | tx_canvas.try_broadcast(dom.clone()).unwrap(); |
10 | }; | 14 | }; |
11 | 15 | ||
12 | builder! { | 16 | builder! { |
13 | - <li style:display="flex"> | 17 | + <li style:display="flex" |
18 | + on:click=tx_click.sink()> | ||
14 | <canvas width="75px" | 19 | <canvas width="75px" |
15 | height="75px" | 20 | height="75px" |
16 | post:build=post_build /> | 21 | post:build=post_build /> |
@@ -24,9 +29,13 @@ pub(super) fn upload_preview_view( tx_canvas :broadcast::Sender<Dom> | @@ -24,9 +29,13 @@ pub(super) fn upload_preview_view( tx_canvas :broadcast::Sender<Dom> | ||
24 | } | 29 | } |
25 | } | 30 | } |
26 | 31 | ||
27 | -pub(super) fn upload_view( tx_logic: broadcast::Sender<DomEvent> | 32 | +pub(super) fn upload_view( tx_logic: broadcast::Sender<UploadLogic> |
28 | , rx_previews: mpmc::Receiver<ListPatch<ViewBuilder<Dom>>> | 33 | , rx_previews: mpmc::Receiver<ListPatch<ViewBuilder<Dom>>> |
29 | ) -> ViewBuilder<Dom> { | 34 | ) -> ViewBuilder<Dom> { |
35 | + let on_change_filter = tx_logic | ||
36 | + . sink() | ||
37 | + . contra_map(|e| UploadLogic::Add(e)); | ||
38 | + | ||
30 | // <div class="spin"></div> | 39 | // <div class="spin"></div> |
31 | builder! { | 40 | builder! { |
32 | <div class="upload"> | 41 | <div class="upload"> |
@@ -34,7 +43,7 @@ pub(super) fn upload_view( tx_logic: broadcast::Sender<DomEvent> | @@ -34,7 +43,7 @@ pub(super) fn upload_view( tx_logic: broadcast::Sender<DomEvent> | ||
34 | <input type="file" | 43 | <input type="file" |
35 | multiple="multiple" | 44 | multiple="multiple" |
36 | accept="image/*" | 45 | accept="image/*" |
37 | - on:change=tx_logic.sink() /> | 46 | + on:change=on_change_filter /> |
38 | <button>"Upload"</button> | 47 | <button>"Upload"</button> |
39 | </div> | 48 | </div> |
40 | <ul patch:children=rx_previews> | 49 | <ul patch:children=rx_previews> |
Please
register
or
login
to post a comment