Переглянути джерело

feat(api): allow mananing windows created on JS (#2154)

Lucas Fernandes Nogueira 4 роки тому
батько
коміт
d69b1cf6d7

+ 5 - 0
.changes/webview-window-extends-window-manager.md

@@ -0,0 +1,5 @@
+---
+"api": patch
+---
+
+Allow manipulating a spawned window directly using `WebviewWindow`, which now extends `WindowManager`.

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
core/tauri/scripts/bundle.js


+ 106 - 85
core/tauri/src/endpoints/window.rs

@@ -11,7 +11,7 @@ use crate::{
     window::dpi::{Position, Size},
     UserAttentionType,
   },
-  Params, Window,
+  Manager, Params, Window,
 };
 use serde::Deserialize;
 
@@ -34,13 +34,10 @@ impl From<IconDto> for Icon {
   }
 }
 
-/// The API descriptor.
+/// Window management API descriptor.
 #[derive(Deserialize)]
-#[serde(tag = "cmd", content = "data", rename_all = "camelCase")]
-pub enum Cmd {
-  CreateWebview {
-    options: WindowConfig,
-  },
+#[serde(tag = "type", content = "payload", rename_all = "camelCase")]
+pub enum WindowManagerCmd {
   // Getters
   ScaleFactor,
   InnerPosition,
@@ -85,6 +82,19 @@ pub enum Cmd {
   Print,
 }
 
+/// The API descriptor.
+#[derive(Deserialize)]
+#[serde(tag = "cmd", content = "data", rename_all = "camelCase")]
+pub enum Cmd {
+  CreateWebview {
+    options: WindowConfig,
+  },
+  Manage {
+    label: Option<String>,
+    cmd: WindowManagerCmd,
+  },
+}
+
 #[cfg(window_create)]
 #[derive(Clone, serde::Serialize)]
 struct WindowCreatedEvent {
@@ -94,88 +104,99 @@ struct WindowCreatedEvent {
 impl Cmd {
   #[allow(dead_code)]
   pub async fn run<P: Params>(self, window: Window<P>) -> crate::Result<InvokeResponse> {
-    if cfg!(not(window_all)) {
-      Err(crate::Error::ApiNotAllowlisted("window > all".to_string()))
-    } else {
-      match self {
-        #[cfg(not(window_create))]
-        Self::CreateWebview { .. } => {
-          return Err(crate::Error::ApiNotAllowlisted(
-            "window > create".to_string(),
-          ));
-        }
-        #[cfg(window_create)]
-        Self::CreateWebview { options } => {
-          let mut window = window;
-          // Panic if the user's `Tag` type decided to return an error while parsing.
-          let label: P::Label = options.label.parse().unwrap_or_else(|_| {
-            panic!(
-              "Window module received unknown window label: {}",
-              options.label
-            )
-          });
+    match self {
+      #[cfg(not(window_create))]
+      Self::CreateWebview { .. } => {
+        return Err(crate::Error::ApiNotAllowlisted(
+          "window > create".to_string(),
+        ));
+      }
+      #[cfg(window_create)]
+      Self::CreateWebview { options } => {
+        let mut window = window;
+        // Panic if the user's `Tag` type decided to return an error while parsing.
+        let label: P::Label = options.label.parse().unwrap_or_else(|_| {
+          panic!(
+            "Window module received unknown window label: {}",
+            options.label
+          )
+        });
 
-          let url = options.url.clone();
+        let url = options.url.clone();
+        window
+          .create_window(label.clone(), url, |_, webview_attributes| {
+            (
+              <<<P::Runtime as Runtime>::Dispatcher as Dispatch>::WindowBuilder>::with_config(
+                options,
+              ),
+              webview_attributes,
+            )
+          })?
+          .emit_others(
+            &crate::manager::tauri_event::<P::Event>("tauri://window-created"),
+            Some(WindowCreatedEvent {
+              label: label.to_string(),
+            }),
+          )?;
+      }
+      Self::Manage { label, cmd } => {
+        let window = if let Some(l) = label {
+          window
+            .get_window(&l.parse().unwrap_or_else(|_| panic!("invalid label")))
+            .ok_or(crate::Error::WebviewNotFound)?
+        } else {
           window
-            .create_window(label.clone(), url, |_, webview_attributes| {
-              (
-                <<<P::Runtime as Runtime>::Dispatcher as Dispatch>::WindowBuilder>::with_config(
-                  options,
-                ),
-                webview_attributes,
-              )
-            })?
-            .emit_others(
-              &crate::manager::tauri_event::<P::Event>("tauri://window-created"),
-              Some(WindowCreatedEvent {
-                label: label.to_string(),
-              }),
-            )?;
+        };
+        match cmd {
+          // Getters
+          WindowManagerCmd::ScaleFactor => return Ok(window.scale_factor()?.into()),
+          WindowManagerCmd::InnerPosition => return Ok(window.inner_position()?.into()),
+          WindowManagerCmd::OuterPosition => return Ok(window.outer_position()?.into()),
+          WindowManagerCmd::InnerSize => return Ok(window.inner_size()?.into()),
+          WindowManagerCmd::OuterSize => return Ok(window.outer_size()?.into()),
+          WindowManagerCmd::IsFullscreen => return Ok(window.is_fullscreen()?.into()),
+          WindowManagerCmd::IsMaximized => return Ok(window.is_maximized()?.into()),
+          WindowManagerCmd::IsDecorated => return Ok(window.is_decorated()?.into()),
+          WindowManagerCmd::IsResizable => return Ok(window.is_resizable()?.into()),
+          WindowManagerCmd::IsVisible => return Ok(window.is_visible()?.into()),
+          WindowManagerCmd::CurrentMonitor => return Ok(window.current_monitor()?.into()),
+          WindowManagerCmd::PrimaryMonitor => return Ok(window.primary_monitor()?.into()),
+          WindowManagerCmd::AvailableMonitors => return Ok(window.available_monitors()?.into()),
+          // Setters
+          WindowManagerCmd::Center => window.center()?,
+          WindowManagerCmd::RequestUserAttention(request_type) => {
+            window.request_user_attention(request_type)?
+          }
+          WindowManagerCmd::SetResizable(resizable) => window.set_resizable(resizable)?,
+          WindowManagerCmd::SetTitle(title) => window.set_title(&title)?,
+          WindowManagerCmd::Maximize => window.maximize()?,
+          WindowManagerCmd::Unmaximize => window.unmaximize()?,
+          WindowManagerCmd::ToggleMaximize => match window.is_maximized()? {
+            true => window.unmaximize()?,
+            false => window.maximize()?,
+          },
+          WindowManagerCmd::Minimize => window.minimize()?,
+          WindowManagerCmd::Unminimize => window.unminimize()?,
+          WindowManagerCmd::Show => window.show()?,
+          WindowManagerCmd::Hide => window.hide()?,
+          WindowManagerCmd::Close => window.close()?,
+          WindowManagerCmd::SetDecorations(decorations) => window.set_decorations(decorations)?,
+          WindowManagerCmd::SetAlwaysOnTop(always_on_top) => {
+            window.set_always_on_top(always_on_top)?
+          }
+          WindowManagerCmd::SetSize(size) => window.set_size(size)?,
+          WindowManagerCmd::SetMinSize(size) => window.set_min_size(size)?,
+          WindowManagerCmd::SetMaxSize(size) => window.set_max_size(size)?,
+          WindowManagerCmd::SetPosition(position) => window.set_position(position)?,
+          WindowManagerCmd::SetFullscreen(fullscreen) => window.set_fullscreen(fullscreen)?,
+          WindowManagerCmd::SetFocus => window.set_focus()?,
+          WindowManagerCmd::SetIcon { icon } => window.set_icon(icon.into())?,
+          WindowManagerCmd::SetSkipTaskbar(skip) => window.set_skip_taskbar(skip)?,
+          WindowManagerCmd::StartDragging => window.start_dragging()?,
+          WindowManagerCmd::Print => window.print()?,
         }
-        // Getters
-        Self::ScaleFactor => return Ok(window.scale_factor()?.into()),
-        Self::InnerPosition => return Ok(window.inner_position()?.into()),
-        Self::OuterPosition => return Ok(window.outer_position()?.into()),
-        Self::InnerSize => return Ok(window.inner_size()?.into()),
-        Self::OuterSize => return Ok(window.outer_size()?.into()),
-        Self::IsFullscreen => return Ok(window.is_fullscreen()?.into()),
-        Self::IsMaximized => return Ok(window.is_maximized()?.into()),
-        Self::IsDecorated => return Ok(window.is_decorated()?.into()),
-        Self::IsResizable => return Ok(window.is_resizable()?.into()),
-        Self::IsVisible => return Ok(window.is_visible()?.into()),
-        Self::CurrentMonitor => return Ok(window.current_monitor()?.into()),
-        Self::PrimaryMonitor => return Ok(window.primary_monitor()?.into()),
-        Self::AvailableMonitors => return Ok(window.available_monitors()?.into()),
-        // Setters
-        Self::Center => window.center()?,
-        Self::RequestUserAttention(request_type) => window.request_user_attention(request_type)?,
-        Self::SetResizable(resizable) => window.set_resizable(resizable)?,
-        Self::SetTitle(title) => window.set_title(&title)?,
-        Self::Maximize => window.maximize()?,
-        Self::Unmaximize => window.unmaximize()?,
-        Self::ToggleMaximize => match window.is_maximized()? {
-          true => window.unmaximize()?,
-          false => window.maximize()?,
-        },
-        Self::Minimize => window.minimize()?,
-        Self::Unminimize => window.unminimize()?,
-        Self::Show => window.show()?,
-        Self::Hide => window.hide()?,
-        Self::Close => window.close()?,
-        Self::SetDecorations(decorations) => window.set_decorations(decorations)?,
-        Self::SetAlwaysOnTop(always_on_top) => window.set_always_on_top(always_on_top)?,
-        Self::SetSize(size) => window.set_size(size)?,
-        Self::SetMinSize(size) => window.set_min_size(size)?,
-        Self::SetMaxSize(size) => window.set_max_size(size)?,
-        Self::SetPosition(position) => window.set_position(position)?,
-        Self::SetFullscreen(fullscreen) => window.set_fullscreen(fullscreen)?,
-        Self::SetFocus => window.set_focus()?,
-        Self::SetIcon { icon } => window.set_icon(icon.into())?,
-        Self::SetSkipTaskbar(skip) => window.set_skip_taskbar(skip)?,
-        Self::StartDragging => window.start_dragging()?,
-        Self::Print => window.print()?,
       }
-      Ok(().into())
     }
+    Ok(().into())
   }
 }

+ 3 - 3
core/tauri/src/manager.rs

@@ -336,9 +336,9 @@ impl<P: Params> WindowManager<P> {
       .initialization_script(&self.initialization_script(&plugin_init, is_init_global))
       .initialization_script(&format!(
         r#"
-              window.__TAURI__.__windows = {window_labels_array}.map(function (label) {{ return {{ label: label }} }});
-              window.__TAURI__.__currentWindow = {{ label: {current_window_label} }}
-            "#,
+          window.__TAURI__.__windows = {window_labels_array}.map(function (label) {{ return {{ label: label }} }});
+          window.__TAURI__.__currentWindow = {{ label: {current_window_label} }}
+        "#,
         window_labels_array = tags_to_javascript_array(pending_labels)?,
         current_window_label = label.to_js_string()?,
       ));

Різницю між файлами не показано, бо вона завелика
+ 0 - 678
examples/api/public/build/bundle.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
examples/api/public/build/bundle.js.map


+ 32 - 42
examples/api/src/components/Window.svelte

@@ -1,30 +1,13 @@
 <script>
-  import { appWindow, WebviewWindow, LogicalSize, LogicalPosition, UserAttentionType } from "@tauri-apps/api/window";
+  import { appWindow, WebviewWindow, LogicalSize, LogicalPosition, UserAttentionType, getCurrent } from "@tauri-apps/api/window";
   import { open as openDialog } from "@tauri-apps/api/dialog";
   import { open } from "@tauri-apps/api/shell";
 
-  const {
-    setResizable,
-    setTitle,
-    maximize,
-    unmaximize,
-    minimize,
-    unminimize,
-    show,
-    hide,
-    setDecorations,
-    setAlwaysOnTop,
-    setSize,
-    setMinSize,
-    setMaxSize,
-    setPosition,
-    setFullscreen,
-    setIcon,
-    center,
-    requestUserAttention,
-  } = appWindow;
-  window.app = appWindow;
   window.UserAttentionType = UserAttentionType;
+  let selectedWindow = getCurrent().label;
+  const windowMap = {
+    [selectedWindow]: appWindow
+  }
 
   export let onMessage;
 
@@ -51,52 +34,59 @@
   }
 
   function setTitle_() {
-    setTitle(windowTitle);
+    windowMap[selectedWindow].setTitle(windowTitle);
   }
 
   function hide_() {
-    hide();
-    setTimeout(show, 2000);
+    windowMap[selectedWindow].hide();
+    setTimeout(windowMap[selectedWindow].show, 2000);
   }
 
   function minimize_() {
-    minimize();
-    setTimeout(unminimize, 2000);
+    windowMap[selectedWindow].minimize();
+    setTimeout(windowMap[selectedWindow].unminimize, 2000);
   }
 
   function getIcon() {
     openDialog({
       multiple: false,
-    }).then(setIcon);
+    }).then(windowMap[selectedWindow].setIcon);
   }
 
   function createWindow() {
-    const webview = new WebviewWindow(Math.random().toString());
+    const label = Math.random().toString();
+    const webview = new WebviewWindow(label);
+    windowMap[label] = webview;
     webview.once('tauri://error', function () {
       onMessage("Error creating new webview")
     })
   }
 
   async function requestUserAttention_() {
-    await minimize();
-    await requestUserAttention(UserAttentionType.Critical);
+    await windowMap[selectedWindow].minimize();
+    await windowMap[selectedWindow].requestUserAttention(UserAttentionType.Critical);
     await new Promise(resolve => setTimeout(resolve, 3000));
-    await requestUserAttention(null);
+    await windowMap[selectedWindow].requestUserAttention(null);
   }
 
-  $: setResizable(resizable);
-  $: maximized ? maximize() : unmaximize();
-  $: setDecorations(decorations);
-  $: setAlwaysOnTop(alwaysOnTop);
-  $: setFullscreen(fullscreen);
+  $: windowMap[selectedWindow].setResizable(resizable);
+  $: maximized ? windowMap[selectedWindow].maximize() : windowMap[selectedWindow].unmaximize();
+  $: windowMap[selectedWindow].setDecorations(decorations);
+  $: windowMap[selectedWindow].setAlwaysOnTop(alwaysOnTop);
+  $: windowMap[selectedWindow].setFullscreen(fullscreen);
 
-  $: setSize(new LogicalSize(width, height));
-  $: minWidth && minHeight ? setMinSize(new LogicalSize(minWidth, minHeight)) : setMinSize(null);
-  $: maxWidth && maxHeight ? setMaxSize(new LogicalSize(maxWidth, maxHeight)) : setMaxSize(null);
-  $: setPosition(new LogicalPosition(x, y));
+  $: windowMap[selectedWindow].setSize(new LogicalSize(width, height));
+  $: minWidth && minHeight ? windowMap[selectedWindow].setMinSize(new LogicalSize(minWidth, minHeight)) : windowMap[selectedWindow].setMinSize(null);
+  $: maxWidth && maxHeight ? windowMap[selectedWindow].setMaxSize(new LogicalSize(maxWidth, maxHeight)) : windowMap[selectedWindow].setMaxSize(null);
+  $: windowMap[selectedWindow].setPosition(new LogicalPosition(x, y));
 </script>
 
 <div class="flex col">
+  <select class="button" bind:value={selectedWindow}>
+      {#each Object.keys(windowMap) as label}
+        <option value={label}>{label}</option>
+      {/each}
+  </select>
   <div>
     <label>
       <input type="checkbox" bind:checked={resizable} />
@@ -106,7 +96,7 @@
       <input type="checkbox" bind:checked={maximized} />
       Maximize
     </label>
-    <button title="Unminimizes after 2 seconds" on:click={center}>
+    <button title="Unminimizes after 2 seconds" on:click={() => windowMap[selectedWindow].center()}>
       Center
     </button>
     <button title="Unminimizes after 2 seconds" on:click={minimize_}>

+ 339 - 136
tooling/api/src/window.ts

@@ -190,21 +190,27 @@ enum UserAttentionType {
 }
 
 /**
- * Get a handle to the current webview window. Allows emitting and listening to events from the backend that are tied to the window.
+ * Get an instance of `WebviewWindow` for the current webview window.
  *
- * @return The current window handle.
+ * @return The current WebviewWindow.
  */
-function getCurrent(): WebviewWindowHandle {
-  return new WebviewWindowHandle(window.__TAURI__.__currentWindow.label)
+function getCurrent(): WebviewWindow {
+  // @ts-expect-error
+  return new WebviewWindow(window.__TAURI__.__currentWindow.label, {
+    skip: true
+  })
 }
 
 /**
- * Gets metadata for all available webview windows.
+ * Gets an instance of `WebviewWindow` for all available webview windows.
  *
- * @return The list of webview handles.
+ * @return The list of WebviewWindow.
  */
-function getAll(): WindowDef[] {
-  return window.__TAURI__.__windows
+function getAll(): WebviewWindow[] {
+  // @ts-expect-error
+  return window.__TAURI__.__windows.map(
+    (w) => new WebviewWindow(w, { skip: true })
+  )
 }
 
 /** @ignore */
@@ -297,66 +303,6 @@ class WebviewWindowHandle {
   }
 }
 
-/**
- * Create new webview windows and get a handle to existing ones.
- * @example
- * ```typescript
- * // loading embedded asset:
- * const webview = new WebviewWindow('theUniqueLabel', {
- *   url: 'path/to/page.html'
- * })
- * // alternatively, load a remote URL:
- * const webview = new WebviewWindow('theUniqueLabel', {
- *   url: 'https://github.com/tauri-apps/tauri'
- * })
- *
- * webview.once('tauri://created', function () {
- *  // webview window successfully created
- * })
- * webview.once('tauri://error', function (e) {
- *  // an error happened creating the webview window
- * })
- *
- * // emit an event to the backend
- * await webview.emit("some event", "data")
- * // listen to an event from the backend
- * const unlisten = await webview.listen("event name", e => {})
- * unlisten()
- * ```
- */
-class WebviewWindow extends WebviewWindowHandle {
-  constructor(label: string, options: WindowOptions = {}) {
-    super(label)
-    invokeTauriCommand({
-      __tauriModule: 'Window',
-      message: {
-        cmd: 'createWebview',
-        data: {
-          options: {
-            label,
-            ...options
-          }
-        }
-      }
-    })
-      .then(async () => this.emit('tauri://created'))
-      .catch(async (e) => this.emit('tauri://error', e))
-  }
-
-  /**
-   * Gets the WebviewWindow handle for the webview associated with the given label.
-   *
-   * @param label The webview window label.
-   * @returns The handle to communicate with the webview or null if the webview doesn't exist.
-   */
-  static getByLabel(label: string): WebviewWindowHandle | null {
-    if (getAll().some((w) => w.label === label)) {
-      return new WebviewWindowHandle(label)
-    }
-    return null
-  }
-}
-
 /**
  * Manage the current window object.
  */
@@ -367,7 +313,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'scaleFactor'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'scaleFactor'
+          }
+        }
       }
     })
   }
@@ -377,7 +329,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'innerPosition'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'innerPosition'
+          }
+        }
       }
     })
   }
