Showing
5 changed files
with
86 additions
and
40 deletions
| ... | ... | @@ -3,28 +3,38 @@ use web_sys::{HtmlInputElement, ImageBitmap, HtmlCanvasElement, CanvasRenderingC |
| 3 | 3 | |
| 4 | 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 | 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 | 38 | , tx_previews: mpmc::Sender<ListPatch<ViewBuilder<Dom>>> |
| 29 | 39 | ) { |
| 30 | 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 | 47 | } |
| 38 | 48 | })); |
| 39 | 49 | |
| 50 | + let mut next_id = 0; | |
| 51 | + | |
| 40 | 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 | 10 | let (tx_logic, rx_logic) = broadcast::bounded(1); |
| 11 | 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 | 16 | Component::from(view).with_logic(logic) |
| 17 | 17 | } | ... | ... |
| 1 | 1 | use mogwai::{prelude::*, utils::window}; |
| 2 | 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 | 6 | #[derive(Clone, Debug)] |
| 7 | 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 | 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 | 19 | let bitmap = window() |
| 15 | 20 | . create_image_bitmap_with_blob(&file.clone().into()) |
| 16 | 21 | . unwrap(); |
| ... | ... | @@ -18,7 +23,7 @@ impl Upload { |
| 18 | 23 | . await.unwrap() |
| 19 | 24 | . dyn_into::<ImageBitmap>().unwrap(); |
| 20 | 25 | |
| 21 | - Self { file, bitmap } | |
| 26 | + Self { id, file, bitmap, tx_logic } | |
| 22 | 27 | } |
| 23 | 28 | |
| 24 | 29 | pub(super) fn mime_type(&self) -> String { |
| ... | ... | @@ -37,13 +42,15 @@ impl Upload { |
| 37 | 42 | impl From<Upload> for Component<Dom> { |
| 38 | 43 | fn from(upload: Upload) -> Self { |
| 39 | 44 | let (tx_canvas, rx_canvas) = broadcast::bounded(1); |
| 45 | + let (tx_click, rx_click) = broadcast::bounded(1); | |
| 40 | 46 | |
| 41 | 47 | let view = upload_preview_view( tx_canvas |
| 48 | + , tx_click | |
| 42 | 49 | , upload.file.name() |
| 43 | 50 | , upload.file.size() |
| 44 | 51 | , upload.file.type_() |
| 45 | 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 | 55 | Component::from(view).with_logic(logic) |
| 49 | 56 | } | ... | ... |
| 1 | 1 | use mogwai::prelude::*; |
| 2 | 2 | |
| 3 | +use crate::component::upload::logic::UploadLogic; | |
| 4 | + | |
| 3 | 5 | pub(super) fn upload_preview_view( tx_canvas :broadcast::Sender<Dom> |
| 6 | + , tx_click :broadcast::Sender<DomEvent> | |
| 4 | 7 | , filename :String |
| 5 | 8 | , size :f64 |
| 6 | 9 | , mime_type :String |
| 7 | - , mtime :f64 ) -> ViewBuilder<Dom> { | |
| 10 | + , mtime :f64 | |
| 11 | + ) -> ViewBuilder<Dom> { | |
| 8 | 12 | let post_build = move |dom: &mut Dom| { |
| 9 | 13 | tx_canvas.try_broadcast(dom.clone()).unwrap(); |
| 10 | 14 | }; |
| 11 | 15 | |
| 12 | 16 | builder! { |
| 13 | - <li style:display="flex"> | |
| 17 | + <li style:display="flex" | |
| 18 | + on:click=tx_click.sink()> | |
| 14 | 19 | <canvas width="75px" |
| 15 | 20 | height="75px" |
| 16 | 21 | post:build=post_build /> |
| ... | ... | @@ -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 | 33 | , rx_previews: mpmc::Receiver<ListPatch<ViewBuilder<Dom>>> |
| 29 | 34 | ) -> ViewBuilder<Dom> { |
| 35 | + let on_change_filter = tx_logic | |
| 36 | + . sink() | |
| 37 | + . contra_map(|e| UploadLogic::Add(e)); | |
| 38 | + | |
| 30 | 39 | // <div class="spin"></div> |
| 31 | 40 | builder! { |
| 32 | 41 | <div class="upload"> |
| ... | ... | @@ -34,7 +43,7 @@ pub(super) fn upload_view( tx_logic: broadcast::Sender<DomEvent> |
| 34 | 43 | <input type="file" |
| 35 | 44 | multiple="multiple" |
| 36 | 45 | accept="image/*" |
| 37 | - on:change=tx_logic.sink() /> | |
| 46 | + on:change=on_change_filter /> | |
| 38 | 47 | <button>"Upload"</button> |
| 39 | 48 | </div> |
| 40 | 49 | <ul patch:children=rx_previews> | ... | ... |
Please
register
or
login
to post a comment