From 8c22c9d35d929861379c7bc77d66b173a764d1bf Mon Sep 17 00:00:00 2001 From: Isaac Mills Date: Tue, 19 Mar 2024 21:40:26 -0400 Subject: [PATCH] Re-implement native support --- Cargo.toml | 6 +-- src/app.rs | 122 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 92 insertions(+), 36 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8f24e64..e71064e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ rust-version = "1.72" [dependencies] -arc-swap = "1.7.0" cosmic-jotdown = { git = "https://git.nations.lol/fnmain/cosmic-jotdown" } eframe = { version = "0.26.2", default-features = false, features = [ "accesskit", # Make egui comptaible with screen readers. NOTE: adds a lot of dependencies. @@ -24,8 +23,6 @@ image = { version = "0.24.9", features = ["jpeg", "png"] } keyframe = { version = "1.1.1", default-features = false } log = "0.4" range-map = "0.2.0" -wasm-bindgen = "0.2.92" -web-sys = { version = "0.3.69", features = ["Window", "History", "PopStateEvent"] } # native: [target.'cfg(not(target_arch = "wasm32"))'.dependencies] @@ -35,6 +32,9 @@ env_logger = "0.10" [target.'cfg(target_arch = "wasm32")'.dependencies] wgpu = { version = "0.19.3", features = ["webgpu", "webgl"] } wasm-bindgen-futures = "0.4" +wasm-bindgen = "0.2.92" +web-sys = { version = "0.3.69", features = ["Window", "History", "PopStateEvent"] } +arc-swap = "1.7.0" [profile.release] diff --git a/src/app.rs b/src/app.rs index 1735120..61fca11 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,12 +1,17 @@ use std as alloc; use std::borrow::Cow; +#[cfg(target_arch = "wasm32")] +use std::cell::RefCell; +#[cfg(target_arch = "wasm32")] +use std::mem::ManuallyDrop; +#[cfg(target_arch = "wasm32")] +use std::ops::Deref; use std::ops::DerefMut; +#[cfg(target_arch = "wasm32")] use std::rc::Rc; use std::sync::Arc; -use alloc::cell::RefCell; -use alloc::mem::ManuallyDrop; -use alloc::ops::Deref; +#[cfg(target_arch = "wasm32")] use arc_swap::ArcSwapAny; use cosmic_jotdown::jotdown::{self, Event, ListKind}; use cosmic_jotdown::{Indent, INDENT_AMOUNT}; @@ -47,10 +52,13 @@ pub struct Portfolio { window: ContextWindow, buffer_size: Vec2, max_size: Rect, + #[cfg(target_arch = "wasm32")] states: Rc>>, + #[cfg(target_arch = "wasm32")] next_state: Rc>>>, } +#[cfg(target_arch = "wasm32")] #[derive(Clone, Copy)] pub enum State { Home, @@ -61,6 +69,7 @@ pub enum State { pub struct ContextWindow { pub size: Vec2, pub text: Vec<(Rect, Indent, ContextBlock)>, + #[cfg(target_arch = "wasm32")] pub name: &'static str, } @@ -226,11 +235,11 @@ impl ContextWindow { pub fn set_content( &mut self, content: &'static Cow<'static, [Event<'static>]>, - transform: Option, - name: Option<&'static str>, + #[cfg(target_arch = "wasm32")] transform: Option, + #[cfg(target_arch = "wasm32")] name: Option<&'static str>, font_system: &mut FontSystem, mut max_width: f32, - states: &mut Vec, + #[cfg(target_arch = "wasm32")] states: &mut Vec, ) { self.size = Vec2::new(max_width / 1.5, 0.0); let mut last_indent = None; @@ -343,6 +352,7 @@ impl ContextWindow { self.size.y += size.y; } + #[cfg(target_arch = "wasm32")] if let Some(name) = name { self.name = name; let state = states.len(); @@ -410,28 +420,35 @@ impl Portfolio { // Load previous app state (if any). // Note that you must enable the `persistence` feature for this to work. - let states = Rc::new(RefCell::new(Vec::new())); - let pop_state = Rc::clone(&states); - let next_state = Rc::new(ArcSwapAny::new(None)); - let pop_next_state = Rc::clone(&next_state); - let popstate_closure = - ManuallyDrop::new(wasm_bindgen::closure::Closure::::new( - move |s: web_sys::PopStateEvent| { - let state = s.state(); - if state.is_null() { - pop_next_state.store(Some(Rc::new(State::Home))); - } else { - let state = state.as_f64().unwrap() as usize; - let pop_state = pop_state.borrow(); - pop_next_state.store(pop_state.get(state).map(|s| Rc::new(*s))); - } - }, - )); - web_sys::window() - .unwrap() - .set_onpopstate(Some(wasm_bindgen::JsCast::unchecked_ref( - popstate_closure.as_ref(), - ))); + #[cfg(target_arch = "wasm32")] + let states; + #[cfg(target_arch = "wasm32")] + let next_state; + #[cfg(target_arch = "wasm32")] + { + states = Rc::new(RefCell::new(Vec::new())); + let pop_state = Rc::clone(&states); + next_state = Rc::new(ArcSwapAny::new(None)); + let pop_next_state = Rc::clone(&next_state); + let popstate_closure = + ManuallyDrop::new(wasm_bindgen::closure::Closure::::new( + move |s: web_sys::PopStateEvent| { + let state = s.state(); + if state.is_null() { + pop_next_state.store(Some(Rc::new(State::Home))); + } else { + let state = state.as_f64().unwrap() as usize; + let pop_state = pop_state.borrow(); + pop_next_state.store(pop_state.get(state).map(|s| Rc::new(*s))); + } + }, + )); + web_sys::window() + .unwrap() + .set_onpopstate(Some(wasm_bindgen::JsCast::unchecked_ref( + popstate_closure.as_ref(), + ))); + } egui_extras::install_image_loaders(&cc.egui_ctx); let mut font_system = FontSystem::new(); @@ -486,12 +503,19 @@ impl Portfolio { buffer_size, window: ContextWindow::default(), max_size: Rect::ZERO, + #[cfg(target_arch = "wasm32")] states, + #[cfg(target_arch = "wasm32")] next_state, } } - pub fn click(&mut self, ui: &egui::Ui, transform: Option, push_state: bool) { + pub fn click( + &mut self, + ui: &egui::Ui, + transform: Option, + #[cfg(target_arch = "wasm32")] push_state: bool, + ) { self.from_size = self.to_size; self.from_pos = self.to_pos; self.click_time_offset = ui.input(|i| i.time); @@ -499,6 +523,7 @@ impl Portfolio { self.to_size = 0.6; self.to_pos = [0.0, 0.0]; self.zoomed = false; + #[cfg(target_arch = "wasm32")] if push_state { let mut states = self.states.borrow_mut(); let state = states.len(); @@ -596,6 +621,7 @@ impl Portfolio { ); } + #[cfg(target_arch = "wasm32")] fn update_state(&mut self, ui: &mut egui::Ui) { if let Some(state) = self.next_state.load().deref() { log::info!("update_state"); @@ -632,6 +658,7 @@ impl eframe::App for Portfolio { .frame(Frame::default().fill(Color32::BLACK)) .show(ctx, |ui| { self.update_customs(ui); + #[cfg(target_arch = "wasm32")] self.update_state(ui); self.custom.custom_painting(ui); if ui.max_rect() != self.max_size { @@ -921,7 +948,12 @@ impl eframe::App for Portfolio { self.image_zoomed = false; }); } else if icon_link.is_none() { - self.click(ui, None, true); + self.click( + ui, + None, + #[cfg(target_arch = "wasm32")] + true, + ); } } } else { @@ -938,13 +970,21 @@ impl eframe::App for Portfolio { } if name_resp.clicked() { - self.click(ui, None, true); + self.click( + ui, + None, + #[cfg(target_arch = "wasm32")] + true, + ); self.window.set_content( &ABOUT_ME, + #[cfg(target_arch = "wasm32")] None, + #[cfg(target_arch = "wasm32")] Some("About Me"), self.font_system.lock().deref_mut(), ui.max_rect().width(), + #[cfg(target_arch = "wasm32")] self.states.borrow_mut().deref_mut(), ); } @@ -991,13 +1031,21 @@ impl eframe::App for Portfolio { if response.clicked() { self.window.set_content( i.content, + #[cfg(target_arch = "wasm32")] Some(transform), + #[cfg(target_arch = "wasm32")] Some(i.name), self.font_system.lock().deref_mut(), ui.max_rect().width(), + #[cfg(target_arch = "wasm32")] self.states.borrow_mut().deref_mut(), ); - self.click(ui, Some(transform), true); + self.click( + ui, + Some(transform), + #[cfg(target_arch = "wasm32")] + true, + ); scroll_area.state.offset = Vec2::ZERO; scroll_area.state.store(ui.ctx(), scroll_area.id); } @@ -1014,15 +1062,23 @@ impl eframe::App for Portfolio { let transform = glam::Mat2::from_angle((-icon.angle_at).to_radians()); self.window.set_content( icon.content, + #[cfg(target_arch = "wasm32")] Some(transform), + #[cfg(target_arch = "wasm32")] Some(icon.name), self.font_system.lock().deref_mut(), ui.max_rect().width(), + #[cfg(target_arch = "wasm32")] self.states.borrow_mut().deref_mut(), ); self.zoomed = false; - self.click(ui, Some(transform), true); + self.click( + ui, + Some(transform), + #[cfg(target_arch = "wasm32")] + true, + ); self.zoomed = true; scroll_area.state.offset = Vec2::ZERO;