@@ -387,7 +345,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'outerPosition'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'outerPosition'
+          }
+        }
       }
     })
   }
@@ -400,7 +364,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'innerSize'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'innerSize'
+          }
+        }
       }
     })
   }
@@ -413,7 +383,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'outerSize'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'outerSize'
+          }
+        }
       }
     })
   }
@@ -423,7 +399,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'isFullscreen'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'isFullscreen'
+          }
+        }
       }
     })
   }
@@ -433,7 +415,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'isMaximized'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'isMaximized'
+          }
+        }
       }
     })
   }
@@ -443,7 +431,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'isDecorated'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'isDecorated'
+          }
+        }
       }
     })
   }
@@ -453,7 +447,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'isResizable'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'isResizable'
+          }
+        }
       }
     })
   }
@@ -463,7 +463,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'isVisible'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'isVisible'
+          }
+        }
       }
     })
   }
@@ -480,7 +486,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'center'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'center'
+          }
+        }
       }
     })
   }
@@ -514,8 +526,14 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'requestUserAttention',
-        data: requestType_
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'requestUserAttention',
+            payload: requestType_
+          }
+        }
       }
     })
   }
@@ -530,8 +548,14 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setResizable',
-        data: resizable
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setResizable',
+            payload: resizable
+          }
+        }
       }
     })
   }
