cleanup + proper loading bar

This commit is contained in:
Simon Gardling 2022-05-11 10:26:36 -04:00
parent 42596be571
commit e6bee04113
7 changed files with 78 additions and 57 deletions

View File

@ -7,7 +7,7 @@ cargo test --package parsing
bash build.sh release bash build.sh release
echo "rsyncing" echo "rsyncing"
rsync -av --delete --info=progress2 tmp/ rpi-public:/mnt/hdd/http_share/integral-demo/ # rsync -av --delete --info=progress2 tmp/ rpi-public:/mnt/hdd/http_share/ytbn/
rsync -av --delete --info=progress2 --exclude=".git" tmp/ ../titaniumtown.github.io/ rsync -av --delete --info=progress2 --exclude=".git" tmp/ ../titaniumtown.github.io/
rm -fr tmp rm -fr tmp
cd ../titaniumtown.github.io cd ../titaniumtown.github.io

View File

@ -72,6 +72,8 @@ pub const COLORS: &[Color32; 13] = &[
Color32::DARK_BLUE, Color32::DARK_BLUE,
]; ];
const_assert!(!COLORS.is_empty());
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref IS_MOBILE: bool = { static ref IS_MOBILE: bool = {

View File

@ -190,7 +190,7 @@ impl FunctionManager {
} }
} }
pub fn new_function(&mut self) { pub fn push_empty(&mut self) {
self.functions self.functions
.push((Id::new(Uuid::new_v4()), FunctionEntry::EMPTY)); .push((Id::new(Uuid::new_v4()), FunctionEntry::EMPTY));
} }

View File

