AkurAI Build
Menu

Public repository / master

AkurAI-Framework / crates/ui/src/host/mod.rs

Latest change fee5b6c2cde89fa6bf8dc51068af7336b56a88b8 - akurai-ui: platform::open_url (hand a URL, e.g. a native shell's scheme, to the window) by Ólafur Búi Ólafsson

//! The DOM host: the only place the UI touches the platform.
//!
//! In the browser (`wasm32`) every call crosses into `host.js`, a small shim
//! that owns a handle table of DOM nodes. Everywhere else (`cargo test`) the
//! same API is served by an in-memory DOM, so components are tested natively
//! with no browser. Both sides expose exactly the functions below.
//!
//! Node handles are never reused, so a stale handle can only miss, never hit
//! the wrong node. Removing a node releases the handles of its whole subtree.

#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod native;
#[cfg(target_arch = "wasm32")]
mod wasm;

#[cfg(not(target_arch = "wasm32"))]
use native as imp;
#[cfg(target_arch = "wasm32")]
use wasm as imp;

/// A handle to a DOM node owned by the host.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub struct Node(pub(crate) u32);

/// The `document` object, for global listeners (e.g. `keydown`).
pub const DOCUMENT: Node = Node(1);
/// `document.body`, the default mount point and the portal target.
pub const BODY: Node = Node(2);
/// The `window` object (`hashchange`, `resize`, …).
pub const WINDOW: Node = Node(3);

/// A handle to the event currently being dispatched.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct EventRef(pub(crate) u32);

pub(crate) const SVG_NS: &str = "http://www.w3.org/2000/svg";

pub(crate) fn create_element(tag: &str) -> Node {
    imp::create_element(tag)
}
pub(crate) fn create_element_ns(ns: &str, tag: &str) -> Node {
    imp::create_element_ns(ns, tag)
}
pub(crate) fn create_text(text: &str) -> Node {
    imp::create_text(text)
}
pub(crate) fn create_comment(text: &str) -> Node {
    imp::create_comment(text)
}
pub(crate) fn set_attr(node: Node, name: &str, value: &str) {
    imp::set_attr(node, name, value)
}
pub(crate) fn remove_attr(node: Node, name: &str) {
    imp::remove_attr(node, name)
}
pub(crate) fn set_prop_str(node: Node, name: &str, value: &str) {
    imp::set_prop_str(node, name, value)
}
pub(crate) fn set_prop_bool(node: Node, name: &str, value: bool) {
    imp::set_prop_bool(node, name, value)
}
pub(crate) fn get_prop_str(node: Node, name: &str) -> String {
    imp::get_prop_str(node, name)
}
pub(crate) fn insert_before(parent: Node, child: Node, before: Option<Node>) {
    imp::insert_before(parent, child, before)
}
/// Detach `node` and release the handles of its subtree.
pub(crate) fn remove(node: Node) {
    imp::remove(node)
}
/// Remove every node strictly between two sibling markers.
pub(crate) fn clear_between(start: Node, end: Node) {
    imp::clear_between(start, end)
}
/// Move the sibling range `start..=end` so it sits right before `before`.
pub(crate) fn move_range(start: Node, end: Node, before: Node) {
    imp::move_range(start, end, before)
}
pub(crate) fn parent(node: Node) -> Option<Node> {
    imp::parent(node)
}
pub(crate) fn next_sibling(node: Node) -> Option<Node> {
    imp::next_sibling(node)
}
pub(crate) fn listen(node: Node, event: &str, callback: u32) {
    imp::listen(node, event, callback)
}
pub(crate) fn get_by_id(id: &str) -> Option<Node> {
    imp::get_by_id(id)
}
pub(crate) fn focus(node: Node) {
    imp::focus(node)
}
/// Focus the first focusable descendant; `false` if there is none.
pub(crate) fn focus_first(node: Node) -> bool {
    imp::focus_first(node)
}
pub(crate) fn active_element() -> Option<Node> {
    imp::active_element()
}
pub(crate) fn contains(ancestor: Node, node: Node) -> bool {
    imp::contains(ancestor, node)
}
pub(crate) fn event_value(ev: EventRef) -> String {
    imp::event_value(ev)
}
pub(crate) fn event_checked(ev: EventRef) -> bool {
    imp::event_checked(ev)
}
pub(crate) fn event_key(ev: EventRef) -> String {
    imp::event_key(ev)
}
pub(crate) fn event_target(ev: EventRef) -> Option<Node> {
    imp::event_target(ev)
}
pub(crate) fn event_shift(ev: EventRef) -> bool {
    imp::event_shift(ev)
}
pub(crate) fn prevent_default(ev: EventRef) {
    imp::prevent_default(ev)
}
pub(crate) fn stop_propagation(ev: EventRef) {
    imp::stop_propagation(ev)
}
/// Open a Server-Sent Events stream listening for the comma-separated named
/// events in `names` (unnamed `message` events always arrive). The host calls
/// `callback` with status 1 and `"<event name>\n<data>"` per message, and
/// status 0 with a reason when the stream errors (the browser reconnects by
/// itself). Returns the stream id.
pub(crate) fn event_source(url: &str, names: &str, callback: u32) -> u32 {
    imp::event_source(url, names, callback)
}
/// Close a stream opened by [`event_source`].
pub(crate) fn event_source_close(id: u32) {
    imp::event_source_close(id)
}
pub(crate) fn fetch(method: &str, url: &str, body: Option<&str>, callback: u32) {
    imp::fetch(method, url, body, callback)
}
/// Start recording from the microphone (asks for permission the first time).
pub(crate) fn record_start() -> bool {
    imp::record_start()
}
/// Stop recording; `callback` gets status 1 and `"<mime>\n<base64>"`, or
/// status 0 and the reason.
pub(crate) fn record_stop(callback: u32) {
    imp::record_stop(callback)
}
/// Play a URL or data: URL through the page's audio output.
pub(crate) fn play_audio(src: &str) {
    imp::play_audio(src)
}
pub(crate) fn stream_audio(src: &str, volume: f64) {
    imp::stream_audio(src, volume)
}
pub(crate) fn open_url(url: &str) {
    imp::open_url(url)
}
pub(crate) fn stream_video(src: &str, volume: f64) {
    imp::stream_video(src, volume)
}
pub(crate) fn set_timeout(ms: u32, callback: u32) {
    imp::set_timeout(ms, callback)
}
pub(crate) fn location_hash() -> String {
    imp::location_hash()
}
pub(crate) fn set_location_hash(hash: &str) {
    imp::set_location_hash(hash)
}
pub(crate) fn now_ms() -> f64 {
    imp::now_ms()
}
pub(crate) fn tz_offset_minutes() -> i32 {
    imp::tz_offset_minutes()
}
pub(crate) fn storage_get(key: &str) -> Option<String> {
    imp::storage_get(key)
}
pub(crate) fn storage_set(key: &str, value: &str) {
    imp::storage_set(key, value)
}
pub(crate) fn set_title(title: &str) {
    imp::set_title(title)
}
pub(crate) fn set_root_attr(name: &str, value: &str) {
    imp::set_root_attr(name, value)
}
pub(crate) fn log(message: &str) {
    imp::log(message)
}