@@ -546,8 +570,14 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setTitle',
-        data: title
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setTitle',
+            payload: title
+          }
+        }
       }
     })
   }
@@ -561,7 +591,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'maximize'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'maximize'
+          }
+        }
       }
     })
   }
@@ -575,7 +611,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'unmaximize'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'unmaximize'
+          }
+        }
       }
     })
   }
@@ -589,7 +631,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'minimize'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'minimize'
+          }
+        }
       }
     })
   }
@@ -603,7 +651,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'unminimize'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'unminimize'
+          }
+        }
       }
     })
   }
@@ -617,7 +671,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'show'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'show'
+          }
+        }
       }
     })
   }
@@ -631,7 +691,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'hide'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'hide'
+          }
+        }
       }
     })
   }
@@ -645,7 +711,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'close'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'close'
+          }
+        }
       }
     })
   }
@@ -660,8 +732,14 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setDecorations',
-        data: decorations
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setDecorations',
+            payload: decorations
+          }
+        }
       }
     })
   }
@@ -676,8 +754,14 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setAlwaysOnTop',
-        data: alwaysOnTop
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setAlwaysOnTop',
+            payload: alwaysOnTop
+          }
+        }
       }
     })
   }
@@ -702,12 +786,18 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setSize',
+        cmd: 'manage',
         data: {
-          type: size.type,
-          data: {
-            width: size.width,
-            height: size.height
+          label: this.label,
+          cmd: {
+            type: 'setSize',
+            payload: {
+              type: size.type,
+              data: {
+                width: size.width,
+                height: size.height
+              }
+            }
           }
         }
       }