@ -3,12 +3,13 @@ use crate::function_entry::Riemann;
use crate::function_manager::FunctionManager; use crate::function_manager::FunctionManager;
use crate::misc::{dyn_mut_iter, option_vec_printer, TextData}; use crate::misc::{dyn_mut_iter, option_vec_printer, TextData};
use eframe::App; use eframe::App;
use egui::FontTweak;
use egui::{ use egui::{
plot::Plot, style::Margin, vec2, Button, CentralPanel, Color32, ComboBox, Context, FontData, plot::Plot, style::Margin, vec2, Button, CentralPanel, Color32, ComboBox, Context, FontData,
FontDefinitions, FontFamily, Frame, Key, RichText, SidePanel, Slider, TopBottomPanel, Vec2, FontDefinitions, FontFamily, Frame, Key, Label, Layout, RichText, SidePanel, Slider,
Visuals, Window, TopBottomPanel, Vec2, Visuals, Window,
}; };
use emath::Align2; use emath::{Align, Align2};
use epaint::Rounding; use epaint::Rounding;
use instant::Duration; use instant::Duration;
use std::collections::BTreeMap; use std::collections::BTreeMap;
@ -17,23 +18,6 @@ use std::{io::Read, ops::BitXorAssign, str};
#[cfg(threading)] #[cfg(threading)]
use rayon::iter::{IndexedParallelIterator, ParallelIterator}; use rayon::iter::{IndexedParallelIterator, ParallelIterator};
cfg_if::cfg_if! {
if #[cfg(target_arch = "wasm32")] {
use wasm_bindgen::JsCast;
/// Removes the "loading" element on the web page that displays a loading indicator
fn stop_loading() {
let document = web_sys::window().expect("Could not get web_sys window").document().expect("Could not get web_sys document");
let loading_element = document.get_element_by_id("loading").expect("Couldn't get loading indicator element")
.dyn_into::<web_sys::HtmlElement>().unwrap();
// Remove the element
loading_element.remove();
}
}
}
/// Stores current settings/state of [`MathApp`] /// Stores current settings/state of [`MathApp`]
// TODO: find a better name for this // TODO: find a better name for this
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -124,24 +108,42 @@ impl MathApp {
#[allow(dead_code)] // This is used lol #[allow(dead_code)] // This is used lol
/// Create new instance of [`MathApp`] and return it /// Create new instance of [`MathApp`] and return it
pub fn new(cc: &eframe::CreationContext<'_>) -> Self { pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
let ctx = &cc.egui_ctx;
let start = instant::Instant::now();
// Remove loading indicator on wasm
#[cfg(target_arch = "wasm32")]
stop_loading();
#[cfg(threading)] #[cfg(threading)]
tracing::info!("Threading: Enabled"); tracing::info!("Threading: Enabled");
#[cfg(not(threading))] #[cfg(not(threading))]
tracing::info!("Threading: Disabled"); tracing::info!("Threading: Disabled");
if let Some(web_info) = &cc.integration_info.web_info { cfg_if::cfg_if! {
tracing::info!("Web Info: {:?}", web_info); if #[cfg(target_arch = "wasm32")] {
use wasm_bindgen::JsCast;
use web_sys::HtmlElement;
if let Some(web_info) = &cc.integration_info.web_info {
tracing::info!("Web Info: {:?}", web_info);
}
let document = web_sys::window()
.expect("Could not get web_sys window")
.document()
.expect("Could not get web_sys document");
let loading_element = document
.get_element_by_id("loading")
.expect("Couldn't get loading indicator element")
.dyn_into::<web_sys::HtmlElement>()
.unwrap();
fn update_loading(loading_element: &HtmlElement, add: i32) {
let value =
unsafe { loading_element.get_attribute("value").unwrap_unchecked().parse::<i32>().unwrap_unchecked() };
loading_element.set_attribute("value", &(add + value).to_string()).unwrap();
}
}
} }
tracing::info!("Loading assets..."); tracing::info!("Initializing...");
let start = instant::Instant::now();
let mut tar_file_data = Vec::new(); let mut tar_file_data = Vec::new();
let _ = unsafe { let _ = unsafe {
ruzstd::StreamingDecoder::new(&mut include_bytes!("../assets.tar.zst").as_slice()) ruzstd::StreamingDecoder::new(&mut include_bytes!("../assets.tar.zst").as_slice())
@ -150,6 +152,9 @@ impl MathApp {
.unwrap_unchecked() .unwrap_unchecked()
}; };
#[cfg(target_arch = "wasm32")]
update_loading(&loading_element, 30);
// Stores fonts // Stores fonts
let mut font_ubuntu_light: Option<FontData> = None; let mut font_ubuntu_light: Option<FontData> = None;
let mut font_notoemoji: Option<FontData> = None; let mut font_notoemoji: Option<FontData> = None;
@ -173,24 +178,34 @@ impl MathApp {
let path = unsafe { file.header().path().unwrap_unchecked() }; let path = unsafe { file.header().path().unwrap_unchecked() };
let path_string = path.to_string_lossy(); let path_string = path.to_string_lossy();
tracing::debug!("Loading file: {}", path_string);
// Match the file extention // Match the file extention
if path_string.ends_with(".ttf") { if path_string.ends_with(".ttf") {
// Parse font files // Parse font files
let font_data = FontData::from_owned(data); let font_data = FontData::from_owned(data);
match path_string.as_ref() { match path_string.as_ref() {
"Hack-Regular.ttf" => { "Hack-Regular.ttf" => {
#[cfg(target_arch = "wasm32")]
update_loading(&loading_element, 10);
font_hack = Some(font_data); font_hack = Some(font_data);
} }
"NotoEmoji-Regular.ttf" => { "NotoEmoji-Regular.ttf" => {
#[cfg(target_arch = "wasm32")]
update_loading(&loading_element, 10);
font_notoemoji = Some(font_data); font_notoemoji = Some(font_data);
} }
"Ubuntu-Light.ttf" => { "Ubuntu-Light.ttf" => {
#[cfg(target_arch = "wasm32")]
update_loading(&loading_element, 10);
font_ubuntu_light = Some(font_data); font_ubuntu_light = Some(font_data);
} }
"emoji-icon-font.ttf" => { "emoji-icon-font.ttf" => {
font_emoji_icon = Some(font_data.tweak(egui::FontTweak { #[cfg(target_arch = "wasm32")]
update_loading(&loading_element, 10);
font_emoji_icon = Some(font_data.tweak(FontTweak {
scale: 0.8, // make it smaller scale: 0.8, // make it smaller
y_offset_factor: 0.07, // move it down slightly y_offset_factor: 0.07, // move it down slightly
y_offset: 0.0, y_offset: 0.0,
@ -201,6 +216,8 @@ impl MathApp {
} }
} }
} else if path_string == "text.json" { } else if path_string == "text.json" {
#[cfg(target_arch = "wasm32")]
update_loading(&loading_element, 10);
text_data = Some(TextData::from_json_str(unsafe { text_data = Some(TextData::from_json_str(unsafe {
str::from_utf8(&data).unwrap_unchecked() str::from_utf8(&data).unwrap_unchecked()
})); }));
@ -251,13 +268,20 @@ impl MathApp {
// Initialize fonts // Initialize fonts
// This used to be in the `update` method, but (after a ton of digging) this actually caused OOMs. that was a pain to debug // This used to be in the `update` method, but (after a ton of digging) this actually caused OOMs. that was a pain to debug
ctx.set_fonts(fonts); cc.egui_ctx.set_fonts(fonts);
// Set dark mode by default // Set dark mode by default
ctx.set_visuals(Visuals::dark()); cc.egui_ctx.set_visuals(Visuals::dark());
#[cfg(target_arch = "wasm32")]
update_loading(&loading_element, 20);
tracing::info!("Initialized! Took: {:?}", start.elapsed()); tracing::info!("Initialized! Took: {:?}", start.elapsed());
// Remove loading indicator on wasm
#[cfg(target_arch = "wasm32")]
loading_element.remove();
Self { Self {
functions: Default::default(), functions: Default::default(),
last_info: (vec![None], None), last_info: (vec![None], None),
@ -365,13 +389,13 @@ impl MathApp {
// Only render if there's enough space // Only render if there's enough space
if ui.available_height() > 0.0 { if ui.available_height() > 0.0 {
ui.with_layout(egui::Layout::bottom_up(emath::Align::Min), |ui| { ui.with_layout(Layout::bottom_up(Align::Min), |ui| {
// Contents put in reverse order from bottom to top due to the 'buttom_up' layout // Contents put in reverse order from bottom to top due to the 'buttom_up' layout
// Licensing information // Licensing information
ui.label( ui.add(Label::new(
RichText::new("(and licensed under AGPLv3)").color(Color32::LIGHT_GRAY), RichText::new("(and licensed under AGPLv3)").color(Color32::LIGHT_GRAY),
) ))
.on_hover_text(&self.text.license_info); .on_hover_text(&self.text.license_info);
// Hyperlink to project's github // Hyperlink to project's github
@ -425,7 +449,7 @@ impl App for MathApp {
.on_hover_text("Create and graph new function") .on_hover_text("Create and graph new function")
.clicked() .clicked()
{ {
self.functions.new_function(); self.functions.push_empty();
} }
// Toggles opening the Help window // Toggles opening the Help window

View File

@ -124,7 +124,7 @@ impl SteppedVector {
pub const fn get_max(&self) -> f64 { self.max } pub const fn get_max(&self) -> f64 { self.max }
#[allow(dead_code)] #[allow(dead_code)]
pub fn get_data(&self) -> Vec<f64> { self.data.clone() } pub fn get_data(&self) -> &Vec<f64> { &self.data }
} }
// Convert `Vec<f64>` into [`SteppedVector`] // Convert `Vec<f64>` into [`SteppedVector`]

View File

@ -22,24 +22,24 @@ pub struct AutoComplete<'a> {
} }
impl<'a> const Default for AutoComplete<'a> { impl<'a> const Default for AutoComplete<'a> {
fn default() -> AutoComplete<'a> { fn default() -> AutoComplete<'a> { AutoComplete::EMPTY }
AutoComplete {
i: 0,
hint: &suggestions::HINT_EMPTY,
string: String::new(),
}
}
} }
impl<'a> AutoComplete<'a> { impl<'a> AutoComplete<'a> {
const EMPTY: AutoComplete<'a> = Self {
i: 0,
hint: &suggestions::HINT_EMPTY,
string: String::new(),
};
#[allow(dead_code)] #[allow(dead_code)]
pub fn update_string(&mut self, string: &str) { pub fn update_string(&mut self, string: &str) {
if self.string != string { if self.string != string {
// catch empty strings here to avoid call to `generate_hint` and unnecessary logic // catch empty strings here to avoid call to `generate_hint` and unnecessary logic
if string.is_empty() { if string.is_empty() {
*self = Self::default(); *self = Self::EMPTY;
} else { } else {
self.string = string.to_string(); self.string = string.to_owned();
self.do_update_logic(); self.do_update_logic();
} }
} }

View File

@ -109,12 +109,7 @@
<noscript>Please enable Javascript, this page uses both WebAssembly and Javascript to run.</noscript> <noscript>Please enable Javascript, this page uses both WebAssembly and Javascript to run.</noscript>
<canvas id="canvas"></canvas> <canvas id="canvas"></canvas>
<div class="centered" id="loading"> <progress class="centered" id="loading" value="0" max="100"></progress>
<p style="font-size: 16px;">
Loading…
</p>
<div class="lds-dual-ring"></div>
</div>
<script type="module"> <script type="module">
delete WebAssembly.instantiateStreaming; delete WebAssembly.instantiateStreaming;