Merge pull request from JonasKruckenberg/fix/builder-chaining

fix: make builder methods chainable
This commit is contained in:
Jonas Kruckenberg 2022-11-18 18:54:51 +01:00 committed by GitHub
commit ab1836e176
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 101 additions and 75 deletions
examples/test/src
src

View file

@ -2,11 +2,9 @@ use anyhow::ensure;
use tauri_sys::dialog::{FileDialogBuilder, MessageDialogBuilder, MessageDialogKind}; use tauri_sys::dialog::{FileDialogBuilder, MessageDialogBuilder, MessageDialogKind};
pub async fn ask() -> anyhow::Result<()> { pub async fn ask() -> anyhow::Result<()> {
let mut builder = MessageDialogBuilder::new(); let works = MessageDialogBuilder::new()
builder.set_title("Tauri"); .set_title("Tauri")
builder.set_kind(MessageDialogKind::Warning); .set_kind(MessageDialogKind::Warning)
let works = builder
.ask("Does this work? \n Click Yes to mark this test as passing") .ask("Does this work? \n Click Yes to mark this test as passing")
.await?; .await?;
@ -16,11 +14,9 @@ pub async fn ask() -> anyhow::Result<()> {
} }
pub async fn confirm() -> anyhow::Result<()> { pub async fn confirm() -> anyhow::Result<()> {
let mut builder = MessageDialogBuilder::new(); let works = MessageDialogBuilder::new()
builder.set_title("Tauri"); .set_title("Tauri")
builder.set_kind(MessageDialogKind::Warning); .set_kind(MessageDialogKind::Warning)
let works = builder
.confirm("Does this work? \n Click Ok to mark this test as passing") .confirm("Does this work? \n Click Ok to mark this test as passing")
.await?; .await?;
@ -30,20 +26,20 @@ pub async fn confirm() -> anyhow::Result<()> {
} }
pub async fn message() -> anyhow::Result<()> { pub async fn message() -> anyhow::Result<()> {
let mut builder = MessageDialogBuilder::new(); MessageDialogBuilder::new()
builder.set_title("Tauri"); .set_title("Tauri")
builder.set_kind(MessageDialogKind::Warning); .set_kind(MessageDialogKind::Warning)
.message("This is a message just for you!")
builder.message("This is a message just for you!").await?; .await?;
Ok(()) Ok(())
} }
pub async fn pick_file() -> anyhow::Result<()> { pub async fn pick_file() -> anyhow::Result<()> {
let mut builder = FileDialogBuilder::new(); let file = FileDialogBuilder::new()
builder.set_title("Select a file to mark this test as passing"); .set_title("Select a file to mark this test as passing")
.pick_file()
let file = builder.pick_file().await?; .await?;
ensure!(file.is_some()); ensure!(file.is_some());
@ -51,10 +47,10 @@ pub async fn pick_file() -> anyhow::Result<()> {
} }
pub async fn pick_files() -> anyhow::Result<()> { pub async fn pick_files() -> anyhow::Result<()> {
let mut builder = FileDialogBuilder::new(); let file = FileDialogBuilder::new()
builder.set_title("Select a multiple files to mark this test as passing"); .set_title("Select a multiple files to mark this test as passing")
.pick_files()
let file = builder.pick_files().await?; .await?;
ensure!(file.is_some()); ensure!(file.is_some());
ensure!(file.unwrap().len() > 1); ensure!(file.unwrap().len() > 1);
@ -63,10 +59,10 @@ pub async fn pick_files() -> anyhow::Result<()> {
} }
pub async fn pick_folder() -> anyhow::Result<()> { pub async fn pick_folder() -> anyhow::Result<()> {
let mut builder = FileDialogBuilder::new(); let file = FileDialogBuilder::new()
builder.set_title("Select a folder to mark this test as passing"); .set_title("Select a folder to mark this test as passing")
.pick_folder()
let file = builder.pick_folder().await?; .await?;
ensure!(file.is_some()); ensure!(file.is_some());
@ -74,10 +70,10 @@ pub async fn pick_folder() -> anyhow::Result<()> {
} }
pub async fn pick_folders() -> anyhow::Result<()> { pub async fn pick_folders() -> anyhow::Result<()> {
let mut builder = FileDialogBuilder::new(); let file = FileDialogBuilder::new()
builder.set_title("Select a multiple folders to mark this test as passing"); .set_title("Select a multiple folders to mark this test as passing")
.pick_folders()
let file = builder.pick_folders().await?; .await?;
ensure!(file.is_some()); ensure!(file.is_some());
ensure!(file.unwrap().len() > 1); ensure!(file.unwrap().len() > 1);
@ -86,10 +82,10 @@ pub async fn pick_folders() -> anyhow::Result<()> {
} }
pub async fn save() -> anyhow::Result<()> { pub async fn save() -> anyhow::Result<()> {
let mut builder = FileDialogBuilder::new(); let file = FileDialogBuilder::new()
builder.set_title("Select a file to mark this test as passing"); .set_title("Select a file to mark this test as passing")
.save()
let file = builder.save().await?; .await?;
ensure!(file.is_some()); ensure!(file.is_some());

View file

@ -49,8 +49,9 @@ impl<'a> FileDialogBuilder<'a> {
} }
/// Set starting file name or directory of the dialog. /// Set starting file name or directory of the dialog.
pub fn set_default_path(&mut self, default_path: &'a Path) { pub fn set_default_path(&mut self, default_path: &'a Path) -> &mut Self {
self.default_path = Some(default_path); self.default_path = Some(default_path);
self
} }
/// If directory is true, indicates that it will be read recursively later. /// If directory is true, indicates that it will be read recursively later.
@ -66,8 +67,9 @@ impl<'a> FileDialogBuilder<'a> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
pub fn set_recursive(&mut self, recursive: bool) { pub fn set_recursive(&mut self, recursive: bool) -> &mut Self {
self.recursive = recursive; self.recursive = recursive;
self
} }
/// Set the title of the dialog. /// Set the title of the dialog.
@ -82,8 +84,9 @@ impl<'a> FileDialogBuilder<'a> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
pub fn set_title(&mut self, title: &'a str) { pub fn set_title(&mut self, title: &'a str) -> &mut Self {
self.title = Some(title); self.title = Some(title);
self
} }
/// Add file extension filter. Takes in the name of the filter, and list of extensions /// Add file extension filter. Takes in the name of the filter, and list of extensions
@ -98,8 +101,9 @@ impl<'a> FileDialogBuilder<'a> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
pub fn add_filter(&mut self, name: &'a str, extensions: &'a [&'a str]) { pub fn add_filter(&mut self, name: &'a str, extensions: &'a [&'a str]) -> &mut Self {
self.filters.push(DialogFilter { name, extensions }); self.filters.push(DialogFilter { name, extensions });
self
} }
/// Add many file extension filters. /// Add many file extension filters.
@ -114,13 +118,14 @@ impl<'a> FileDialogBuilder<'a> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
pub fn add_filters(&mut self, filters: impl IntoIterator<Item = (&'a str, &'a [&'a str])>) { pub fn add_filters(&mut self, filters: impl IntoIterator<Item = (&'a str, &'a [&'a str])>) -> &mut Self {
for (name, extensions) in filters.into_iter() { for (name, extensions) in filters.into_iter() {
self.filters.push(DialogFilter { self.filters.push(DialogFilter {
name: name.as_ref(), name: name.as_ref(),
extensions, extensions,
}); });
} }
self
} }
/// Shows the dialog to select a single file. /// Shows the dialog to select a single file.
@ -137,7 +142,7 @@ impl<'a> FileDialogBuilder<'a> {
/// ``` /// ```
/// ///
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled. /// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
pub async fn pick_file(self) -> crate::Result<Option<PathBuf>> { pub async fn pick_file(&self) -> crate::Result<Option<PathBuf>> {
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?; let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?) Ok(serde_wasm_bindgen::from_value(raw)?)
@ -157,7 +162,7 @@ impl<'a> FileDialogBuilder<'a> {
/// ``` /// ```
/// ///
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled. /// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
pub async fn pick_files(mut self) -> crate::Result<Option<Vec<PathBuf>>> { pub async fn pick_files(&mut self) -> crate::Result<Option<Vec<PathBuf>>> {
self.multiple = true; self.multiple = true;
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?; let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
@ -179,7 +184,7 @@ impl<'a> FileDialogBuilder<'a> {
/// ``` /// ```
/// ///
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled. /// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
pub async fn pick_folder(mut self) -> crate::Result<Option<PathBuf>> { pub async fn pick_folder(&mut self) -> crate::Result<Option<PathBuf>> {
self.directory = true; self.directory = true;
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?; let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
@ -201,7 +206,7 @@ impl<'a> FileDialogBuilder<'a> {
/// ``` /// ```
/// ///
/// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled. /// Requires [`allowlist > dialog > open`](https://tauri.app/v1/api/config#dialogallowlistconfig.open) to be enabled.
pub async fn pick_folders(mut self) -> crate::Result<Option<Vec<PathBuf>>> { pub async fn pick_folders(&mut self) -> crate::Result<Option<Vec<PathBuf>>> {
self.directory = true; self.directory = true;
self.multiple = true; self.multiple = true;
@ -230,7 +235,7 @@ impl<'a> FileDialogBuilder<'a> {
/// ``` /// ```
/// ///
/// Requires [`allowlist > dialog > save`](https://tauri.app/v1/api/config#dialogallowlistconfig.save) to be enabled. /// Requires [`allowlist > dialog > save`](https://tauri.app/v1/api/config#dialogallowlistconfig.save) to be enabled.
pub async fn save(self) -> crate::Result<Option<PathBuf>> { pub async fn save(&self) -> crate::Result<Option<PathBuf>> {
let raw = inner::save(serde_wasm_bindgen::to_value(&self)?).await?; let raw = inner::save(serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?) Ok(serde_wasm_bindgen::from_value(raw)?)
@ -274,8 +279,9 @@ impl<'a> MessageDialogBuilder<'a> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
pub fn set_title(&mut self, title: &'a str) { pub fn set_title(&mut self, title: &'a str) -> &mut Self {
self.title = Some(title); self.title = Some(title);
self
} }
/// Set the type of the dialog. /// Set the type of the dialog.
@ -290,8 +296,9 @@ impl<'a> MessageDialogBuilder<'a> {
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
pub fn set_kind(&mut self, kind: MessageDialogKind) { pub fn set_kind(&mut self, kind: MessageDialogKind) -> &mut Self {
self.kind = r#kind; self.kind = kind;
self
} }
/// Shows a message dialog with an `Ok` button. /// Shows a message dialog with an `Ok` button.
@ -308,7 +315,7 @@ impl<'a> MessageDialogBuilder<'a> {
/// ``` /// ```
/// ///
/// Requires [`allowlist > dialog > message`](https://tauri.app/v1/api/config#dialogallowlistconfig.message) to be enabled. /// Requires [`allowlist > dialog > message`](https://tauri.app/v1/api/config#dialogallowlistconfig.message) to be enabled.
pub async fn message(self, message: &str) -> crate::Result<()> { pub async fn message(&self, message: &str) -> crate::Result<()> {
Ok(inner::message(message, serde_wasm_bindgen::to_value(&self)?).await?) Ok(inner::message(message, serde_wasm_bindgen::to_value(&self)?).await?)
} }
@ -326,7 +333,7 @@ impl<'a> MessageDialogBuilder<'a> {
/// ``` /// ```
/// ///
/// Requires [`allowlist > dialog > ask`](https://tauri.app/v1/api/config#dialogallowlistconfig.ask) to be enabled. /// Requires [`allowlist > dialog > ask`](https://tauri.app/v1/api/config#dialogallowlistconfig.ask) to be enabled.
pub async fn ask(self, message: &str) -> crate::Result<bool> { pub async fn ask(&self, message: &str) -> crate::Result<bool> {
let raw = inner::ask(message, serde_wasm_bindgen::to_value(&self)?).await?; let raw = inner::ask(message, serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?) Ok(serde_wasm_bindgen::from_value(raw)?)
@ -346,7 +353,7 @@ impl<'a> MessageDialogBuilder<'a> {
/// ``` /// ```
/// ///
/// Requires [`allowlist > dialog > confirm`](https://tauri.app/v1/api/config#dialogallowlistconfig.confirm) to be enabled. /// Requires [`allowlist > dialog > confirm`](https://tauri.app/v1/api/config#dialogallowlistconfig.confirm) to be enabled.
pub async fn confirm(self, message: &str) -> crate::Result<bool> { pub async fn confirm(&self, message: &str) -> crate::Result<bool> {
let raw = inner::confirm(message, serde_wasm_bindgen::to_value(&self)?).await?; let raw = inner::confirm(message, serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?) Ok(serde_wasm_bindgen::from_value(raw)?)

View file

@ -227,138 +227,161 @@ impl<'a> WebviewWindowBuilder<'a> {
/// - URL such as `https://github.com/tauri-apps` is opened directly on a Tauri window. /// - URL such as `https://github.com/tauri-apps` is opened directly on a Tauri window.
/// - data: URL such as `data:text/html,<html>...` is only supported with the `window-data-url` Cargo feature for the `tauri` dependency. /// - data: URL such as `data:text/html,<html>...` is only supported with the `window-data-url` Cargo feature for the `tauri` dependency.
/// - local file path or route such as `/path/to/page.html` or `/users` is appended to the application URL (the devServer URL on development, or `tauri://localhost/` and `https://tauri.localhost/` on production). /// - local file path or route such as `/path/to/page.html` or `/users` is appended to the application URL (the devServer URL on development, or `tauri://localhost/` and `https://tauri.localhost/` on production).
pub fn set_url(&mut self, url: &'a str) { pub fn set_url(&mut self, url: &'a str) -> &mut Self {
self.inner.url = Some(url); self.inner.url = Some(url);
self
} }
/// Show window in the center of the screen. /// Show window in the center of the screen.
pub fn set_center(&mut self, center: bool) { pub fn set_center(&mut self, center: bool) -> &mut Self {
self.inner.center = center; self.inner.center = center;
self
} }
/// The initial position. /// The initial position.
pub fn set_position(&mut self, position: PhysicalPosition) { pub fn set_position(&mut self, position: PhysicalPosition) -> &mut Self {
self.inner.x = Some(position.x()); self.inner.x = Some(position.x());
self.inner.y = Some(position.y()); self.inner.y = Some(position.y());
self
} }
/// The initial size. /// The initial size.
pub fn set_size(&mut self, size: PhysicalSize) { pub fn set_size(&mut self, size: PhysicalSize) -> &mut Self {
self.inner.width = Some(size.width()); self.inner.width = Some(size.width());
self.inner.height = Some(size.height()); self.inner.height = Some(size.height());
self
} }
/// Minimum window size. /// Minimum window size.
pub fn set_min_size(&mut self, min_size: PhysicalSize) { pub fn set_min_size(&mut self, min_size: PhysicalSize) -> &mut Self {
self.inner.min_width = Some(min_size.width()); self.inner.min_width = Some(min_size.width());
self.inner.min_height = Some(min_size.height()); self.inner.min_height = Some(min_size.height());
self
} }
/// Maximum window size. /// Maximum window size.
pub fn set_max_size(&mut self, max_size: PhysicalSize) { pub fn set_max_size(&mut self, max_size: PhysicalSize) -> &mut Self {
self.inner.max_width = Some(max_size.width()); self.inner.max_width = Some(max_size.width());
self.inner.max_height = Some(max_size.height()); self.inner.max_height = Some(max_size.height());
self
} }
/// Whether the window is resizable or not. /// Whether the window is resizable or not.
pub fn set_resizable(&mut self, resizable: bool) { pub fn set_resizable(&mut self, resizable: bool) -> &mut Self {
self.inner.resizable = resizable; self.inner.resizable = resizable;
self
} }
/// Window title. /// Window title.
pub fn set_title(&mut self, title: &'a str) { pub fn set_title(&mut self, title: &'a str) -> &mut Self {
self.inner.title = Some(title); self.inner.title = Some(title);
self
} }
/// Whether the window is in fullscreen mode or not. /// Whether the window is in fullscreen mode or not.
pub fn set_fullscreen(&mut self, fullscreen: bool) { pub fn set_fullscreen(&mut self, fullscreen: bool) -> &mut Self {
self.inner.fullscreen = fullscreen; self.inner.fullscreen = fullscreen;
self
} }
/// Whether the window will be initially focused or not. /// Whether the window will be initially focused or not.
pub fn set_focus(&mut self, focus: bool) { pub fn set_focus(&mut self, focus: bool) -> &mut Self {
self.inner.focus = focus; self.inner.focus = focus;
self
} }
/// Whether the window is transparent or not. /// Whether the window is transparent or not.
/// ///
/// Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri.conf.json > tauri > macOSPrivateApi`. /// Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri.conf.json > tauri > macOSPrivateApi`.
/// WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`. /// WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`.
pub fn set_transparent(&mut self, transparent: bool) { pub fn set_transparent(&mut self, transparent: bool) -> &mut Self {
self.inner.transparent = transparent; self.inner.transparent = transparent;
self
} }
/// Whether the window should be maximized upon creation or not. /// Whether the window should be maximized upon creation or not.
pub fn set_maximized(&mut self, maximized: bool) { pub fn set_maximized(&mut self, maximized: bool) -> &mut Self {
self.inner.maximized = maximized; self.inner.maximized = maximized;
self
} }
/// Whether the window should be immediately visible upon creation or not. /// Whether the window should be immediately visible upon creation or not.
pub fn set_visible(&mut self, visible: bool) { pub fn set_visible(&mut self, visible: bool) -> &mut Self {
self.inner.visible = visible; self.inner.visible = visible;
self
} }
/// Whether the window should have borders and bars or not. /// Whether the window should have borders and bars or not.
pub fn set_decorations(&mut self, decorations: bool) { pub fn set_decorations(&mut self, decorations: bool) -> &mut Self {
self.inner.decorations = decorations; self.inner.decorations = decorations;
self
} }
/// Whether the window should always be on top of other windows or not. /// Whether the window should always be on top of other windows or not.
pub fn set_always_on_top(&mut self, always_on_top: bool) { pub fn set_always_on_top(&mut self, always_on_top: bool) -> &mut Self {
self.inner.always_on_top = always_on_top; self.inner.always_on_top = always_on_top;
self
} }
/// Whether or not the window icon should be added to the taskbar. /// Whether or not the window icon should be added to the taskbar.
pub fn set_skip_taskbar(&mut self, skip_taskbar: bool) { pub fn set_skip_taskbar(&mut self, skip_taskbar: bool) -> &mut Self {
self.inner.skip_taskbar = skip_taskbar; self.inner.skip_taskbar = skip_taskbar;
self
} }
/// Whether the file drop is enabled or not on the webview. By default it is enabled. /// Whether the file drop is enabled or not on the webview. By default it is enabled.
/// ///
/// Disabling it is required to use drag and drop on the frontend on Windows. /// Disabling it is required to use drag and drop on the frontend on Windows.
pub fn set_file_drop_enabled(&mut self, file_drop_enabled: bool) { pub fn set_file_drop_enabled(&mut self, file_drop_enabled: bool) -> &mut Self {
self.inner.file_drop_enabled = file_drop_enabled; self.inner.file_drop_enabled = file_drop_enabled;
self
} }
/// The initial window theme. Defaults to the system theme. /// The initial window theme. Defaults to the system theme.
/// ///
/// Only implemented on Windows and macOS 10.14+. /// Only implemented on Windows and macOS 10.14+.
pub fn set_theme(&mut self, theme: Theme) { pub fn set_theme(&mut self, theme: Theme) -> &mut Self {
self.inner.theme = Some(theme); self.inner.theme = Some(theme);
self
} }
/// The style of the macOS title bar. /// The style of the macOS title bar.
pub fn set_title_bar_style(&mut self, title_bar_style: TitleBarStyle) { pub fn set_title_bar_style(&mut self, title_bar_style: TitleBarStyle) -> &mut Self {
self.inner.title_bar_style = Some(title_bar_style); self.inner.title_bar_style = Some(title_bar_style);
self
} }
/// If `true`, sets the window title to be hidden on macOS. /// If `true`, sets the window title to be hidden on macOS.
pub fn set_hidden_title(&mut self, hidden_title: bool) { pub fn set_hidden_title(&mut self, hidden_title: bool) -> &mut Self {
self.inner.hidden_title = hidden_title; self.inner.hidden_title = hidden_title;
self
} }
/// Whether clicking an inactive window also clicks through to the webview. /// Whether clicking an inactive window also clicks through to the webview.
pub fn set_accept_first_mouse(&mut self, accept_first_mouse: bool) { pub fn set_accept_first_mouse(&mut self, accept_first_mouse: bool) -> &mut Self {
self.inner.accept_first_mouse = accept_first_mouse; self.inner.accept_first_mouse = accept_first_mouse;
self
} }
/// Defines the window [tabbing identifier](https://developer.apple.com/documentation/appkit/nswindow/1644704-tabbingidentifier) on macOS. /// Defines the window [tabbing identifier](https://developer.apple.com/documentation/appkit/nswindow/1644704-tabbingidentifier) on macOS.
/// ///
/// Windows with the same tabbing identifier will be grouped together. /// Windows with the same tabbing identifier will be grouped together.
/// If the tabbing identifier is not set, automatic tabbing will be disabled. /// If the tabbing identifier is not set, automatic tabbing will be disabled.
pub fn set_tabbing_identifier(&mut self, tabbing_identifier: &'a str) { pub fn set_tabbing_identifier(&mut self, tabbing_identifier: &'a str) -> &mut Self {
self.inner.tabbing_identifier = Some(tabbing_identifier); self.inner.tabbing_identifier = Some(tabbing_identifier);
self
} }
/// The user agent for the webview. /// The user agent for the webview.
pub fn set_user_agent(&mut self, user_agent: &'a str) { pub fn set_user_agent(&mut self, user_agent: &'a str) -> &mut Self {
self.inner.user_agent = Some(user_agent); self.inner.user_agent = Some(user_agent);
self
} }
/// Creates a new webview window. /// Creates a new webview window.
/// ///
/// Requires [`allowlist > window > create`](https://tauri.app/v1/api/config#windowallowlistconfig.create) to be enabled. /// Requires [`allowlist > window > create`](https://tauri.app/v1/api/config#windowallowlistconfig.create) to be enabled.
pub fn build(self) -> crate::Result<WebviewWindow> { pub fn build(&self) -> crate::Result<WebviewWindow> {
let opts = serde_wasm_bindgen::to_value(&self.inner)?; let opts = serde_wasm_bindgen::to_value(&self.inner)?;
Ok(WebviewWindow(inner::WebviewWindow::new(self.label, opts))) Ok(WebviewWindow(inner::WebviewWindow::new(self.label, opts)))