use tauri::{
webview::{WebviewBuilder, Webview},
LogicalPosition, LogicalSize, Runtime, State, WebviewUrl,
};
use crate::{
registry::{CefWebview, Registry},
scripts,
};
fn error(error: impl std::fmt::Display) -> String {
error.to_string()
}
fn handle<R: Runtime>(registry: &Registry<R>, label: &str) -> Result<CefWebview<R>, String> {
registry
.get(label)
.ok_or_else(|| format!("cef webview `{label}` not found"))
}
#[tauri::command]
pub fn create<R: Runtime>(
caller: Webview<R>,
registry: State<'_, Registry<R>>,
label: String,
url: String,
x: f64,
y: f64,
width: f64,
height: f64,
js: Option<Vec<String>>,
css: Option<Vec<String>>,
) -> Result<(), String> {
let window = caller.window();
if let Some(existing) = window
.webviews()
.into_iter()
.find(|webview| webview.label() == label)
{
existing
.set_bounds(tauri::Rect {
position: LogicalPosition::new(x, y).into(),
size: LogicalSize::new(width, height).into(),
})
.map_err(error)?;
registry.insert(&label, existing);
return Ok(());
}
let url = url
.parse()
.map_err(|cause| format!("invalid url `{url}`: {cause}"))?;
let mut builder = WebviewBuilder::new(label.clone(), WebviewUrl::External(url))
.position(LogicalPosition::new(x, y))
.size(LogicalSize::new(width, height));
for script in registry.config().js.iter() {
builder = builder.initialization_script(script.clone());
}
for script in js.into_iter().flatten() {
builder = builder.initialization_script(script);
}
for (index, css) in registry.config().css.iter().enumerate() {
builder = builder.initialization_script(scripts::insert_style(
&format!("cwv-init-{index}"),
css,
));
}
for (index, css) in css.into_iter().flatten().enumerate() {
builder =
builder.initialization_script(scripts::insert_style(&format!("cwv-element-{index}"), &css));
}
let webview = window.add_child(builder).map_err(error)?;
registry.insert(&label, webview);
Ok(())
}
#[tauri::command]
pub fn set_rect<R: Runtime>(
_caller: Webview<R>,
registry: State<'_, Registry<R>>,
label: String,
x: f64,
y: f64,
width: f64,
height: f64,
) -> Result<(), String> {
handle(®istry, &label)?
.set_rect(x, y, width, height)
.map_err(error)
}
#[tauri::command]
pub fn set_visible<R: Runtime>(
_caller: Webview<R>,
registry: State<'_, Registry<R>>,
label: String,
visible: bool,
) -> Result<(), String> {
handle(®istry, &label)?
.set_visible(visible)
.map_err(error)
}
#[tauri::command]
pub fn destroy<R: Runtime>(
_caller: Webview<R>,
registry: State<'_, Registry<R>>,
label: String,
) -> Result<(), String> {
if let Some(webview) = registry.remove(&label) {
webview.close().map_err(error)?;
}
Ok(())
}
#[tauri::command]
pub fn eval<R: Runtime>(
_caller: Webview<R>,
registry: State<'_, Registry<R>>,
label: String,
js: String,
) -> Result<(), String> {
handle(®istry, &label)?.eval(js).map_err(error)
}
#[tauri::command]
pub fn insert_css<R: Runtime>(
_caller: Webview<R>,
registry: State<'_, Registry<R>>,
label: String,
css: String,
) -> Result<String, String> {
handle(®istry, &label)?
.insert_css(&css)
.map_err(error)
}
#[tauri::command]
pub fn remove_inserted_css<R: Runtime>(
_caller: Webview<R>,
registry: State<'_, Registry<R>>,
label: String,
key: String,
) -> Result<(), String> {
handle(®istry, &label)?
.remove_inserted_css(&key)
.map_err(error)
}
#[tauri::command]
pub fn navigate<R: Runtime>(
_caller: Webview<R>,
registry: State<'_, Registry<R>>,
label: String,
url: String,
) -> Result<(), String> {
handle(®istry, &label)?.navigate(&url)
}
#[tauri::command]
pub fn reload<R: Runtime>(
_caller: Webview<R>,
registry: State<'_, Registry<R>>,
label: String,
) -> Result<(), String> {
handle(®istry, &label)?.reload().map_err(error)
}
#[tauri::command]
pub fn open_devtools<R: Runtime>(
_caller: Webview<R>,
registry: State<'_, Registry<R>>,
label: String,
) -> Result<(), String> {
handle(®istry, &label)?.open_devtools();
Ok(())
}