use std::{
collections::HashMap,
sync::{
atomic::{AtomicU64, Ordering},
Arc, Mutex,
},
};
use tauri::{
webview::Webview, LogicalPosition, LogicalSize, Rect, Runtime, Url,
};
use crate::{scripts, Config};
pub struct Registry<R: Runtime> {
webviews: Mutex<HashMap<String, Webview<R>>>,
css_sequence: Arc<AtomicU64>,
config: Config,
}
impl<R: Runtime> Registry<R> {
pub(crate) fn new(config: Config) -> Self {
Self {
webviews: Mutex::new(HashMap::new()),
css_sequence: Arc::new(AtomicU64::new(0)),
config,
}
}
pub(crate) fn config(&self) -> &Config {
&self.config
}
pub(crate) fn insert(&self, label: &str, webview: Webview<R>) {
self.webviews
.lock()
.unwrap_or_else(|error| error.into_inner())
.insert(label.to_string(), webview);
}
pub(crate) fn remove(&self, label: &str) -> Option<Webview<R>> {
self.webviews
.lock()
.unwrap_or_else(|error| error.into_inner())
.remove(label)
}
pub fn get(&self, label: &str) -> Option<CefWebview<R>> {
self.webviews
.lock()
.unwrap_or_else(|error| error.into_inner())
.get(label)
.cloned()
.map(|webview| CefWebview {
webview,
css_sequence: Arc::clone(&self.css_sequence),
})
}
pub fn labels(&self) -> Vec<String> {
self.webviews
.lock()
.unwrap_or_else(|error| error.into_inner())
.keys()
.cloned()
.collect()
}
}
#[derive(Clone)]
pub struct CefWebview<R: Runtime> {
pub(crate) webview: Webview<R>,
css_sequence: Arc<AtomicU64>,
}
impl<R: Runtime> CefWebview<R> {
pub fn label(&self) -> &str {
self.webview.label()
}
pub fn inner(&self) -> &Webview<R> {
&self.webview
}
pub fn eval(&self, js: impl Into<String>) -> tauri::Result<()> {
self.webview.eval(js)
}
pub fn insert_css(&self, css: &str) -> tauri::Result<String> {
let key = format!(
"cwv-css-{}",
self.css_sequence.fetch_add(1, Ordering::Relaxed)
);
self.webview.eval(scripts::insert_style(&key, css))?;
Ok(key)
}
pub fn remove_inserted_css(&self, key: &str) -> tauri::Result<()> {
self.webview.eval(scripts::remove_style(key))
}
pub fn navigate(&self, url: &str) -> Result<(), String> {
let url = Url::parse(url).map_err(|error| error.to_string())?;
self.webview.navigate(url).map_err(|error| error.to_string())
}
pub fn reload(&self) -> tauri::Result<()> {
self.webview.reload()
}
#[cfg(any(debug_assertions, feature = "devtools"))]
pub fn open_devtools(&self) {
self.webview.open_devtools();
}
#[cfg(not(any(debug_assertions, feature = "devtools")))]
pub fn open_devtools(&self) {}
pub fn set_rect(&self, x: f64, y: f64, width: f64, height: f64) -> tauri::Result<()> {
self.webview.set_bounds(Rect {
position: LogicalPosition::new(x, y).into(),
size: LogicalSize::new(width, height).into(),
})
}
pub fn set_visible(&self, visible: bool) -> tauri::Result<()> {
if visible {
self.webview.show()
} else {
self.webview.hide()
}
}
pub fn close(&self) -> tauri::Result<()> {
self.webview.close()
}
}