use common::ron_api; use gloo::{console::log, events::EventListener, utils::window}; use utils::by_id; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::spawn_local; use web_sys::{HtmlElement, HtmlInputElement, HtmlSelectElement}; use crate::utils::selector; mod calendar; mod error; mod modal_dialog; mod on_click; mod pages; mod recipe_scheduler; mod request; mod shopping_list; mod toast; mod utils; #[wasm_bindgen(start)] pub fn main() -> Result<(), JsValue> { console_error_panic_hook::set_once(); let lang = utils::get_current_lang(); let location = window().location().pathname()?; let path: Vec<&str> = location .split('/') .skip(1) .skip_while(|part| *part == lang) .collect(); let mut location_without_lang = String::new(); for part in &path { location_without_lang.push('/'); location_without_lang.push_str(part); } let is_user_logged = selector::("html") .dataset() .get("userLogged") .map(|v| v == "true") .unwrap_or_default(); let first_day_of_the_week = selector::("html") .dataset() .get("userFirstDayOfTheWeek") .map(|v| v.parse().unwrap_or(chrono::Weekday::Mon)) .unwrap_or(chrono::Weekday::Mon); match path[..] { ["recipe", "edit", id] => match id.parse::() { Ok(id) => pages::recipe_edit::setup_page(id), Err(error) => log!(format!("Error parsing recipe id: {}", error)), }, ["recipe", "view", id] => match id.parse::() { Ok(id) => pages::recipe_view::setup_page(id, is_user_logged, first_day_of_the_week), Err(error) => log!(format!("Error parsing recipe id: {}", error)), }, ["dev_panel"] => pages::dev_panel::setup_page(), // Home. [""] => pages::home::setup_page(is_user_logged, first_day_of_the_week), _ => log!("Path unknown: ", location), } // Language handling. let select_language: HtmlSelectElement = by_id("select-website-language"); EventListener::new(&select_language.clone(), "input", move |_event| { let lang = select_language.value(); let body = ron_api::SetLang { lang: lang.clone() }; let location_without_lang = location_without_lang.clone(); spawn_local(async move { let _ = request::put::<(), _>("lang", body).await; window() .location() .set_href(&format!( "/{}{}{}", lang, location_without_lang, window().location().search().unwrap().as_str() )) .unwrap(); }); }) .forget(); // Dark/light theme handling. if get_cookie_dark_theme().is_none() && window() .match_media("(prefers-color-scheme: dark)") .map(|r| r.is_some()) .unwrap_or_default() { set_cookie_dark_theme(true); window().location().reload().unwrap(); }; let toggle_theme: HtmlInputElement = selector("#toggle-theme input"); EventListener::new(&toggle_theme.clone(), "change", move |_event| { set_cookie_dark_theme(!toggle_theme.checked()); window().location().reload().unwrap(); }) .forget(); Ok(()) } /// `wasm_cookies::set` is specific for the wasm32 target architecture and Rust Analyzer says /// it's an error, it's not possible to configure different target configurations into the same /// workspace. Here is the issue: /// https://users.rust-lang.org/t/can-i-configure-rust-analyzer-vscode-to-use-a-different-target-for-different-crates-in-my-workspce/123661 #[cfg(target_arch = "wasm32")] fn set_cookie_dark_theme(dark_theme: bool) { wasm_cookies::set( common::consts::COOKIE_DARK_THEME, &dark_theme.to_string(), &wasm_cookies::CookieOptions { path: Some("/"), domain: None, expires: None, secure: false, same_site: wasm_cookies::SameSite::Strict, }, ); } #[cfg(not(target_arch = "wasm32"))] fn set_cookie_dark_theme(_dark_theme: bool) {} #[cfg(target_arch = "wasm32")] fn get_cookie_dark_theme() -> Option { wasm_cookies::get(common::consts::COOKIE_DARK_THEME).map(|value| match value { Ok(str) => match str.parse() { Ok(v) => v, Err(_) => { set_cookie_dark_theme(false); false } }, Err(_) => false, }) } #[cfg(not(target_arch = "wasm32"))] fn get_cookie_dark_theme() -> Option { Some(false) }