forked from yewstack/yew
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
128 lines (115 loc) · 4.12 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::collections::HashMap;
use web_sys::{Event, HtmlInputElement};
use yew::{html, html::TargetCast, Component, Context, Html};
use gloo_file::callbacks::FileReader;
use gloo_file::File;
type Chunks = bool;
pub enum Msg {
Loaded(String, String),
LoadedBytes(String, Vec<u8>),
Files(Vec<File>, Chunks),
ToggleReadBytes,
}
pub struct App {
readers: HashMap<String, FileReader>,
files: Vec<String>,
read_bytes: bool,
}
impl Component for App {
type Message = Msg;
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {
readers: HashMap::default(),
files: vec![],
read_bytes: false,
}
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::Loaded(file_name, data) => {
let info = format!("file_name: {}, data: {:?}", file_name, data);
self.files.push(info);
self.readers.remove(&file_name);
true
}
Msg::LoadedBytes(file_name, data) => {
let info = format!("file_name: {}, data: {:?}", file_name, data);
self.files.push(info);
self.readers.remove(&file_name);
true
}
Msg::Files(files, bytes) => {
for file in files.into_iter() {
let file_name = file.name();
let task = {
let file_name = file_name.clone();
let link = ctx.link().clone();
if bytes {
gloo_file::callbacks::read_as_bytes(&file, move |res| {
link.send_message(Msg::LoadedBytes(
file_name,
res.expect("failed to read file"),
))
})
} else {
gloo_file::callbacks::read_as_text(&file, move |res| {
link.send_message(Msg::Loaded(
file_name,
res.unwrap_or_else(|e| e.to_string()),
))
})
}
};
self.readers.insert(file_name, task);
}
true
}
Msg::ToggleReadBytes => {
self.read_bytes = !self.read_bytes;
true
}
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
let flag = self.read_bytes;
html! {
<div>
<div>
<p>{ "Choose a file to upload to see the uploaded bytes" }</p>
<input type="file" multiple=true onchange={ctx.link().callback(move |e: Event| {
let mut result = Vec::new();
let input: HtmlInputElement = e.target_unchecked_into();
if let Some(files) = input.files() {
let files = js_sys::try_iter(&files)
.unwrap()
.unwrap()
.map(|v| web_sys::File::from(v.unwrap()))
.map(File::from);
result.extend(files);
}
Msg::Files(result, flag)
})}
/>
</div>
<div>
<label>{ "Read bytes" }</label>
<input type="checkbox" checked={flag} onclick={ctx.link().callback(|_| Msg::ToggleReadBytes)} />
</div>
<ul>
{ for self.files.iter().map(|f| Self::view_file(f)) }
</ul>
</div>
}
}
}
impl App {
fn view_file(data: &str) -> Html {
html! {
<li>{ data }</li>
}
}
}
fn main() {
yew::Renderer::<App>::new().render();
}