mirror of
https://github.com/Zenithsiz/dynatos.git
synced 2026-02-04 10:21:23 +00:00
Added dynatos-title to manage the document title.
This commit is contained in:
parent
ede516500a
commit
eab0e669c3
15
Cargo.lock
generated
15
Cargo.lock
generated
@ -108,6 +108,21 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dynatos-title"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"duplicate",
|
||||
"dynatos-reactive",
|
||||
"dynatos-util",
|
||||
"extend",
|
||||
"js-sys",
|
||||
"tracing",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dynatos-util"
|
||||
version = "0.1.0"
|
||||
|
||||
@ -7,6 +7,7 @@ members = [
|
||||
"dynatos-logger",
|
||||
"dynatos-reactive",
|
||||
"dynatos-router",
|
||||
"dynatos-title",
|
||||
"dynatos-util",
|
||||
]
|
||||
resolver = "2"
|
||||
@ -20,6 +21,7 @@ dynatos-html = { path = "dynatos-html" }
|
||||
dynatos-logger = { path = "dynatos-logger" }
|
||||
dynatos-reactive = { path = "dynatos-reactive" }
|
||||
dynatos-router = { path = "dynatos-router" }
|
||||
dynatos-title = { path = "dynatos-title" }
|
||||
dynatos-util = { path = "dynatos-util" }
|
||||
|
||||
anyhow = "1.0.79"
|
||||
|
||||
17
dynatos-title/Cargo.toml
Normal file
17
dynatos-title/Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "dynatos-title"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
dynatos-reactive = { workspace = true }
|
||||
dynatos-util = { workspace = true }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
duplicate = { workspace = true }
|
||||
extend = { workspace = true }
|
||||
js-sys = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
wasm-bindgen = { workspace = true }
|
||||
web-sys = { workspace = true }
|
||||
123
dynatos-title/src/lib.rs
Normal file
123
dynatos-title/src/lib.rs
Normal file
@ -0,0 +1,123 @@
|
||||
//! Title management for [`dynatos`]
|
||||
|
||||
// TODO: It seems that titles aren't getting dropped for some reason.
|
||||
|
||||
// Features
|
||||
#![feature(lint_reasons)]
|
||||
|
||||
// Imports
|
||||
use {dynatos_util::ObjectSetProp, std::cell::RefCell, wasm_bindgen::prelude::wasm_bindgen};
|
||||
|
||||
thread_local! {
|
||||
/// Title stack.
|
||||
static TITLE_STACK: RefCell<Vec<Option<String>>> = RefCell::new(vec![]);
|
||||
}
|
||||
|
||||
/// Title.
|
||||
///
|
||||
/// Sets the title for as long as this lives.
|
||||
#[derive(Debug)]
|
||||
pub struct Title {
|
||||
/// Title index
|
||||
title_idx: usize,
|
||||
}
|
||||
|
||||
impl Title {
|
||||
/// Creates a title.
|
||||
pub fn new<S>(title: S) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
{
|
||||
let title = title.into();
|
||||
|
||||
// Set and add the title to the stack
|
||||
self::set_title(&title);
|
||||
let title_idx = TITLE_STACK.with_borrow_mut(|stack| {
|
||||
// If no title exists, add the current one
|
||||
if stack.is_empty() {
|
||||
stack.push(Some(self::cur_title()));
|
||||
}
|
||||
|
||||
// Then add ours
|
||||
let title_idx = stack.len();
|
||||
stack.push(Some(title));
|
||||
|
||||
title_idx
|
||||
});
|
||||
|
||||
Self { title_idx }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Title {
|
||||
fn drop(&mut self) {
|
||||
// Get the value
|
||||
TITLE_STACK.with_borrow_mut(|stack| {
|
||||
// Remove our title
|
||||
let _prev_title = stack
|
||||
.get_mut(self.title_idx)
|
||||
.and_then(Option::take)
|
||||
.expect("Title was already taken");
|
||||
|
||||
// Then find the next title to set back to.
|
||||
let next_title = loop {
|
||||
let last = stack.last().expect("Should contain at least 1 title");
|
||||
match last {
|
||||
Some(title) => break title,
|
||||
None => {
|
||||
stack.pop().expect("Just checked the value existed");
|
||||
},
|
||||
}
|
||||
};
|
||||
self::set_title(next_title);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait to attach a title to an object.
|
||||
#[extend::ext(name = ObjectAttachTitle)]
|
||||
pub impl js_sys::Object {
|
||||
/// Attaches a title to this object
|
||||
fn attach_title(&self, title: &str) {
|
||||
let prop_name: &str = "__dynatos_title";
|
||||
let title = Title::new(title);
|
||||
self.set_prop(prop_name, WasmTitle(title));
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait to attach a title to an object.
|
||||
#[extend::ext(name = ObjectWithTitle)]
|
||||
pub impl<T> T
|
||||
where
|
||||
T: AsRef<js_sys::Object>,
|
||||
{
|
||||
/// Attaches a title to this object.
|
||||
///
|
||||
/// Returns the object, for chaining
|
||||
fn with_title(self, title: &str) -> Self {
|
||||
self.as_ref().attach_title(title);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the current title
|
||||
fn cur_title() -> String {
|
||||
web_sys::window()
|
||||
.expect("Unable to get window")
|
||||
.document()
|
||||
.expect("Unable to get document")
|
||||
.title()
|
||||
}
|
||||
|
||||
/// Sets the title
|
||||
fn set_title(title: &str) {
|
||||
web_sys::window()
|
||||
.expect("Unable to get window")
|
||||
.document()
|
||||
.expect("Unable to get document")
|
||||
.set_title(title);
|
||||
}
|
||||
|
||||
/// A wasm `Title` type.
|
||||
#[wasm_bindgen]
|
||||
struct WasmTitle(Title);
|
||||
@ -12,6 +12,7 @@ dynatos-html = { path = "../dynatos-html" }
|
||||
dynatos-logger = { path = "../dynatos-logger" }
|
||||
dynatos-reactive = { path = "../dynatos-reactive" }
|
||||
dynatos-router = { path = "../dynatos-router" }
|
||||
dynatos-title = { path = "../dynatos-title" }
|
||||
dynatos-util = { path = "../dynatos-util" }
|
||||
|
||||
anyhow = "1.0.79"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user