feat: client side read files
This commit is contained in:
@@ -33,6 +33,7 @@ tracing-subscriber = { version = "0.3.18", features = [
|
||||
], optional = true }
|
||||
ron = { version = "0.8" }
|
||||
rand = { version = "0.8", optional = true }
|
||||
web-sys = { version = "0.3.76", features = ["File", "FileList"] }
|
||||
|
||||
[dev-dependencies.serde_json]
|
||||
version = "1"
|
||||
|
||||
@@ -17,7 +17,7 @@ pub fn shell(options: LeptosOptions) -> impl IntoView {
|
||||
<HydrationScripts options />
|
||||
<MetaTags />
|
||||
</head>
|
||||
<body class="bg-slate-950">
|
||||
<body class="bg-slate-950 text-white">
|
||||
<App />
|
||||
</body>
|
||||
</html>
|
||||
@@ -50,7 +50,7 @@ pub fn App() -> impl leptos::IntoView {
|
||||
<main>
|
||||
<Routes fallback=|| "Not found">
|
||||
<Route path=path!("/wall") view=Wall />
|
||||
<Route path=path!("/wall/edit") view=EditWall/>
|
||||
<Route path=path!("/wall/edit") view=EditWall />
|
||||
</Routes>
|
||||
</main>
|
||||
</Router>
|
||||
|
||||
@@ -2,5 +2,5 @@ use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Header() -> impl leptos::IntoView {
|
||||
leptos::view! { <div>"header"</div> }
|
||||
leptos::view! { <div class="border-b py-2 mb-4">"Ascend"</div> }
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
use crate::components::header::Header;
|
||||
use crate::models::HoldPosition;
|
||||
use crate::models::HoldRole;
|
||||
use crate::models::Wall;
|
||||
use leptos::ev::Event;
|
||||
use leptos::html::Input;
|
||||
use leptos::prelude::*;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::FileList;
|
||||
|
||||
#[component]
|
||||
pub fn EditWall() -> impl leptos::IntoView {
|
||||
@@ -15,12 +19,12 @@ pub fn EditWall() -> impl leptos::IntoView {
|
||||
|
||||
leptos::view! {
|
||||
<div class="min-w-screen min-h-screen bg-slate-900">
|
||||
<div class="container mx-auto">
|
||||
<Header />
|
||||
<Await future=load let:data>
|
||||
<Ready data=data.to_owned() />
|
||||
</Await>
|
||||
</div>
|
||||
<div class="container mx-auto">
|
||||
<Header />
|
||||
<Await future=load let:data>
|
||||
<Ready data=data.to_owned() />
|
||||
</Await>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -35,22 +39,68 @@ fn Ready(data: InitialData) -> impl leptos::IntoView {
|
||||
}
|
||||
}
|
||||
|
||||
let mut cells = vec![];
|
||||
for &_hold_position in &hold_positions {
|
||||
let cell = view! { <Hold /> };
|
||||
cells.push(cell);
|
||||
let mut holds = vec![];
|
||||
for &hold_position in &hold_positions {
|
||||
holds.push(view! { <Hold hold_position /> });
|
||||
}
|
||||
|
||||
let grid_classes = format!("grid grid-rows-{} grid-cols-{} gap-4", data.wall.rows, data.wall.cols);
|
||||
|
||||
view! {
|
||||
<div class=move || { grid_classes.clone() }>{cells}</div>
|
||||
}
|
||||
view! { <div class=move || { grid_classes.clone() }>{holds}</div> }
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Hold() -> impl leptos::IntoView {
|
||||
view! { <div class="bg-indigo-100 aspect-square rounded"></div> }
|
||||
fn Hold(hold_position: HoldPosition) -> impl leptos::IntoView {
|
||||
let file_input_ref = NodeRef::<Input>::new();
|
||||
|
||||
let open_camera = move |_| {
|
||||
if let Some(input) = file_input_ref.get() {
|
||||
input.click(); // Trigger the file input click programmatically
|
||||
}
|
||||
};
|
||||
|
||||
// Callback to handle file selection
|
||||
let on_file_input = move |event: Event| {
|
||||
let files: FileList = event.target().unwrap().unchecked_ref::<web_sys::HtmlInputElement>().files().unwrap();
|
||||
leptos::logging::log!("{:?}", &files);
|
||||
let file = files.item(0).unwrap();
|
||||
leptos::logging::log!("{:?}", &file);
|
||||
|
||||
let file_reader = web_sys::FileReader::new().unwrap();
|
||||
file_reader.read_as_array_buffer(&file).unwrap();
|
||||
|
||||
leptos::logging::log!("foo");
|
||||
|
||||
let onload = Closure::wrap(Box::new(move |event: Event| {
|
||||
leptos::logging::log!("onload");
|
||||
let file_reader: web_sys::FileReader = event.target().unwrap().dyn_into().unwrap();
|
||||
let file = file_reader.result().unwrap();
|
||||
let file = web_sys::js_sys::Uint8Array::new(&file);
|
||||
|
||||
let mut file_buffer = vec![0; file.length() as usize];
|
||||
file.copy_to(&mut file_buffer);
|
||||
|
||||
leptos::logging::log!("bytes: {:?}", &file_buffer.len());
|
||||
}) as Box<dyn FnMut(_)>);
|
||||
|
||||
file_reader.set_onload(Some(onload.as_ref().unchecked_ref()));
|
||||
onload.forget();
|
||||
};
|
||||
|
||||
view! {
|
||||
<button on:click=open_camera>
|
||||
<div class="bg-indigo-100 aspect-square rounded"></div>
|
||||
</button>
|
||||
|
||||
<input
|
||||
node_ref=file_input_ref
|
||||
type="file"
|
||||
accept="image/*"
|
||||
capture="user"
|
||||
style="display: none;"
|
||||
on:input=on_file_input
|
||||
/>
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
|
||||
@@ -17,12 +17,12 @@ pub fn Wall() -> impl leptos::IntoView {
|
||||
|
||||
leptos::view! {
|
||||
<div class="min-w-screen min-h-screen bg-slate-900">
|
||||
<div class="container mx-auto">
|
||||
<Header />
|
||||
<Await future=load let:data>
|
||||
<Ready data=data.to_owned() />
|
||||
</Await>
|
||||
</div>
|
||||
<div class="container mx-auto">
|
||||
<Header />
|
||||
<Await future=load let:data>
|
||||
<Ready data=data.to_owned() />
|
||||
</Await>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ fn Ready(data: InitialData) -> impl leptos::IntoView {
|
||||
|
||||
let mut cells = vec![];
|
||||
for &hold_position in &hold_positions {
|
||||
let role = move || current_problem.get().map(|problem| problem.holds.get(&hold_position).copied()).flatten();
|
||||
let role = move || current_problem.get().and_then(|problem| problem.holds.get(&hold_position).copied());
|
||||
let role = Signal::derive(role);
|
||||
|
||||
let cell = view! { <Hold role /> };
|
||||
@@ -72,7 +72,7 @@ fn Hold(#[prop(into)] role: Signal<Option<HoldRole>>) -> impl leptos::IntoView {
|
||||
};
|
||||
let mut s = "bg-indigo-100 aspect-square rounded".to_string();
|
||||
if let Some(c) = role_classes {
|
||||
s.push_str(" ");
|
||||
s.push(' ');
|
||||
s.push_str(c);
|
||||
}
|
||||
s
|
||||
|
||||
Reference in New Issue
Block a user