@@ -736,16 +826,22 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setMinSize',
-        data: size
-          ? {
-              type: size.type,
-              data: {
-                width: size.width,
-                height: size.height
-              }
-            }
-          : null
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setMinSize',
+            payload: size
+              ? {
+                  type: size.type,
+                  data: {
+                    width: size.width,
+                    height: size.height
+                  }
+                }
+              : null
+          }
+        }
       }
     })
   }
@@ -772,16 +868,22 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setMaxSize',
-        data: size
-          ? {
-              type: size.type,
-              data: {
-                width: size.width,
-                height: size.height
-              }
-            }
-          : null
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setMaxSize',
+            payload: size
+              ? {
+                  type: size.type,
+                  data: {
+                    width: size.width,
+                    height: size.height
+                  }
+                }
+              : null
+          }
+        }
       }
     })
   }
@@ -811,12 +913,18 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setPosition',
+        cmd: 'manage',
         data: {
-          type: position.type,
-          data: {
-            x: position.x,
-            y: position.y
+          label: this.label,
+          cmd: {
+            type: 'setPosition',
+            payload: {
+              type: position.type,
+              data: {
+                x: position.x,
+                y: position.y
+              }
+            }
           }
         }
       }
@@ -833,8 +941,14 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setFullscreen',
-        data: fullscreen
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setFullscreen',
+            payload: fullscreen
+          }
+        }
       }
     })
   }
