This commit is contained in:
parent
b8f59fef2a
commit
8c22c9d35d
2 changed files with 92 additions and 36 deletions
|
@ -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]
|
||||||
|
|
122
src/app.rs
122
src/app.rs
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue