Re-implement native support
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

This commit is contained in:
Isaac Mills 2024-03-19 21:40:26 -04:00
parent b8f59fef2a
commit 8c22c9d35d
Signed by: fnmain
GPG key ID: B67D7410F33A0F61
2 changed files with 92 additions and 36 deletions

View file

@ -7,7 +7,6 @@ rust-version = "1.72"
[dependencies] [dependencies]
arc-swap = "1.7.0"
cosmic-jotdown = { git = "https://git.nations.lol/fnmain/cosmic-jotdown" } cosmic-jotdown = { git = "https://git.nations.lol/fnmain/cosmic-jotdown" }
eframe = { version = "0.26.2", default-features = false, features = [ eframe = { version = "0.26.2", default-features = false, features = [
"accesskit", # Make egui comptaible with screen readers. NOTE: adds a lot of dependencies. "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 } keyframe = { version = "1.1.1", default-features = false }
log = "0.4" log = "0.4"
range-map = "0.2.0" range-map = "0.2.0"
wasm-bindgen = "0.2.92"
web-sys = { version = "0.3.69", features = ["Window", "History", "PopStateEvent"] }
# native: # native:
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
@ -35,6 +32,9 @@ env_logger = "0.10"
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
wgpu = { version = "0.19.3", features = ["webgpu", "webgl"] } wgpu = { version = "0.19.3", features = ["webgpu", "webgl"] }
wasm-bindgen-futures = "0.4" 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] [profile.release]

View file

@ -1,12 +1,17 @@
use std as alloc; use std as alloc;
use std::borrow::Cow; 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; use std::ops::DerefMut;
#[cfg(target_arch = "wasm32")]
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use alloc::cell::RefCell; #[cfg(target_arch = "wasm32")]
use alloc::mem::ManuallyDrop;
use alloc::ops::Deref;
use arc_swap::ArcSwapAny; use arc_swap::ArcSwapAny;
use cosmic_jotdown::jotdown::{self, Event, ListKind}; use cosmic_jotdown::jotdown::{self, Event, ListKind};
use cosmic_jotdown::{Indent, INDENT_AMOUNT}; use cosmic_jotdown::{Indent, INDENT_AMOUNT};
@ -47,10 +52,13 @@ pub struct Portfolio {
window: ContextWindow, window: ContextWindow,
buffer_size: Vec2, buffer_size: Vec2,
max_size: Rect, max_size: Rect,
#[cfg(target_arch = "wasm32")]
states: Rc<RefCell<Vec<State>>>, states: Rc<RefCell<Vec<State>>>,
#[cfg(target_arch = "wasm32")]
next_state: Rc<ArcSwapAny<Option<Rc<State>>>>, next_state: Rc<ArcSwapAny<Option<Rc<State>>>>,
} }
#[cfg(target_arch = "wasm32")]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum State { pub enum State {
Home, Home,
@ -61,6 +69,7 @@ pub enum State {
pub struct ContextWindow { pub struct ContextWindow {
pub size: Vec2, pub size: Vec2,
pub text: Vec<(Rect, Indent, ContextBlock)>, pub text: Vec<(Rect, Indent, ContextBlock)>,
#[cfg(target_arch = "wasm32")]
pub name: &'static str, pub name: &'static str,
} }
@ -226,11 +235,11 @@ impl ContextWindow {
pub fn set_content( pub fn set_content(
&mut self, &mut self,
content: &'static Cow<'static, [Event<'static>]>, content: &'static Cow<'static, [Event<'static>]>,
transform: Option<Mat2>, #[cfg(target_arch = "wasm32")] transform: Option<Mat2>,
name: Option<&'static str>, #[cfg(target_arch = "wasm32")] name: Option<&'static str>,
font_system: &mut FontSystem, font_system: &mut FontSystem,
mut max_width: f32, mut max_width: f32,
states: &mut Vec<State>, #[cfg(target_arch = "wasm32")] states: &mut Vec<State>,
) { ) {
self.size = Vec2::new(max_width / 1.5, 0.0); self.size = Vec2::new(max_width / 1.5, 0.0);
let mut last_indent = None; let mut last_indent = None;
@ -343,6 +352,7 @@ impl ContextWindow {
self.size.y += size.y; self.size.y += size.y;
} }
#[cfg(target_arch = "wasm32")]
if let Some(name) = name { if let Some(name) = name {
self.name = name; self.name = name;
let state = states.len(); let state = states.len();
@ -410,28 +420,35 @@ impl Portfolio {
// Load previous app state (if any). // Load previous app state (if any).
// Note that you must enable the `persistence` feature for this to work. // Note that you must enable the `persistence` feature for this to work.
let states = Rc::new(RefCell::new(Vec::new())); #[cfg(target_arch = "wasm32")]
let pop_state = Rc::clone(&states); let states;
let next_state = Rc::new(ArcSwapAny::new(None)); #[cfg(target_arch = "wasm32")]
let pop_next_state = Rc::clone(&next_state); let next_state;
let popstate_closure = #[cfg(target_arch = "wasm32")]
ManuallyDrop::new(wasm_bindgen::closure::Closure::<dyn FnMut(_)>::new( {
move |s: web_sys::PopStateEvent| { states = Rc::new(RefCell::new(Vec::new()));
let state = s.state(); let pop_state = Rc::clone(&states);
if state.is_null() { next_state = Rc::new(ArcSwapAny::new(None));
pop_next_state.store(Some(Rc::new(State::Home))); let pop_next_state = Rc::clone(&next_state);
} else { let popstate_closure =
let state = state.as_f64().unwrap() as usize; ManuallyDrop::new(wasm_bindgen::closure::Closure::<dyn FnMut(_)>::new(
let pop_state = pop_state.borrow(); move |s: web_sys::PopStateEvent| {
pop_next_state.store(pop_state.get(state).map(|s| Rc::new(*s))); let state = s.state();
} if state.is_null() {
}, pop_next_state.store(Some(Rc::new(State::Home)));
)); } else {
web_sys::window() let state = state.as_f64().unwrap() as usize;
.unwrap() let pop_state = pop_state.borrow();
.set_onpopstate(Some(wasm_bindgen::JsCast::unchecked_ref( pop_next_state.store(pop_state.get(state).map(|s| Rc::new(*s)));
popstate_closure.as_ref(), }
))); },
));
web_sys::window()
.unwrap()
.set_onpopstate(Some(wasm_bindgen::JsCast::unchecked_ref(
popstate_closure.as_ref(),
)));
}
egui_extras::install_image_loaders(&cc.egui_ctx); egui_extras::install_image_loaders(&cc.egui_ctx);
let mut font_system = FontSystem::new(); let mut font_system = FontSystem::new();
@ -486,12 +503,19 @@ impl Portfolio {
buffer_size, buffer_size,
window: ContextWindow::default(), window: ContextWindow::default(),
max_size: Rect::ZERO, max_size: Rect::ZERO,
#[cfg(target_arch = "wasm32")]
states, states,
#[cfg(target_arch = "wasm32")]
next_state, next_state,
} }
} }
pub fn click(&mut self, ui: &egui::Ui, transform: Option<Mat2>, push_state: bool) { pub fn click(
&mut self,
ui: &egui::Ui,
transform: Option<Mat2>,
#[cfg(target_arch = "wasm32")] push_state: bool,
) {
self.from_size = self.to_size; self.from_size = self.to_size;
self.from_pos = self.to_pos; self.from_pos = self.to_pos;
self.click_time_offset = ui.input(|i| i.time); self.click_time_offset = ui.input(|i| i.time);
@ -499,6 +523,7 @@ impl Portfolio {
self.to_size = 0.6; self.to_size = 0.6;
self.to_pos = [0.0, 0.0]; self.to_pos = [0.0, 0.0];
self.zoomed = false; self.zoomed = false;
#[cfg(target_arch = "wasm32")]
if push_state { if push_state {
let mut states = self.states.borrow_mut(); let mut states = self.states.borrow_mut();
let state = states.len(); let state = states.len();
@ -596,6 +621,7 @@ impl Portfolio {
); );
} }
#[cfg(target_arch = "wasm32")]
fn update_state(&mut self, ui: &mut egui::Ui) { fn update_state(&mut self, ui: &mut egui::Ui) {
if let Some(state) = self.next_state.load().deref() { if let Some(state) = self.next_state.load().deref() {
log::info!("update_state"); log::info!("update_state");
@ -632,6 +658,7 @@ impl eframe::App for Portfolio {
.frame(Frame::default().fill(Color32::BLACK)) .frame(Frame::default().fill(Color32::BLACK))
.show(ctx, |ui| { .show(ctx, |ui| {
self.update_customs(ui); self.update_customs(ui);
#[cfg(target_arch = "wasm32")]
self.update_state(ui); self.update_state(ui);
self.custom.custom_painting(ui); self.custom.custom_painting(ui);
if ui.max_rect() != self.max_size { if ui.max_rect() != self.max_size {
@ -921,7 +948,12 @@ impl eframe::App for Portfolio {
self.image_zoomed = false; self.image_zoomed = false;
}); });
} else if icon_link.is_none() { } else if icon_link.is_none() {
self.click(ui, None, true); self.click(
ui,
None,
#[cfg(target_arch = "wasm32")]
true,
);
} }
} }
} else { } else {
@ -938,13 +970,21 @@ impl eframe::App for Portfolio {
} }
if name_resp.clicked() { if name_resp.clicked() {
self.click(ui, None, true); self.click(
ui,
None,
#[cfg(target_arch = "wasm32")]
true,
);
self.window.set_content( self.window.set_content(
&ABOUT_ME, &ABOUT_ME,
#[cfg(target_arch = "wasm32")]
None, None,
#[cfg(target_arch = "wasm32")]
Some("About Me"), Some("About Me"),
self.font_system.lock().deref_mut(), self.font_system.lock().deref_mut(),
ui.max_rect().width(), ui.max_rect().width(),
#[cfg(target_arch = "wasm32")]
self.states.borrow_mut().deref_mut(), self.states.borrow_mut().deref_mut(),
); );
} }
@ -991,13 +1031,21 @@ impl eframe::App for Portfolio {
if response.clicked() { if response.clicked() {
self.window.set_content( self.window.set_content(
i.content, i.content,
#[cfg(target_arch = "wasm32")]
Some(transform), Some(transform),
#[cfg(target_arch = "wasm32")]
Some(i.name), Some(i.name),
self.font_system.lock().deref_mut(), self.font_system.lock().deref_mut(),
ui.max_rect().width(), ui.max_rect().width(),
#[cfg(target_arch = "wasm32")]
self.states.borrow_mut().deref_mut(), 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.offset = Vec2::ZERO;
scroll_area.state.store(ui.ctx(), scroll_area.id); 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()); let transform = glam::Mat2::from_angle((-icon.angle_at).to_radians());
self.window.set_content( self.window.set_content(
icon.content, icon.content,
#[cfg(target_arch = "wasm32")]
Some(transform), Some(transform),
#[cfg(target_arch = "wasm32")]
Some(icon.name), Some(icon.name),
self.font_system.lock().deref_mut(), self.font_system.lock().deref_mut(),
ui.max_rect().width(), ui.max_rect().width(),
#[cfg(target_arch = "wasm32")]
self.states.borrow_mut().deref_mut(), self.states.borrow_mut().deref_mut(),
); );
self.zoomed = false; self.zoomed = false;
self.click(ui, Some(transform), true); self.click(
ui,
Some(transform),
#[cfg(target_arch = "wasm32")]
true,
);
self.zoomed = true; self.zoomed = true;
scroll_area.state.offset = Vec2::ZERO; scroll_area.state.offset = Vec2::ZERO;