use crate::*;
#[derive(Clone, Copy, Data)]
pub struct UseBrowserApi {
#[get(pub, type(copy))]
#[set(pub)]
pub local_key: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub local_value: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub local_result: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub session_key: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub session_value: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub session_result: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub clipboard_text: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub clipboard_result: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub window_size: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub user_agent: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub language: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub location_url: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub location_origin_val: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub location_pathname_val: Signal<String>,
#[get(pub, type(copy))]
#[set(pub)]
pub console_input: Signal<String>,
}
impl Default for UseBrowserApi {
fn default() -> Self {
UseBrowserApi {
local_key: Signal::new("".to_string()),
local_value: Signal::new("".to_string()),
local_result: Signal::new("".to_string()),
session_key: Signal::new("".to_string()),
session_value: Signal::new("".to_string()),
session_result: Signal::new("".to_string()),
clipboard_text: Signal::new("".to_string()),
clipboard_result: Signal::new("".to_string()),
window_size: Signal::new("".to_string()),
user_agent: Signal::new("".to_string()),
language: Signal::new("".to_string()),
location_url: Signal::new("".to_string()),
location_origin_val: Signal::new("".to_string()),
location_pathname_val: Signal::new("".to_string()),
console_input: Signal::new("".to_string()),
}
}
}
pub fn use_browser_api() -> UseBrowserApi {
let mut state: UseBrowserApi = UseBrowserApi::default();
state.set_local_key(use_signal(|| "euv-demo-key".to_string()));
state.set_local_value(use_signal(|| "".to_string()));
state.set_local_result(use_signal(|| "No data yet".to_string()));
state.set_session_key(use_signal(|| "euv-session-key".to_string()));
state.set_session_value(use_signal(|| "".to_string()));
state.set_session_result(use_signal(|| "No data yet".to_string()));
state.set_clipboard_text(use_signal(|| "".to_string()));
state.set_clipboard_result(use_signal(|| "".to_string()));
state.set_window_size(use_signal(|| {
let (width, height): (i32, i32) = window_inner_size();
format!("{} x {}", width, height)
}));
state.set_user_agent(use_signal(navigator_user_agent));
state.set_language(use_signal(navigator_language));
state.set_location_url(use_signal(location_href));
state.set_location_origin_val(use_signal(location_origin));
state.set_location_pathname_val(use_signal(location_pathname));
state.set_console_input(use_signal(|| "".to_string()));
state
}
pub fn local_storage_get(key: &str) -> Option<String> {
let window: Window = window().expect("no global window exists");
let storage: Storage = window.local_storage().ok()??;
storage.get_item(key).ok()?
}
pub fn local_storage_set(key: &str, value: &str) {
let window: Window = window().expect("no global window exists");
let storage: Storage = match window.local_storage() {
Ok(Some(s)) => s,
_ => return,
};
let _ = storage.set_item(key, value);
}
pub fn local_storage_remove(key: &str) {
let window: Window = window().expect("no global window exists");
let storage: Storage = match window.local_storage() {
Ok(Some(s)) => s,
_ => return,
};
let _ = storage.remove_item(key);
}
pub fn session_storage_get(key: &str) -> Option<String> {
let window: Window = window().expect("no global window exists");
let storage: Storage = window.session_storage().ok()??;
storage.get_item(key).ok()?
}
pub fn session_storage_set(key: &str, value: &str) {
let window: Window = window().expect("no global window exists");
let storage: Storage = match window.session_storage() {
Ok(Some(s)) => s,
_ => return,
};
let _ = storage.set_item(key, value);
}
pub fn session_storage_remove(key: &str) {
let window: Window = window().expect("no global window exists");
let storage: Storage = match window.session_storage() {
Ok(Some(s)) => s,
_ => return,
};
let _ = storage.remove_item(key);
}
pub async fn clipboard_read_text() -> String {
let window: Window = window().expect("no global window exists");
let navigator: Navigator = window.navigator();
let clipboard: Clipboard = navigator.clipboard();
let promise: js_sys::Promise = clipboard.read_text();
let future: wasm_bindgen_futures::JsFuture = wasm_bindgen_futures::JsFuture::from(promise);
match future.await {
Ok(value) => value
.as_string()
.unwrap_or_else(|| "No text content".to_string()),
Err(_) => "Failed to read clipboard".to_string(),
}
}
pub async fn clipboard_write_text(text: &str) -> bool {
let window: Window = window().expect("no global window exists");
let navigator: Navigator = window.navigator();
let clipboard: Clipboard = navigator.clipboard();
let promise: js_sys::Promise = clipboard.write_text(text);
let future: wasm_bindgen_futures::JsFuture = wasm_bindgen_futures::JsFuture::from(promise);
future.await.is_ok()
}
pub fn window_inner_size() -> (i32, i32) {
let window: Window = window().expect("no global window exists");
let width: i32 = window
.inner_width()
.ok()
.and_then(|v| v.as_f64())
.map(|v| v as i32)
.unwrap_or(0);
let height: i32 = window
.inner_height()
.ok()
.and_then(|v| v.as_f64())
.map(|v| v as i32)
.unwrap_or(0);
(width, height)
}
pub fn navigator_user_agent() -> String {
let window: Window = window().expect("no global window exists");
window
.navigator()
.user_agent()
.unwrap_or_else(|_| "Unknown".to_string())
}
pub fn navigator_language() -> String {
let window: Window = window().expect("no global window exists");
window
.navigator()
.language()
.unwrap_or_else(|| "Unknown".to_string())
}
pub fn location_href() -> String {
let window: Window = window().expect("no global window exists");
window
.location()
.href()
.unwrap_or_else(|_| "Unknown".to_string())
}
pub fn location_origin() -> String {
let window: Window = window().expect("no global window exists");
window
.location()
.origin()
.unwrap_or_else(|_| "Unknown".to_string())
}
pub fn location_pathname() -> String {
let window: Window = window().expect("no global window exists");
window
.location()
.pathname()
.unwrap_or_else(|_| "Unknown".to_string())
}
pub fn local_storage_on_set(state: UseBrowserApi) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let key: String = state.local_key.get();
let value: String = state.local_value.get();
if !key.is_empty() {
local_storage_set(&key, &value);
state.local_result.set(format!("Set: {} = {}", key, value));
}
})
}
pub fn local_storage_on_get(state: UseBrowserApi) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let key: String = state.local_key.get();
let value: Option<String> = local_storage_get(&key);
match value {
Some(v) => state.local_result.set(format!("Get: {} = {}", key, v)),
None => state.local_result.set(format!("Key '{}' not found", key)),
}
})
}
pub fn local_storage_on_remove(state: UseBrowserApi) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let key: String = state.local_key.get();
local_storage_remove(&key);
state.local_result.set(format!("Removed key: {}", key));
})
}
pub fn session_storage_on_set(state: UseBrowserApi) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let key: String = state.session_key.get();
let value: String = state.session_value.get();
if !key.is_empty() {
session_storage_set(&key, &value);
state
.session_result
.set(format!("Set: {} = {}", key, value));
}
})
}
pub fn session_storage_on_get(state: UseBrowserApi) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let key: String = state.session_key.get();
let value: Option<String> = session_storage_get(&key);
match value {
Some(v) => state.session_result.set(format!("Get: {} = {}", key, v)),
None => state.session_result.set(format!("Key '{}' not found", key)),
}
})
}
pub fn session_storage_on_remove(state: UseBrowserApi) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let key: String = state.session_key.get();
session_storage_remove(&key);
state.session_result.set(format!("Removed key: {}", key));
})
}
pub fn clipboard_on_copy(state: UseBrowserApi) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let text: String = state.clipboard_text.get();
let text_clone: String = text.clone();
let result: Signal<String> = state.clipboard_result;
if text.is_empty() {
result.set("Please enter text to copy".to_string());
} else {
wasm_bindgen_futures::spawn_local(async move {
let success: bool = clipboard_write_text(&text_clone).await;
if success {
result.set("Copied to clipboard!".to_string());
} else {
result.set("Failed to copy".to_string());
}
});
}
})
}
pub fn clipboard_on_paste(state: UseBrowserApi) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let result: Signal<String> = state.clipboard_result;
wasm_bindgen_futures::spawn_local(async move {
let text: String = clipboard_read_text().await;
result.set(format!("Pasted: {}", text));
});
})
}
pub fn window_on_refresh_size(state: UseBrowserApi) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let (width, height): (i32, i32) = window_inner_size();
state.window_size.set(format!("{} x {}", width, height));
})
}
pub fn console_on_log(console_input: Signal<String>) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let message: String = console_input.get();
Console::log(&message);
})
}
pub fn console_on_warn(console_input: Signal<String>) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let message: String = console_input.get();
Console::warn(&message);
})
}
pub fn console_on_error(console_input: Signal<String>) -> NativeEventHandler {
NativeEventHandler::new(NativeEventName::Click, move |_event: NativeEvent| {
let message: String = console_input.get();
Console::error(&message);
})
}