@@ -848,7 +962,13 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setFocus'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setFocus'
+          }
+        }
       }
     })
   }
@@ -863,9 +983,15 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setIcon',
+        cmd: 'manage',
         data: {
-          icon
+          label: this.label,
+          cmd: {
+            type: 'setIcon',
+            payload: {
+              icon
+            }
+          }
         }
       }
     })
@@ -881,8 +1007,14 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'setSkipTaskbar',
-        data: skip
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'setSkipTaskbar',
+            payload: skip
+          }
+        }
       }
     })
   }
@@ -896,14 +1028,85 @@ class WindowManager extends WebviewWindowHandle {
     return invokeTauriCommand({
       __tauriModule: 'Window',
       message: {
-        cmd: 'startDragging'
+        cmd: 'manage',
+        data: {
+          label: this.label,
+          cmd: {
+            type: 'startDragging'
+          }
+        }
       }
     })
   }
 }
 
-/** The manager for the current window. Allows you to manipulate the window object, listen and emit events. */
-const appWindow = new WindowManager(window.__TAURI__.__currentWindow.label)
+/**
+ * Create new webview windows and get a handle to existing ones.
+ * @example
+ * ```typescript
+ * // loading embedded asset:
+ * const webview = new WebviewWindow('theUniqueLabel', {
+ *   url: 'path/to/page.html'
+ * })
+ * // alternatively, load a remote URL:
+ * const webview = new WebviewWindow('theUniqueLabel', {
+ *   url: 'https://github.com/tauri-apps/tauri'
+ * })
+ *
+ * webview.once('tauri://created', function () {
+ *  // webview window successfully created
+ * })
+ * webview.once('tauri://error', function (e) {
+ *  // an error happened creating the webview window
+ * })
+ *
+ * // emit an event to the backend
+ * await webview.emit("some event", "data")
+ * // listen to an event from the backend
+ * const unlisten = await webview.listen("event name", e => {})
+ * unlisten()
+ * ```
+ */
+class WebviewWindow extends WindowManager {
+  constructor(label: string, options: WindowOptions = {}) {
+    super(label)
+    // @ts-expect-error
+    if (!options?.skip) {
+      invokeTauriCommand({
+        __tauriModule: 'Window',
+        message: {
+          cmd: 'createWebview',
+          data: {
+            options: {
+              label,
+              ...options
+            }
+          }
+        }
+      })
+        .then(async () => this.emit('tauri://created'))
+        .catch(async (e) => this.emit('tauri://error', e))
+    }
+  }
+
+  /**
+   * Gets the WebviewWindow for the webview associated with the given label.
+   *
+   * @param label The webview window label.
+   * @returns The WebviewWindow instance to communicate with the webview or null if the webview doesn't exist.
+   */
+  static getByLabel(label: string): WebviewWindow | null {
+    if (getAll().some((w) => w.label === label)) {
+      // @ts-expect-error
+      return new WebviewWindow(label, { skip: true })
+    }
+    return null
+  }
+}
+
+/** The WebviewWindow for the current window. */
+// @ts-expect-error
+const appWindow = new WebviewWindow()
 
 /** Configuration for the window to create. */
 interface WindowOptions {

Деякі файли не було показано, через те що забагато файлів було змінено