use std::sync::Arc;
use tauri::{
http,
plugin::{Builder, TauriPlugin},
Manager, Runtime, UriSchemeContext,
};
pub use config::{Config, Http, Protocol, Remote, Source};
#[cfg(desktop)]
mod desktop;
mod config;
mod error;
pub use error::{Error, Result};
#[cfg(desktop)]
use desktop::WebviewBundle;
pub trait WebviewBundleExtra<R: Runtime> {
fn webview_bundle(&self) -> &WebviewBundle<R>;
fn wvb(&self) -> &WebviewBundle<R> {
self.webview_bundle()
}
}
impl<R: Runtime, T: Manager<R>> WebviewBundleExtra<R> for T {
fn webview_bundle(&self) -> &WebviewBundle<R> {
self.state::<WebviewBundle<R>>().inner()
}
}
pub fn init<R: Runtime>(config: Config<R>) -> TauriPlugin<R> {
let config = Arc::new(config);
let c = config.clone();
let mut builder = Builder::<R>::new("webview-bundle").setup(move |app, _api| {
#[cfg(desktop)]
let webview_bundle = desktop::init(app, c)?;
app.manage(webview_bundle);
Ok(())
});
for protocol_config in &config.protocols {
let scheme = protocol_config.scheme().to_string();
builder = builder.register_asynchronous_uri_scheme_protocol(
protocol_config.scheme(),
move |ctx: UriSchemeContext<R>, req, res| {
let protocol = ctx
.app_handle()
.webview_bundle()
.get_protocol(&scheme)
.unwrap_or_else(|| panic!("protocol not found: {scheme}"))
.clone();
tauri::async_runtime::spawn(async move {
match protocol.handle(req).await {
Ok(resp) => res.respond(resp),
Err(e) => {
let resp = http::Response::builder()
.status(http::StatusCode::INTERNAL_SERVER_ERROR)
.header(http::header::CONTENT_TYPE, "text/plain")
.body(
format!("webview bundle protocol error: {e}")
.as_bytes()
.to_vec(),
)
.unwrap();
res.respond(resp);
}
}
});
},
)
}
builder.build()
}