diff --git a/.changes/api-dpi-toIPC.md b/.changes/api-dpi-toIPC.md new file mode 100644 index 000000000000..c0258131e598 --- /dev/null +++ b/.changes/api-dpi-toIPC.md @@ -0,0 +1,10 @@ +--- +"@tauri-apps/api": "minor:feat" +"tauri": "minor:feat" +--- + +Improved support for `dpi` module types to allow these types to be used without manual conversions with `invoke`: + +- Added `SERIALIZE_TO_IPC_FN` const in `core` module which can be used to implement custom IPC serialization for types passed to `invoke`. +- Added `Size` and `Position` classes in `dpi` module. +- Implementd `SERIALIZE_TO_IPC_FN` method on `PhysicalSize`, `PhysicalPosition`, `LogicalSize` and `LogicalPosition` to convert it into a valid IPC-compatible value that can be deserialized correctly on the Rust side into its equivalent struct. diff --git a/.changes/tauri-toIPC copy.md b/.changes/tauri-toIPC copy.md new file mode 100644 index 000000000000..e4957e3ecf08 --- /dev/null +++ b/.changes/tauri-toIPC copy.md @@ -0,0 +1,5 @@ +--- +"tauri": "minor:feat" +--- + +Detect if `SERIALIZE_TO_IPC_FN`, const from the JS `core` module, is implemented on objects when serializing over IPC and use it. diff --git a/crates/tauri/scripts/bundle.global.js b/crates/tauri/scripts/bundle.global.js index 54f47c5c904b..316e09b65f99 100644 --- a/crates/tauri/scripts/bundle.global.js +++ b/crates/tauri/scripts/bundle.global.js @@ -1 +1 @@ -var __TAURI_IIFE__=function(e){"use strict";function n(e,n,t,i){if("a"===t&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof n?e!==n||!i:!n.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?i:"a"===t?i.call(e):i?i.value:n.get(e)}function t(e,n,t,i,r){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof n?e!==n||!r:!n.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?r.call(e,t):r?r.value=t:n.set(e,t),t}var i,r,a,s;function l(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}"function"==typeof SuppressedError&&SuppressedError;class o{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),r.set(this,0),a.set(this,{}),this.id=l((({message:e,id:s})=>{if(s===n(this,r,"f")){t(this,r,s+1,"f"),n(this,i,"f").call(this,e);const l=Object.keys(n(this,a,"f"));if(l.length>0){let e=s+1;for(const t of l.sort()){if(parseInt(t)!==e)break;{const r=n(this,a,"f")[t];delete n(this,a,"f")[t],n(this,i,"f").call(this,r),e+=1}}t(this,r,e,"f")}}else n(this,a,"f")[s.toString()]=e}))}set onmessage(e){t(this,i,e,"f")}get onmessage(){return n(this,i,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}i=new WeakMap,r=new WeakMap,a=new WeakMap;class u{constructor(e,n,t){this.plugin=e,this.event=n,this.channelId=t}async unregister(){return c(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function c(e,n={},t){return window.__TAURI_INTERNALS__.invoke(e,n,t)}class d{get rid(){return n(this,s,"f")}constructor(e){s.set(this,void 0),t(this,s,e,"f")}async close(){return c("plugin:resources|close",{rid:this.rid})}}s=new WeakMap;var p=Object.freeze({__proto__:null,Channel:o,PluginListener:u,Resource:d,addPluginListener:async function(e,n,t){const i=new o;return i.onmessage=t,c(`plugin:${e}|registerListener`,{event:n,handler:i}).then((()=>new u(e,n,i.id)))},checkPermissions:async function(e){return c(`plugin:${e}|check_permissions`)},convertFileSrc:function(e,n="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,n)},invoke:c,isTauri:function(){return"isTauri"in window&&!!window.isTauri},requestPermissions:async function(e){return c(`plugin:${e}|request_permissions`)},transformCallback:l});class h extends d{constructor(e){super(e)}static async new(e,n,t){return c("plugin:image|new",{rgba:w(e),width:n,height:t}).then((e=>new h(e)))}static async fromBytes(e){return c("plugin:image|from_bytes",{bytes:w(e)}).then((e=>new h(e)))}static async fromPath(e){return c("plugin:image|from_path",{path:e}).then((e=>new h(e)))}async rgba(){return c("plugin:image|rgba",{rid:this.rid}).then((e=>new Uint8Array(e)))}async size(){return c("plugin:image|size",{rid:this.rid})}}function w(e){return null==e?null:"string"==typeof e?e:e instanceof h?e.rid:e}var y=Object.freeze({__proto__:null,Image:h,transformImage:w});var g=Object.freeze({__proto__:null,defaultWindowIcon:async function(){return c("plugin:app|default_window_icon").then((e=>e?new h(e):null))},getName:async function(){return c("plugin:app|name")},getTauriVersion:async function(){return c("plugin:app|tauri_version")},getVersion:async function(){return c("plugin:app|version")},hide:async function(){return c("plugin:app|app_hide")},setTheme:async function(e){return c("plugin:app|set_app_theme",{theme:e})},show:async function(){return c("plugin:app|app_show")}});class _{constructor(e,n){this.type="Logical",this.width=e,this.height=n}toPhysical(e){return new b(this.width*e,this.height*e)}}class b{constructor(e,n){this.type="Physical",this.width=e,this.height=n}toLogical(e){return new _(this.width/e,this.height/e)}}class m{constructor(e,n){this.type="Logical",this.x=e,this.y=n}toPhysical(e){return new v(this.x*e,this.x*e)}}class v{constructor(e,n){this.type="Physical",this.x=e,this.y=n}toLogical(e){return new m(this.x/e,this.y/e)}}var f,k=Object.freeze({__proto__:null,LogicalPosition:m,LogicalSize:_,PhysicalPosition:v,PhysicalSize:b});async function A(e,n){await c("plugin:event|unlisten",{event:e,eventId:n})}async function E(e,n,t){var i;const r="string"==typeof(null==t?void 0:t.target)?{kind:"AnyLabel",label:t.target}:null!==(i=null==t?void 0:t.target)&&void 0!==i?i:{kind:"Any"};return c("plugin:event|listen",{event:e,target:r,handler:l(n)}).then((n=>async()=>A(e,n)))}async function D(e,n,t){return E(e,(t=>{A(e,t.id),n(t)}),t)}async function T(e,n){await c("plugin:event|emit",{event:e,payload:n})}async function I(e,n,t){const i="string"==typeof e?{kind:"AnyLabel",label:e}:e;await c("plugin:event|emit_to",{target:i,event:n,payload:t})}!function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(f||(f={}));var R,S,L,P,x,z=Object.freeze({__proto__:null,get TauriEvent(){return f},emit:T,emitTo:I,listen:E,once:D});function C(e){var n;if("items"in e)e.items=null===(n=e.items)||void 0===n?void 0:n.map((e=>"rid"in e?e:C(e)));else if("action"in e&&e.action){const n=new o;return n.onmessage=e.action,delete e.action,{...e,handler:n}}return e}async function W(e,n){const t=new o;if(n&&"object"==typeof n&&("action"in n&&n.action&&(t.onmessage=n.action,delete n.action),"items"in n&&n.items)){function i(e){var n;return"rid"in e?[e.rid,e.kind]:("item"in e&&"object"==typeof e.item&&(null===(n=e.item.About)||void 0===n?void 0:n.icon)&&(e.item.About.icon=w(e.item.About.icon)),"icon"in e&&e.icon&&(e.icon=w(e.icon)),"items"in e&&e.items&&(e.items=e.items.map(i)),C(e))}n.items=n.items.map(i)}return c("plugin:menu|new",{kind:e,options:n,handler:t})}class N extends d{get id(){return n(this,R,"f")}get kind(){return n(this,S,"f")}constructor(e,n,i){super(e),R.set(this,void 0),S.set(this,void 0),t(this,R,n,"f"),t(this,S,i,"f")}}R=new WeakMap,S=new WeakMap;class O extends N{constructor(e,n){super(e,n,"MenuItem")}static async new(e){return W("MenuItem",e).then((([e,n])=>new O(e,n)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return c("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class F extends N{constructor(e,n){super(e,n,"Check")}static async new(e){return W("Check",e).then((([e,n])=>new F(e,n)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return c("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return c("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return c("plugin:menu|set_checked",{rid:this.rid,checked:e})}}!function(e){e.Add="Add",e.Advanced="Advanced",e.Bluetooth="Bluetooth",e.Bookmarks="Bookmarks",e.Caution="Caution",e.ColorPanel="ColorPanel",e.ColumnView="ColumnView",e.Computer="Computer",e.EnterFullScreen="EnterFullScreen",e.Everyone="Everyone",e.ExitFullScreen="ExitFullScreen",e.FlowView="FlowView",e.Folder="Folder",e.FolderBurnable="FolderBurnable",e.FolderSmart="FolderSmart",e.FollowLinkFreestanding="FollowLinkFreestanding",e.FontPanel="FontPanel",e.GoLeft="GoLeft",e.GoRight="GoRight",e.Home="Home",e.IChatTheater="IChatTheater",e.IconView="IconView",e.Info="Info",e.InvalidDataFreestanding="InvalidDataFreestanding",e.LeftFacingTriangle="LeftFacingTriangle",e.ListView="ListView",e.LockLocked="LockLocked",e.LockUnlocked="LockUnlocked",e.MenuMixedState="MenuMixedState",e.MenuOnState="MenuOnState",e.MobileMe="MobileMe",e.MultipleDocuments="MultipleDocuments",e.Network="Network",e.Path="Path",e.PreferencesGeneral="PreferencesGeneral",e.QuickLook="QuickLook",e.RefreshFreestanding="RefreshFreestanding",e.Refresh="Refresh",e.Remove="Remove",e.RevealFreestanding="RevealFreestanding",e.RightFacingTriangle="RightFacingTriangle",e.Share="Share",e.Slideshow="Slideshow",e.SmartBadge="SmartBadge",e.StatusAvailable="StatusAvailable",e.StatusNone="StatusNone",e.StatusPartiallyAvailable="StatusPartiallyAvailable",e.StatusUnavailable="StatusUnavailable",e.StopProgressFreestanding="StopProgressFreestanding",e.StopProgress="StopProgress",e.TrashEmpty="TrashEmpty",e.TrashFull="TrashFull",e.User="User",e.UserAccounts="UserAccounts",e.UserGroup="UserGroup",e.UserGuest="UserGuest"}(L||(L={}));class M extends N{constructor(e,n){super(e,n,"Icon")}static async new(e){return W("Icon",e).then((([e,n])=>new M(e,n)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return c("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return c("plugin:menu|set_icon",{rid:this.rid,icon:w(e)})}}class U extends N{constructor(e,n){super(e,n,"Predefined")}static async new(e){return W("Predefined",e).then((([e,n])=>new U(e,n)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}!function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"}(P||(P={}));class B{constructor(e){this._preventDefault=!1,this.event=e.event,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}function j(){return new H(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}async function V(){return c("plugin:window|get_all_windows").then((e=>e.map((e=>new H(e,{skip:!0})))))}!function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"}(x||(x={}));const G=["tauri://created","tauri://error"];class H{constructor(e,n={}){var t;this.label=e,this.listeners=Object.create(null),(null==n?void 0:n.skip)||c("plugin:window|create",{options:{...n,parent:"string"==typeof n.parent?n.parent:null===(t=n.parent)||void 0===t?void 0:t.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static async getByLabel(e){var n;return null!==(n=(await V()).find((n=>n.label===e)))&&void 0!==n?n:null}static getCurrent(){return j()}static async getAll(){return V()}static async getFocusedWindow(){for(const e of await V())if(await e.isFocused())return e;return null}async listen(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:E(e,n,{target:{kind:"Window",label:this.label}})}async once(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:D(e,n,{target:{kind:"Window",label:this.label}})}async emit(e,n){if(!G.includes(e))return T(e,n);for(const t of this.listeners[e]||[])t({event:e,id:-1,payload:n})}async emitTo(e,n,t){if(!G.includes(n))return I(e,n,t);for(const e of this.listeners[n]||[])e({event:n,id:-1,payload:t})}_handleTauriEvent(e,n){return!!G.includes(e)&&(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0)}async scaleFactor(){return c("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return c("plugin:window|inner_position",{label:this.label}).then((({x:e,y:n})=>new v(e,n)))}async outerPosition(){return c("plugin:window|outer_position",{label:this.label}).then((({x:e,y:n})=>new v(e,n)))}async innerSize(){return c("plugin:window|inner_size",{label:this.label}).then((({width:e,height:n})=>new b(e,n)))}async outerSize(){return c("plugin:window|outer_size",{label:this.label}).then((({width:e,height:n})=>new b(e,n)))}async isFullscreen(){return c("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return c("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return c("plugin:window|is_maximized",{label:this.label})}async isFocused(){return c("plugin:window|is_focused",{label:this.label})}async isDecorated(){return c("plugin:window|is_decorated",{label:this.label})}async isResizable(){return c("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return c("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return c("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return c("plugin:window|is_closable",{label:this.label})}async isVisible(){return c("plugin:window|is_visible",{label:this.label})}async title(){return c("plugin:window|title",{label:this.label})}async theme(){return c("plugin:window|theme",{label:this.label})}async center(){return c("plugin:window|center",{label:this.label})}async requestUserAttention(e){let n=null;return e&&(n=e===P.Critical?{type:"Critical"}:{type:"Informational"}),c("plugin:window|request_user_attention",{label:this.label,value:n})}async setResizable(e){return c("plugin:window|set_resizable",{label:this.label,value:e})}async setEnabled(e){return c("plugin:window|set_enabled",{label:this.label,value:e})}async isEnabled(){return c("plugin:window|is_enabled",{label:this.label})}async setMaximizable(e){return c("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return c("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return c("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return c("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return c("plugin:window|maximize",{label:this.label})}async unmaximize(){return c("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return c("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return c("plugin:window|minimize",{label:this.label})}async unminimize(){return c("plugin:window|unminimize",{label:this.label})}async show(){return c("plugin:window|show",{label:this.label})}async hide(){return c("plugin:window|hide",{label:this.label})}async close(){return c("plugin:window|close",{label:this.label})}async destroy(){return c("plugin:window|destroy",{label:this.label})}async setDecorations(e){return c("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return c("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return c("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return c("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return c("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return c("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return c("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");const n={};return n[`${e.type}`]={width:e.width,height:e.height},c("plugin:window|set_size",{label:this.label,value:n})}async setMinSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");let n=null;return e&&(n={},n[`${e.type}`]={width:e.width,height:e.height}),c("plugin:window|set_min_size",{label:this.label,value:n})}async setMaxSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");let n=null;return e&&(n={},n[`${e.type}`]={width:e.width,height:e.height}),c("plugin:window|set_max_size",{label:this.label,value:n})}async setSizeConstraints(e){function n(e){return e?{Logical:e}:null}return c("plugin:window|set_size_constraints",{label:this.label,value:{minWidth:n(null==e?void 0:e.minWidth),minHeight:n(null==e?void 0:e.minHeight),maxWidth:n(null==e?void 0:e.maxWidth),maxHeight:n(null==e?void 0:e.maxHeight)}})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");const n={};return n[`${e.type}`]={x:e.x,y:e.y},c("plugin:window|set_position",{label:this.label,value:n})}async setFullscreen(e){return c("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return c("plugin:window|set_focus",{label:this.label})}async setIcon(e){return c("plugin:window|set_icon",{label:this.label,value:w(e)})}async setSkipTaskbar(e){return c("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return c("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return c("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return c("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");const n={};return n[`${e.type}`]={x:e.x,y:e.y},c("plugin:window|set_cursor_position",{label:this.label,value:n})}async setIgnoreCursorEvents(e){return c("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return c("plugin:window|start_dragging",{label:this.label})}async startResizeDragging(e){return c("plugin:window|start_resize_dragging",{label:this.label,value:e})}async setProgressBar(e){return c("plugin:window|set_progress_bar",{label:this.label,value:e})}async setVisibleOnAllWorkspaces(e){return c("plugin:window|set_visible_on_all_workspaces",{label:this.label,value:e})}async setTitleBarStyle(e){return c("plugin:window|set_title_bar_style",{label:this.label,value:e})}async setTheme(e){return c("plugin:window|set_theme",{label:this.label,value:e})}async onResized(e){return this.listen(f.WINDOW_RESIZED,(n=>{n.payload=J(n.payload),e(n)}))}async onMoved(e){return this.listen(f.WINDOW_MOVED,(n=>{n.payload=Z(n.payload),e(n)}))}async onCloseRequested(e){return this.listen(f.WINDOW_CLOSE_REQUESTED,(async n=>{const t=new B(n);await e(t),t.isPreventDefault()||await this.destroy()}))}async onDragDropEvent(e){const n=await this.listen(f.DRAG_ENTER,(n=>{e({...n,payload:{type:"enter",paths:n.payload.paths,position:Z(n.payload.position)}})})),t=await this.listen(f.DRAG_OVER,(n=>{e({...n,payload:{type:"over",position:Z(n.payload.position)}})})),i=await this.listen(f.DRAG_DROP,(n=>{e({...n,payload:{type:"drop",paths:n.payload.paths,position:Z(n.payload.position)}})})),r=await this.listen(f.DRAG_LEAVE,(n=>{e({...n,payload:{type:"leave"}})}));return()=>{n(),i(),t(),r()}}async onFocusChanged(e){const n=await this.listen(f.WINDOW_FOCUS,(n=>{e({...n,payload:!0})})),t=await this.listen(f.WINDOW_BLUR,(n=>{e({...n,payload:!1})}));return()=>{n(),t()}}async onScaleChanged(e){return this.listen(f.WINDOW_SCALE_FACTOR_CHANGED,e)}async onThemeChanged(e){return this.listen(f.WINDOW_THEME_CHANGED,e)}}var $,q;function Q(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:Z(e.position),size:J(e.size)}}function Z(e){return new v(e.x,e.y)}function J(e){return new b(e.width,e.height)}!function(e){e.AppearanceBased="appearanceBased",e.Light="light",e.Dark="dark",e.MediumLight="mediumLight",e.UltraDark="ultraDark",e.Titlebar="titlebar",e.Selection="selection",e.Menu="menu",e.Popover="popover",e.Sidebar="sidebar",e.HeaderView="headerView",e.Sheet="sheet",e.WindowBackground="windowBackground",e.HudWindow="hudWindow",e.FullScreenUI="fullScreenUI",e.Tooltip="tooltip",e.ContentBackground="contentBackground",e.UnderWindowBackground="underWindowBackground",e.UnderPageBackground="underPageBackground",e.Mica="mica",e.Blur="blur",e.Acrylic="acrylic",e.Tabbed="tabbed",e.TabbedDark="tabbedDark",e.TabbedLight="tabbedLight"}($||($={})),function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"}(q||(q={}));var K=Object.freeze({__proto__:null,CloseRequestedEvent:B,get Effect(){return $},get EffectState(){return q},LogicalPosition:m,LogicalSize:_,PhysicalPosition:v,PhysicalSize:b,get ProgressBarStatus(){return x},get UserAttentionType(){return P},Window:H,availableMonitors:async function(){return c("plugin:window|available_monitors").then((e=>e.map(Q)))},currentMonitor:async function(){return c("plugin:window|current_monitor").then(Q)},cursorPosition:async function(){return c("plugin:window|cursor_position").then(Z)},getAllWindows:V,getCurrentWindow:j,monitorFromPoint:async function(e,n){return c("plugin:window|monitor_from_point",{x:e,y:n}).then(Q)},primaryMonitor:async function(){return c("plugin:window|primary_monitor").then(Q)}});function Y([e,n,t]){switch(t){case"Submenu":return new X(e,n);case"Predefined":return new U(e,n);case"Check":return new F(e,n);case"Icon":return new M(e,n);default:return new O(e,n)}}class X extends N{constructor(e,n){super(e,n,"Submenu")}static async new(e){return W("Submenu",e).then((([e,n])=>new X(e,n)))}async text(){return c("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return c("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return c("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return c("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return c("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return c("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,n){return c("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:n})}async remove(e){return c("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return c("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(Y)}async items(){return c("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(Y)))}async get(e){return c("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?Y(e):null))}async popup(e,n){var t;let i=null;return e&&(i={},i[""+(e instanceof v?"Physical":"Logical")]={x:e.x,y:e.y}),c("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:null!==(t=null==n?void 0:n.label)&&void 0!==t?t:null,at:i})}async setAsWindowsMenuForNSApp(){return c("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return c("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function ee([e,n,t]){switch(t){case"Submenu":return new X(e,n);case"Predefined":return new U(e,n);case"Check":return new F(e,n);case"Icon":return new M(e,n);default:return new O(e,n)}}class ne extends N{constructor(e,n){super(e,n,"Menu")}static async new(e){return W("Menu",e).then((([e,n])=>new ne(e,n)))}static async default(){return c("plugin:menu|create_default").then((([e,n])=>new ne(e,n)))}async append(e){return c("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return c("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,n){return c("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:n})}async remove(e){return c("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return c("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(ee)}async items(){return c("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(ee)))}async get(e){return c("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?ee(e):null))}async popup(e,n){var t;let i=null;return e&&(i={},i[""+(e instanceof v?"Physical":"Logical")]={x:e.x,y:e.y}),c("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:null!==(t=null==n?void 0:n.label)&&void 0!==t?t:null,at:i})}async setAsAppMenu(){return c("plugin:menu|set_as_app_menu",{rid:this.rid}).then((e=>e?new ne(e[0],e[1]):null))}async setAsWindowMenu(e){var n;return c("plugin:menu|set_as_window_menu",{rid:this.rid,window:null!==(n=null==e?void 0:e.label)&&void 0!==n?n:null}).then((e=>e?new ne(e[0],e[1]):null))}}var te=Object.freeze({__proto__:null,CheckMenuItem:F,IconMenuItem:M,Menu:ne,MenuItem:O,get NativeIcon(){return L},PredefinedMenuItem:U,Submenu:X});function ie(){var e;window.__TAURI_INTERNALS__=null!==(e=window.__TAURI_INTERNALS__)&&void 0!==e?e:{}}var re,ae=Object.freeze({__proto__:null,clearMocks:function(){var e,n,t;"object"==typeof window.__TAURI_INTERNALS__&&((null===(e=window.__TAURI_INTERNALS__)||void 0===e?void 0:e.convertFileSrc)&&delete window.__TAURI_INTERNALS__.convertFileSrc,(null===(n=window.__TAURI_INTERNALS__)||void 0===n?void 0:n.invoke)&&delete window.__TAURI_INTERNALS__.invoke,(null===(t=window.__TAURI_INTERNALS__)||void 0===t?void 0:t.metadata)&&delete window.__TAURI_INTERNALS__.metadata)},mockConvertFileSrc:function(e){ie(),window.__TAURI_INTERNALS__.convertFileSrc=function(n,t="asset"){const i=encodeURIComponent(n);return"windows"===e?`http://${t}.localhost/${i}`:`${t}://localhost/${i}`}},mockIPC:function(e){ie(),window.__TAURI_INTERNALS__.transformCallback=function(e,n=!1){const t=window.crypto.getRandomValues(new Uint32Array(1))[0],i=`_${t}`;return Object.defineProperty(window,i,{value:t=>(n&&Reflect.deleteProperty(window,i),e&&e(t)),writable:!1,configurable:!0}),t},window.__TAURI_INTERNALS__.invoke=function(n,t,i){return e(n,t)}},mockWindows:function(e,...n){ie(),window.__TAURI_INTERNALS__.metadata={currentWindow:{label:e},currentWebview:{windowLabel:e,label:e}}}});!function(e){e[e.Audio=1]="Audio",e[e.Cache=2]="Cache",e[e.Config=3]="Config",e[e.Data=4]="Data",e[e.LocalData=5]="LocalData",e[e.Document=6]="Document",e[e.Download=7]="Download",e[e.Picture=8]="Picture",e[e.Public=9]="Public",e[e.Video=10]="Video",e[e.Resource=11]="Resource",e[e.Temp=12]="Temp",e[e.AppConfig=13]="AppConfig",e[e.AppData=14]="AppData",e[e.AppLocalData=15]="AppLocalData",e[e.AppCache=16]="AppCache",e[e.AppLog=17]="AppLog",e[e.Desktop=18]="Desktop",e[e.Executable=19]="Executable",e[e.Font=20]="Font",e[e.Home=21]="Home",e[e.Runtime=22]="Runtime",e[e.Template=23]="Template"}(re||(re={}));var se=Object.freeze({__proto__:null,get BaseDirectory(){return re},appCacheDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppCache})},appConfigDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppConfig})},appDataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppData})},appLocalDataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppLocalData})},appLogDir:async function(){return c("plugin:path|resolve_directory",{directory:re.AppLog})},audioDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Audio})},basename:async function(e,n){return c("plugin:path|basename",{path:e,ext:n})},cacheDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Cache})},configDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Config})},dataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Data})},delimiter:function(){return window.__TAURI_INTERNALS__.plugins.path.delimiter},desktopDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Desktop})},dirname:async function(e){return c("plugin:path|dirname",{path:e})},documentDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Document})},downloadDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Download})},executableDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Executable})},extname:async function(e){return c("plugin:path|extname",{path:e})},fontDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Font})},homeDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Home})},isAbsolute:async function(e){return c("plugin:path|isAbsolute",{path:e})},join:async function(...e){return c("plugin:path|join",{paths:e})},localDataDir:async function(){return c("plugin:path|resolve_directory",{directory:re.LocalData})},normalize:async function(e){return c("plugin:path|normalize",{path:e})},pictureDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Picture})},publicDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Public})},resolve:async function(...e){return c("plugin:path|resolve",{paths:e})},resolveResource:async function(e){return c("plugin:path|resolve_directory",{directory:re.Resource,path:e})},resourceDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Resource})},runtimeDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Runtime})},sep:function(){return window.__TAURI_INTERNALS__.plugins.path.sep},tempDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Temp})},templateDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Template})},videoDir:async function(){return c("plugin:path|resolve_directory",{directory:re.Video})}});class le extends d{constructor(e,n){super(e),this.id=n}static async getById(e){return c("plugin:tray|get_by_id",{id:e}).then((n=>n?new le(n,e):null))}static async removeById(e){return c("plugin:tray|remove_by_id",{id:e})}static async new(e){(null==e?void 0:e.menu)&&(e.menu=[e.menu.rid,e.menu.kind]),(null==e?void 0:e.icon)&&(e.icon=w(e.icon));const n=new o;if(null==e?void 0:e.action){const t=e.action;n.onmessage=e=>t(function(e){const n=e;return n.position=new v(e.position.x,e.position.y),n.rect.position=new v(e.rect.position.Physical.x,e.rect.position.Physical.y),n.rect.size=new b(e.rect.size.Physical.width,e.rect.size.Physical.height),n}(e)),delete e.action}return c("plugin:tray|new",{options:null!=e?e:{},handler:n}).then((([e,n])=>new le(e,n)))}async setIcon(e){let n=null;return e&&(n=w(e)),c("plugin:tray|set_icon",{rid:this.rid,icon:n})}async setMenu(e){return e&&(e=[e.rid,e.kind]),c("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return c("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return c("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return c("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return c("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return c("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return c("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}var oe=Object.freeze({__proto__:null,TrayIcon:le});function ue(){return new pe(j(),window.__TAURI_INTERNALS__.metadata.currentWebview.label,{skip:!0})}async function ce(){return c("plugin:webview|get_all_webviews").then((e=>e.map((e=>new pe(new H(e.windowLabel,{skip:!0}),e.label,{skip:!0})))))}const de=["tauri://created","tauri://error"];class pe{constructor(e,n,t){this.window=e,this.label=n,this.listeners=Object.create(null),(null==t?void 0:t.skip)||c("plugin:webview|create_webview",{windowLabel:e.label,label:n,options:t}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static async getByLabel(e){var n;return null!==(n=(await ce()).find((n=>n.label===e)))&&void 0!==n?n:null}static getCurrent(){return ue()}static async getAll(){return ce()}async listen(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:E(e,n,{target:{kind:"Webview",label:this.label}})}async once(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:D(e,n,{target:{kind:"Webview",label:this.label}})}async emit(e,n){if(!de.includes(e))return T(e,n);for(const t of this.listeners[e]||[])t({event:e,id:-1,payload:n})}async emitTo(e,n,t){if(!de.includes(n))return I(e,n,t);for(const e of this.listeners[n]||[])e({event:n,id:-1,payload:t})}_handleTauriEvent(e,n){return!!de.includes(e)&&(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0)}async position(){return c("plugin:webview|webview_position",{label:this.label}).then((({x:e,y:n})=>new v(e,n)))}async size(){return c("plugin:webview|webview_size",{label:this.label}).then((({width:e,height:n})=>new b(e,n)))}async close(){return c("plugin:webview|close",{label:this.label})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");const n={};return n[`${e.type}`]={width:e.width,height:e.height},c("plugin:webview|set_webview_size",{label:this.label,value:n})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");const n={};return n[`${e.type}`]={x:e.x,y:e.y},c("plugin:webview|set_webview_position",{label:this.label,value:n})}async setFocus(){return c("plugin:webview|set_webview_focus",{label:this.label})}async hide(){return c("plugin:webview|webview_hide",{label:this.label})}async show(){return c("plugin:webview|webview_show",{label:this.label})}async setZoom(e){return c("plugin:webview|set_webview_zoom",{label:this.label,value:e})}async reparent(e){return c("plugin:webview|reparent",{label:this.label,window:"string"==typeof e?e:e.label})}async clearAllBrowsingData(){return c("plugin:webview|clear_all_browsing_data")}async onDragDropEvent(e){const n=await this.listen(f.DRAG_ENTER,(n=>{e({...n,payload:{type:"enter",paths:n.payload.paths,position:he(n.payload.position)}})})),t=await this.listen(f.DRAG_OVER,(n=>{e({...n,payload:{type:"over",position:he(n.payload.position)}})})),i=await this.listen(f.DRAG_DROP,(n=>{e({...n,payload:{type:"drop",paths:n.payload.paths,position:he(n.payload.position)}})})),r=await this.listen(f.DRAG_LEAVE,(n=>{e({...n,payload:{type:"leave"}})}));return()=>{n(),i(),t(),r()}}}function he(e){return new v(e.x,e.y)}var we,ye,ge=Object.freeze({__proto__:null,Webview:pe,getAllWebviews:ce,getCurrentWebview:ue});function _e(){const e=ue();return new me(e.label,{skip:!0})}async function be(){return c("plugin:window|get_all_windows").then((e=>e.map((e=>new me(e,{skip:!0})))))}class me{constructor(e,n={}){var t;this.label=e,this.listeners=Object.create(null),(null==n?void 0:n.skip)||c("plugin:webview|create_webview_window",{options:{...n,parent:"string"==typeof n.parent?n.parent:null===(t=n.parent)||void 0===t?void 0:t.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static async getByLabel(e){var n;const t=null!==(n=(await be()).find((n=>n.label===e)))&&void 0!==n?n:null;return t?new me(t.label,{skip:!0}):null}static getCurrent(){return _e()}static async getAll(){return be()}async listen(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:E(e,n,{target:{kind:"WebviewWindow",label:this.label}})}async once(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:D(e,n,{target:{kind:"WebviewWindow",label:this.label}})}}we=me,ye=[H,pe],(Array.isArray(ye)?ye:[ye]).forEach((e=>{Object.getOwnPropertyNames(e.prototype).forEach((n=>{var t;"object"==typeof we.prototype&&we.prototype&&n in we.prototype||Object.defineProperty(we.prototype,n,null!==(t=Object.getOwnPropertyDescriptor(e.prototype,n))&&void 0!==t?t:Object.create(null))}))}));var ve=Object.freeze({__proto__:null,WebviewWindow:me,getAllWebviewWindows:be,getCurrentWebviewWindow:_e});return e.app=g,e.core=p,e.dpi=k,e.event=z,e.image=y,e.menu=te,e.mocks=ae,e.path=se,e.tray=oe,e.webview=ge,e.webviewWindow=ve,e.window=K,e}({});window.__TAURI__=__TAURI_IIFE__; +var __TAURI_IIFE__=function(e){"use strict";function n(e,n,t,i){if("a"===t&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof n?e!==n||!i:!n.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?i:"a"===t?i.call(e):i?i.value:n.get(e)}function t(e,n,t,i,r){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof n?e!==n||!r:!n.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?r.call(e,t):r?r.value=t:n.set(e,t),t}var i,r,s,a;"function"==typeof SuppressedError&&SuppressedError;const l="__TAURI_TO_IPC_KEY__";function o(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}class u{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),r.set(this,0),s.set(this,{}),this.id=o((({message:e,id:a})=>{if(a===n(this,r,"f")){t(this,r,a+1,"f"),n(this,i,"f").call(this,e);const l=Object.keys(n(this,s,"f"));if(l.length>0){let e=a+1;for(const t of l.sort()){if(parseInt(t)!==e)break;{const r=n(this,s,"f")[t];delete n(this,s,"f")[t],n(this,i,"f").call(this,r),e+=1}}t(this,r,e,"f")}}else n(this,s,"f")[a.toString()]=e}))}set onmessage(e){t(this,i,e,"f")}get onmessage(){return n(this,i,"f")}[(i=new WeakMap,r=new WeakMap,s=new WeakMap,l)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[l]()}}class c{constructor(e,n,t){this.plugin=e,this.event=n,this.channelId=t}async unregister(){return d(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function d(e,n={},t){return window.__TAURI_INTERNALS__.invoke(e,n,t)}class h{get rid(){return n(this,a,"f")}constructor(e){a.set(this,void 0),t(this,a,e,"f")}async close(){return d("plugin:resources|close",{rid:this.rid})}}a=new WeakMap;var p=Object.freeze({__proto__:null,Channel:u,PluginListener:c,Resource:h,SERIALIZE_TO_IPC_FN:l,addPluginListener:async function(e,n,t){const i=new u;return i.onmessage=t,d(`plugin:${e}|registerListener`,{event:n,handler:i}).then((()=>new c(e,n,i.id)))},checkPermissions:async function(e){return d(`plugin:${e}|check_permissions`)},convertFileSrc:function(e,n="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,n)},invoke:d,isTauri:function(){return"isTauri"in window&&!!window.isTauri},requestPermissions:async function(e){return d(`plugin:${e}|request_permissions`)},transformCallback:o});class w extends h{constructor(e){super(e)}static async new(e,n,t){return d("plugin:image|new",{rgba:y(e),width:n,height:t}).then((e=>new w(e)))}static async fromBytes(e){return d("plugin:image|from_bytes",{bytes:y(e)}).then((e=>new w(e)))}static async fromPath(e){return d("plugin:image|from_path",{path:e}).then((e=>new w(e)))}async rgba(){return d("plugin:image|rgba",{rid:this.rid}).then((e=>new Uint8Array(e)))}async size(){return d("plugin:image|size",{rid:this.rid})}}function y(e){return null==e?null:"string"==typeof e?e:e instanceof w?e.rid:e}var _=Object.freeze({__proto__:null,Image:w,transformImage:y});var g=Object.freeze({__proto__:null,defaultWindowIcon:async function(){return d("plugin:app|default_window_icon").then((e=>e?new w(e):null))},getName:async function(){return d("plugin:app|name")},getTauriVersion:async function(){return d("plugin:app|tauri_version")},getVersion:async function(){return d("plugin:app|version")},hide:async function(){return d("plugin:app|app_hide")},setTheme:async function(e){return d("plugin:app|set_app_theme",{theme:e})},show:async function(){return d("plugin:app|app_show")}});class b{constructor(...e){this.type="Logical",1===e.length?"Logical"in e[0]?(this.width=e[0].Logical.width,this.height=e[0].Logical.height):(this.width=e[0].width,this.height=e[0].height):(this.width=e[0],this.height=e[1])}toPhysical(e){return new m(this.width*e,this.height*e)}[l](){return{width:this.width,height:this.height}}toJSON(){return this[l]()}}class m{constructor(...e){this.type="Physical",1===e.length?"Physical"in e[0]?(this.width=e[0].Physical.width,this.height=e[0].Physical.height):(this.width=e[0].width,this.height=e[0].height):(this.width=e[0],this.height=e[1])}toLogical(e){return new b(this.width/e,this.height/e)}[l](){return{width:this.width,height:this.height}}toJSON(){return this[l]()}}class v{constructor(e){this.size=e}toLogical(e){return this.size instanceof b?this.size:this.size.toLogical(e)}toPhysical(e){return this.size instanceof m?this.size:this.size.toPhysical(e)}[l](){return{[`${this.size.type}`]:{width:this.size.width,height:this.size.height}}}toJSON(){return this[l]()}}class f{constructor(...e){this.type="Logical",1===e.length?"Logical"in e[0]?(this.x=e[0].Logical.x,this.y=e[0].Logical.y):(this.x=e[0].x,this.y=e[0].y):(this.x=e[0],this.y=e[1])}toPhysical(e){return new k(this.x*e,this.x*e)}[l](){return{x:this.x,y:this.y}}toJSON(){return this[l]()}}class k{constructor(...e){this.type="Physical",1===e.length?"Physical"in e[0]?(this.x=e[0].Physical.x,this.y=e[0].Physical.y):(this.x=e[0].x,this.y=e[0].y):(this.x=e[0],this.y=e[1])}toLogical(e){return new f(this.x/e,this.x/e)}[l](){return{x:this.x,y:this.y}}toJSON(){return this[l]()}}class A{constructor(e){this.position=e}toLogical(e){return this.position instanceof f?this.position:this.position.toLogical(e)}toPhysical(e){return this.position instanceof k?this.position:this.position.toPhysical(e)}[l](){return{[`${this.position.type}`]:{x:this.position.x,y:this.position.y}}}toJSON(){return this[l]()}}var E,T=Object.freeze({__proto__:null,LogicalPosition:f,LogicalSize:b,PhysicalPosition:k,PhysicalSize:m,Position:A,Size:v});async function D(e,n){await d("plugin:event|unlisten",{event:e,eventId:n})}async function I(e,n,t){var i;const r="string"==typeof(null==t?void 0:t.target)?{kind:"AnyLabel",label:t.target}:null!==(i=null==t?void 0:t.target)&&void 0!==i?i:{kind:"Any"};return d("plugin:event|listen",{event:e,target:r,handler:o(n)}).then((n=>async()=>D(e,n)))}async function R(e,n,t){return I(e,(t=>{D(e,t.id),n(t)}),t)}async function S(e,n){await d("plugin:event|emit",{event:e,payload:n})}async function L(e,n,t){const i="string"==typeof e?{kind:"AnyLabel",label:e}:e;await d("plugin:event|emit_to",{target:i,event:n,payload:t})}!function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(E||(E={}));var x,N,C,P=Object.freeze({__proto__:null,get TauriEvent(){return E},emit:S,emitTo:L,listen:I,once:R});function z(e){var n;if("items"in e)e.items=null===(n=e.items)||void 0===n?void 0:n.map((e=>"rid"in e?e:z(e)));else if("action"in e&&e.action){const n=new u;return n.onmessage=e.action,delete e.action,{...e,handler:n}}return e}async function W(e,n){const t=new u;if(n&&"object"==typeof n&&("action"in n&&n.action&&(t.onmessage=n.action,delete n.action),"items"in n&&n.items)){function i(e){var n;return"rid"in e?[e.rid,e.kind]:("item"in e&&"object"==typeof e.item&&(null===(n=e.item.About)||void 0===n?void 0:n.icon)&&(e.item.About.icon=y(e.item.About.icon)),"icon"in e&&e.icon&&(e.icon=y(e.icon)),"items"in e&&e.items&&(e.items=e.items.map(i)),z(e))}n.items=n.items.map(i)}return d("plugin:menu|new",{kind:e,options:n,handler:t})}class O extends h{get id(){return n(this,x,"f")}get kind(){return n(this,N,"f")}constructor(e,n,i){super(e),x.set(this,void 0),N.set(this,void 0),t(this,x,n,"f"),t(this,N,i,"f")}}x=new WeakMap,N=new WeakMap;class F extends O{constructor(e,n){super(e,n,"MenuItem")}static async new(e){return W("MenuItem",e).then((([e,n])=>new F(e,n)))}async text(){return d("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return d("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return d("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return d("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return d("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class M extends O{constructor(e,n){super(e,n,"Check")}static async new(e){return W("Check",e).then((([e,n])=>new M(e,n)))}async text(){return d("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return d("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return d("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return d("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return d("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return d("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return d("plugin:menu|set_checked",{rid:this.rid,checked:e})}}!function(e){e.Add="Add",e.Advanced="Advanced",e.Bluetooth="Bluetooth",e.Bookmarks="Bookmarks",e.Caution="Caution",e.ColorPanel="ColorPanel",e.ColumnView="ColumnView",e.Computer="Computer",e.EnterFullScreen="EnterFullScreen",e.Everyone="Everyone",e.ExitFullScreen="ExitFullScreen",e.FlowView="FlowView",e.Folder="Folder",e.FolderBurnable="FolderBurnable",e.FolderSmart="FolderSmart",e.FollowLinkFreestanding="FollowLinkFreestanding",e.FontPanel="FontPanel",e.GoLeft="GoLeft",e.GoRight="GoRight",e.Home="Home",e.IChatTheater="IChatTheater",e.IconView="IconView",e.Info="Info",e.InvalidDataFreestanding="InvalidDataFreestanding",e.LeftFacingTriangle="LeftFacingTriangle",e.ListView="ListView",e.LockLocked="LockLocked",e.LockUnlocked="LockUnlocked",e.MenuMixedState="MenuMixedState",e.MenuOnState="MenuOnState",e.MobileMe="MobileMe",e.MultipleDocuments="MultipleDocuments",e.Network="Network",e.Path="Path",e.PreferencesGeneral="PreferencesGeneral",e.QuickLook="QuickLook",e.RefreshFreestanding="RefreshFreestanding",e.Refresh="Refresh",e.Remove="Remove",e.RevealFreestanding="RevealFreestanding",e.RightFacingTriangle="RightFacingTriangle",e.Share="Share",e.Slideshow="Slideshow",e.SmartBadge="SmartBadge",e.StatusAvailable="StatusAvailable",e.StatusNone="StatusNone",e.StatusPartiallyAvailable="StatusPartiallyAvailable",e.StatusUnavailable="StatusUnavailable",e.StopProgressFreestanding="StopProgressFreestanding",e.StopProgress="StopProgress",e.TrashEmpty="TrashEmpty",e.TrashFull="TrashFull",e.User="User",e.UserAccounts="UserAccounts",e.UserGroup="UserGroup",e.UserGuest="UserGuest"}(C||(C={}));class U extends O{constructor(e,n){super(e,n,"Icon")}static async new(e){return W("Icon",e).then((([e,n])=>new U(e,n)))}async text(){return d("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return d("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return d("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return d("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return d("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return d("plugin:menu|set_icon",{rid:this.rid,icon:y(e)})}}class B extends O{constructor(e,n){super(e,n,"Predefined")}static async new(e){return W("Predefined",e).then((([e,n])=>new B(e,n)))}async text(){return d("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return d("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}function j([e,n,t]){switch(t){case"Submenu":return new V(e,n);case"Predefined":return new B(e,n);case"Check":return new M(e,n);case"Icon":return new U(e,n);default:return new F(e,n)}}class V extends O{constructor(e,n){super(e,n,"Submenu")}static async new(e){return W("Submenu",e).then((([e,n])=>new V(e,n)))}async text(){return d("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return d("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return d("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return d("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return d("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return d("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,n){return d("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:n})}async remove(e){return d("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return d("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(j)}async items(){return d("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(j)))}async get(e){return d("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?j(e):null))}async popup(e,n){var t;return d("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:null!==(t=null==n?void 0:n.label)&&void 0!==t?t:null,at:e instanceof A?e:e?new A(e):null})}async setAsWindowsMenuForNSApp(){return d("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return d("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function G([e,n,t]){switch(t){case"Submenu":return new V(e,n);case"Predefined":return new B(e,n);case"Check":return new M(e,n);case"Icon":return new U(e,n);default:return new F(e,n)}}class H extends O{constructor(e,n){super(e,n,"Menu")}static async new(e){return W("Menu",e).then((([e,n])=>new H(e,n)))}static async default(){return d("plugin:menu|create_default").then((([e,n])=>new H(e,n)))}async append(e){return d("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return d("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,n){return d("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:n})}async remove(e){return d("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return d("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(G)}async items(){return d("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(G)))}async get(e){return d("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?G(e):null))}async popup(e,n){var t;return d("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:null!==(t=null==n?void 0:n.label)&&void 0!==t?t:null,at:e instanceof A?e:e?new A(e):null})}async setAsAppMenu(){return d("plugin:menu|set_as_app_menu",{rid:this.rid}).then((e=>e?new H(e[0],e[1]):null))}async setAsWindowMenu(e){var n;return d("plugin:menu|set_as_window_menu",{rid:this.rid,window:null!==(n=null==e?void 0:e.label)&&void 0!==n?n:null}).then((e=>e?new H(e[0],e[1]):null))}}var $=Object.freeze({__proto__:null,CheckMenuItem:M,IconMenuItem:U,Menu:H,MenuItem:F,get NativeIcon(){return C},PredefinedMenuItem:B,Submenu:V});function q(){var e;window.__TAURI_INTERNALS__=null!==(e=window.__TAURI_INTERNALS__)&&void 0!==e?e:{}}var J,Q=Object.freeze({__proto__:null,clearMocks:function(){var e,n,t;"object"==typeof window.__TAURI_INTERNALS__&&((null===(e=window.__TAURI_INTERNALS__)||void 0===e?void 0:e.convertFileSrc)&&delete window.__TAURI_INTERNALS__.convertFileSrc,(null===(n=window.__TAURI_INTERNALS__)||void 0===n?void 0:n.invoke)&&delete window.__TAURI_INTERNALS__.invoke,(null===(t=window.__TAURI_INTERNALS__)||void 0===t?void 0:t.metadata)&&delete window.__TAURI_INTERNALS__.metadata)},mockConvertFileSrc:function(e){q(),window.__TAURI_INTERNALS__.convertFileSrc=function(n,t="asset"){const i=encodeURIComponent(n);return"windows"===e?`http://${t}.localhost/${i}`:`${t}://localhost/${i}`}},mockIPC:function(e){q(),window.__TAURI_INTERNALS__.transformCallback=function(e,n=!1){const t=window.crypto.getRandomValues(new Uint32Array(1))[0],i=`_${t}`;return Object.defineProperty(window,i,{value:t=>(n&&Reflect.deleteProperty(window,i),e&&e(t)),writable:!1,configurable:!0}),t},window.__TAURI_INTERNALS__.invoke=function(n,t,i){return e(n,t)}},mockWindows:function(e,...n){q(),window.__TAURI_INTERNALS__.metadata={currentWindow:{label:e},currentWebview:{windowLabel:e,label:e}}}});!function(e){e[e.Audio=1]="Audio",e[e.Cache=2]="Cache",e[e.Config=3]="Config",e[e.Data=4]="Data",e[e.LocalData=5]="LocalData",e[e.Document=6]="Document",e[e.Download=7]="Download",e[e.Picture=8]="Picture",e[e.Public=9]="Public",e[e.Video=10]="Video",e[e.Resource=11]="Resource",e[e.Temp=12]="Temp",e[e.AppConfig=13]="AppConfig",e[e.AppData=14]="AppData",e[e.AppLocalData=15]="AppLocalData",e[e.AppCache=16]="AppCache",e[e.AppLog=17]="AppLog",e[e.Desktop=18]="Desktop",e[e.Executable=19]="Executable",e[e.Font=20]="Font",e[e.Home=21]="Home",e[e.Runtime=22]="Runtime",e[e.Template=23]="Template"}(J||(J={}));var Z=Object.freeze({__proto__:null,get BaseDirectory(){return J},appCacheDir:async function(){return d("plugin:path|resolve_directory",{directory:J.AppCache})},appConfigDir:async function(){return d("plugin:path|resolve_directory",{directory:J.AppConfig})},appDataDir:async function(){return d("plugin:path|resolve_directory",{directory:J.AppData})},appLocalDataDir:async function(){return d("plugin:path|resolve_directory",{directory:J.AppLocalData})},appLogDir:async function(){return d("plugin:path|resolve_directory",{directory:J.AppLog})},audioDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Audio})},basename:async function(e,n){return d("plugin:path|basename",{path:e,ext:n})},cacheDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Cache})},configDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Config})},dataDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Data})},delimiter:function(){return window.__TAURI_INTERNALS__.plugins.path.delimiter},desktopDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Desktop})},dirname:async function(e){return d("plugin:path|dirname",{path:e})},documentDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Document})},downloadDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Download})},executableDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Executable})},extname:async function(e){return d("plugin:path|extname",{path:e})},fontDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Font})},homeDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Home})},isAbsolute:async function(e){return d("plugin:path|isAbsolute",{path:e})},join:async function(...e){return d("plugin:path|join",{paths:e})},localDataDir:async function(){return d("plugin:path|resolve_directory",{directory:J.LocalData})},normalize:async function(e){return d("plugin:path|normalize",{path:e})},pictureDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Picture})},publicDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Public})},resolve:async function(...e){return d("plugin:path|resolve",{paths:e})},resolveResource:async function(e){return d("plugin:path|resolve_directory",{directory:J.Resource,path:e})},resourceDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Resource})},runtimeDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Runtime})},sep:function(){return window.__TAURI_INTERNALS__.plugins.path.sep},tempDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Temp})},templateDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Template})},videoDir:async function(){return d("plugin:path|resolve_directory",{directory:J.Video})}});class K extends h{constructor(e,n){super(e),this.id=n}static async getById(e){return d("plugin:tray|get_by_id",{id:e}).then((n=>n?new K(n,e):null))}static async removeById(e){return d("plugin:tray|remove_by_id",{id:e})}static async new(e){(null==e?void 0:e.menu)&&(e.menu=[e.menu.rid,e.menu.kind]),(null==e?void 0:e.icon)&&(e.icon=y(e.icon));const n=new u;if(null==e?void 0:e.action){const t=e.action;n.onmessage=e=>t(function(e){const n=e;return n.position=new k(e.position),n.rect.position=new k(e.rect.position),n.rect.size=new m(e.rect.size),n}(e)),delete e.action}return d("plugin:tray|new",{options:null!=e?e:{},handler:n}).then((([e,n])=>new K(e,n)))}async setIcon(e){let n=null;return e&&(n=y(e)),d("plugin:tray|set_icon",{rid:this.rid,icon:n})}async setMenu(e){return e&&(e=[e.rid,e.kind]),d("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return d("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return d("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return d("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return d("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return d("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return d("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}var Y,X,ee=Object.freeze({__proto__:null,TrayIcon:K});!function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"}(Y||(Y={}));class ne{constructor(e){this._preventDefault=!1,this.event=e.event,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}function te(){return new se(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}async function ie(){return d("plugin:window|get_all_windows").then((e=>e.map((e=>new se(e,{skip:!0})))))}!function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"}(X||(X={}));const re=["tauri://created","tauri://error"];class se{constructor(e,n={}){var t;this.label=e,this.listeners=Object.create(null),(null==n?void 0:n.skip)||d("plugin:window|create",{options:{...n,parent:"string"==typeof n.parent?n.parent:null===(t=n.parent)||void 0===t?void 0:t.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static async getByLabel(e){var n;return null!==(n=(await ie()).find((n=>n.label===e)))&&void 0!==n?n:null}static getCurrent(){return te()}static async getAll(){return ie()}static async getFocusedWindow(){for(const e of await ie())if(await e.isFocused())return e;return null}async listen(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:I(e,n,{target:{kind:"Window",label:this.label}})}async once(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:R(e,n,{target:{kind:"Window",label:this.label}})}async emit(e,n){if(!re.includes(e))return S(e,n);for(const t of this.listeners[e]||[])t({event:e,id:-1,payload:n})}async emitTo(e,n,t){if(!re.includes(n))return L(e,n,t);for(const e of this.listeners[n]||[])e({event:n,id:-1,payload:t})}_handleTauriEvent(e,n){return!!re.includes(e)&&(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0)}async scaleFactor(){return d("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return d("plugin:window|inner_position",{label:this.label}).then((e=>new k(e)))}async outerPosition(){return d("plugin:window|outer_position",{label:this.label}).then((e=>new k(e)))}async innerSize(){return d("plugin:window|inner_size",{label:this.label}).then((e=>new m(e)))}async outerSize(){return d("plugin:window|outer_size",{label:this.label}).then((e=>new m(e)))}async isFullscreen(){return d("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return d("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return d("plugin:window|is_maximized",{label:this.label})}async isFocused(){return d("plugin:window|is_focused",{label:this.label})}async isDecorated(){return d("plugin:window|is_decorated",{label:this.label})}async isResizable(){return d("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return d("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return d("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return d("plugin:window|is_closable",{label:this.label})}async isVisible(){return d("plugin:window|is_visible",{label:this.label})}async title(){return d("plugin:window|title",{label:this.label})}async theme(){return d("plugin:window|theme",{label:this.label})}async center(){return d("plugin:window|center",{label:this.label})}async requestUserAttention(e){let n=null;return e&&(n=e===Y.Critical?{type:"Critical"}:{type:"Informational"}),d("plugin:window|request_user_attention",{label:this.label,value:n})}async setResizable(e){return d("plugin:window|set_resizable",{label:this.label,value:e})}async setEnabled(e){return d("plugin:window|set_enabled",{label:this.label,value:e})}async isEnabled(){return d("plugin:window|is_enabled",{label:this.label})}async setMaximizable(e){return d("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return d("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return d("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return d("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return d("plugin:window|maximize",{label:this.label})}async unmaximize(){return d("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return d("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return d("plugin:window|minimize",{label:this.label})}async unminimize(){return d("plugin:window|unminimize",{label:this.label})}async show(){return d("plugin:window|show",{label:this.label})}async hide(){return d("plugin:window|hide",{label:this.label})}async close(){return d("plugin:window|close",{label:this.label})}async destroy(){return d("plugin:window|destroy",{label:this.label})}async setDecorations(e){return d("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return d("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return d("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return d("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return d("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return d("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return d("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){return d("plugin:window|set_size",{label:this.label,value:e instanceof v?e:new v(e)})}async setMinSize(e){return d("plugin:window|set_min_size",{label:this.label,value:e instanceof v?e:e?new v(e):null})}async setMaxSize(e){return d("plugin:window|set_max_size",{label:this.label,value:e instanceof v?e:e?new v(e):null})}async setSizeConstraints(e){function n(e){return e?{Logical:e}:null}return d("plugin:window|set_size_constraints",{label:this.label,value:{minWidth:n(null==e?void 0:e.minWidth),minHeight:n(null==e?void 0:e.minHeight),maxWidth:n(null==e?void 0:e.maxWidth),maxHeight:n(null==e?void 0:e.maxHeight)}})}async setPosition(e){return d("plugin:window|set_position",{label:this.label,value:e instanceof A?e:new A(e)})}async setFullscreen(e){return d("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return d("plugin:window|set_focus",{label:this.label})}async setIcon(e){return d("plugin:window|set_icon",{label:this.label,value:y(e)})}async setSkipTaskbar(e){return d("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return d("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return d("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return d("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){return d("plugin:window|set_cursor_position",{label:this.label,value:e instanceof A?e:new A(e)})}async setIgnoreCursorEvents(e){return d("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return d("plugin:window|start_dragging",{label:this.label})}async startResizeDragging(e){return d("plugin:window|start_resize_dragging",{label:this.label,value:e})}async setProgressBar(e){return d("plugin:window|set_progress_bar",{label:this.label,value:e})}async setVisibleOnAllWorkspaces(e){return d("plugin:window|set_visible_on_all_workspaces",{label:this.label,value:e})}async setTitleBarStyle(e){return d("plugin:window|set_title_bar_style",{label:this.label,value:e})}async setTheme(e){return d("plugin:window|set_theme",{label:this.label,value:e})}async onResized(e){return this.listen(E.WINDOW_RESIZED,(n=>{n.payload=new m(n.payload),e(n)}))}async onMoved(e){return this.listen(E.WINDOW_MOVED,(n=>{n.payload=new k(n.payload),e(n)}))}async onCloseRequested(e){return this.listen(E.WINDOW_CLOSE_REQUESTED,(async n=>{const t=new ne(n);await e(t),t.isPreventDefault()||await this.destroy()}))}async onDragDropEvent(e){const n=await this.listen(E.DRAG_ENTER,(n=>{e({...n,payload:{type:"enter",paths:n.payload.paths,position:new k(n.payload.position)}})})),t=await this.listen(E.DRAG_OVER,(n=>{e({...n,payload:{type:"over",position:new k(n.payload.position)}})})),i=await this.listen(E.DRAG_DROP,(n=>{e({...n,payload:{type:"drop",paths:n.payload.paths,position:new k(n.payload.position)}})})),r=await this.listen(E.DRAG_LEAVE,(n=>{e({...n,payload:{type:"leave"}})}));return()=>{n(),i(),t(),r()}}async onFocusChanged(e){const n=await this.listen(E.WINDOW_FOCUS,(n=>{e({...n,payload:!0})})),t=await this.listen(E.WINDOW_BLUR,(n=>{e({...n,payload:!1})}));return()=>{n(),t()}}async onScaleChanged(e){return this.listen(E.WINDOW_SCALE_FACTOR_CHANGED,e)}async onThemeChanged(e){return this.listen(E.WINDOW_THEME_CHANGED,e)}}var ae,le;function oe(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:new k(e.position),size:new m(e.size)}}!function(e){e.AppearanceBased="appearanceBased",e.Light="light",e.Dark="dark",e.MediumLight="mediumLight",e.UltraDark="ultraDark",e.Titlebar="titlebar",e.Selection="selection",e.Menu="menu",e.Popover="popover",e.Sidebar="sidebar",e.HeaderView="headerView",e.Sheet="sheet",e.WindowBackground="windowBackground",e.HudWindow="hudWindow",e.FullScreenUI="fullScreenUI",e.Tooltip="tooltip",e.ContentBackground="contentBackground",e.UnderWindowBackground="underWindowBackground",e.UnderPageBackground="underPageBackground",e.Mica="mica",e.Blur="blur",e.Acrylic="acrylic",e.Tabbed="tabbed",e.TabbedDark="tabbedDark",e.TabbedLight="tabbedLight"}(ae||(ae={})),function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"}(le||(le={}));var ue=Object.freeze({__proto__:null,CloseRequestedEvent:ne,get Effect(){return ae},get EffectState(){return le},LogicalPosition:f,LogicalSize:b,PhysicalPosition:k,PhysicalSize:m,get ProgressBarStatus(){return X},get UserAttentionType(){return Y},Window:se,availableMonitors:async function(){return d("plugin:window|available_monitors").then((e=>e.map(oe)))},currentMonitor:async function(){return d("plugin:window|current_monitor").then(oe)},cursorPosition:async function(){return d("plugin:window|cursor_position").then((e=>new k(e)))},getAllWindows:ie,getCurrentWindow:te,monitorFromPoint:async function(e,n){return d("plugin:window|monitor_from_point",{x:e,y:n}).then(oe)},primaryMonitor:async function(){return d("plugin:window|primary_monitor").then(oe)}});function ce(){return new pe(te(),window.__TAURI_INTERNALS__.metadata.currentWebview.label,{skip:!0})}async function de(){return d("plugin:webview|get_all_webviews").then((e=>e.map((e=>new pe(new se(e.windowLabel,{skip:!0}),e.label,{skip:!0})))))}const he=["tauri://created","tauri://error"];class pe{constructor(e,n,t){this.window=e,this.label=n,this.listeners=Object.create(null),(null==t?void 0:t.skip)||d("plugin:webview|create_webview",{windowLabel:e.label,label:n,options:t}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static async getByLabel(e){var n;return null!==(n=(await de()).find((n=>n.label===e)))&&void 0!==n?n:null}static getCurrent(){return ce()}static async getAll(){return de()}async listen(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:I(e,n,{target:{kind:"Webview",label:this.label}})}async once(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:R(e,n,{target:{kind:"Webview",label:this.label}})}async emit(e,n){if(!he.includes(e))return S(e,n);for(const t of this.listeners[e]||[])t({event:e,id:-1,payload:n})}async emitTo(e,n,t){if(!he.includes(n))return L(e,n,t);for(const e of this.listeners[n]||[])e({event:n,id:-1,payload:t})}_handleTauriEvent(e,n){return!!he.includes(e)&&(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0)}async position(){return d("plugin:webview|webview_position",{label:this.label}).then((e=>new k(e)))}async size(){return d("plugin:webview|webview_size",{label:this.label}).then((e=>new m(e)))}async close(){return d("plugin:webview|close",{label:this.label})}async setSize(e){return d("plugin:webview|set_webview_size",{label:this.label,value:e instanceof v?e:new v(e)})}async setPosition(e){return d("plugin:webview|set_webview_position",{label:this.label,value:e instanceof A?e:new A(e)})}async setFocus(){return d("plugin:webview|set_webview_focus",{label:this.label})}async hide(){return d("plugin:webview|webview_hide",{label:this.label})}async show(){return d("plugin:webview|webview_show",{label:this.label})}async setZoom(e){return d("plugin:webview|set_webview_zoom",{label:this.label,value:e})}async reparent(e){return d("plugin:webview|reparent",{label:this.label,window:"string"==typeof e?e:e.label})}async clearAllBrowsingData(){return d("plugin:webview|clear_all_browsing_data")}async onDragDropEvent(e){const n=await this.listen(E.DRAG_ENTER,(n=>{e({...n,payload:{type:"enter",paths:n.payload.paths,position:new k(n.payload.position)}})})),t=await this.listen(E.DRAG_OVER,(n=>{e({...n,payload:{type:"over",position:new k(n.payload.position)}})})),i=await this.listen(E.DRAG_DROP,(n=>{e({...n,payload:{type:"drop",paths:n.payload.paths,position:new k(n.payload.position)}})})),r=await this.listen(E.DRAG_LEAVE,(n=>{e({...n,payload:{type:"leave"}})}));return()=>{n(),i(),t(),r()}}}var we,ye,_e=Object.freeze({__proto__:null,Webview:pe,getAllWebviews:de,getCurrentWebview:ce});function ge(){const e=ce();return new me(e.label,{skip:!0})}async function be(){return d("plugin:window|get_all_windows").then((e=>e.map((e=>new me(e,{skip:!0})))))}class me{constructor(e,n={}){var t;this.label=e,this.listeners=Object.create(null),(null==n?void 0:n.skip)||d("plugin:webview|create_webview_window",{options:{...n,parent:"string"==typeof n.parent?n.parent:null===(t=n.parent)||void 0===t?void 0:t.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static async getByLabel(e){var n;const t=null!==(n=(await be()).find((n=>n.label===e)))&&void 0!==n?n:null;return t?new me(t.label,{skip:!0}):null}static getCurrent(){return ge()}static async getAll(){return be()}async listen(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:I(e,n,{target:{kind:"WebviewWindow",label:this.label}})}async once(e,n){return this._handleTauriEvent(e,n)?()=>{const t=this.listeners[e];t.splice(t.indexOf(n),1)}:R(e,n,{target:{kind:"WebviewWindow",label:this.label}})}}we=me,ye=[se,pe],(Array.isArray(ye)?ye:[ye]).forEach((e=>{Object.getOwnPropertyNames(e.prototype).forEach((n=>{var t;"object"==typeof we.prototype&&we.prototype&&n in we.prototype||Object.defineProperty(we.prototype,n,null!==(t=Object.getOwnPropertyDescriptor(e.prototype,n))&&void 0!==t?t:Object.create(null))}))}));var ve=Object.freeze({__proto__:null,WebviewWindow:me,getAllWebviewWindows:be,getCurrentWebviewWindow:ge});return e.app=g,e.core=p,e.dpi=T,e.event=P,e.image=_,e.menu=$,e.mocks=Q,e.path=Z,e.tray=ee,e.webview=_e,e.webviewWindow=ve,e.window=ue,e}({});window.__TAURI__=__TAURI_IIFE__; diff --git a/crates/tauri/scripts/ipc.js b/crates/tauri/scripts/ipc.js index 28cf331509e6..84013187d55e 100644 --- a/crates/tauri/scripts/ipc.js +++ b/crates/tauri/scripts/ipc.js @@ -88,6 +88,51 @@ return } + // `postMessage` uses `structuredClone` to serialize the data before sending it + // unlike `JSON.stringify`, we can't extend a type with a method similar to `toJSON` + // so that `structuredClone` would use, so until https://github.com/whatwg/html/issues/7428 + // we manually call `toIPC` + function serializeIpcPayload(data) { + // if this value changes, make sure to update it in: + // 1. process-ipc-message-fn.js + // 2. core.ts + const SERIALIZE_TO_IPC_FN = '__TAURI_TO_IPC_KEY__' + + if ( + typeof data === 'object' && + data !== null && + 'constructor' in data && + data.constructor === Array + ) { + return data.map((v) => serializeIpcPayload(v)) + } + + if ( + typeof data === 'object' && + data !== null && + SERIALIZE_TO_IPC_FN in data + ) { + return data[SERIALIZE_TO_IPC_FN]() + } + + if ( + typeof data === 'object' && + data !== null && + 'constructor' in data && + data.constructor === Object + ) { + const acc = {} + Object.entries(data).forEach(([k, v]) => { + acc[k] = serializeIpcPayload(v) + }) + return acc + } + + return data + } + + data.payload = serializeIpcPayload(data.payload) + isolation.frame.contentWindow.postMessage( data, '*' /* todo: set this to the secure origin */ diff --git a/crates/tauri/scripts/process-ipc-message-fn.js b/crates/tauri/scripts/process-ipc-message-fn.js index 42af59df9c1f..2a0ad768b8d9 100644 --- a/crates/tauri/scripts/process-ipc-message-fn.js +++ b/crates/tauri/scripts/process-ipc-message-fn.js @@ -16,21 +16,26 @@ } } else { const data = JSON.stringify(message, (_k, val) => { + // if this value changes, make sure to update it in: + // 1. ipc.js + // 2. core.ts + const SERIALIZE_TO_IPC_FN = '__TAURI_TO_IPC_KEY__' + if (val instanceof Map) { - let o = {} - val.forEach((v, k) => (o[k] = v)) - return o + return Object.fromEntries(val.entries()) } else if (val instanceof Uint8Array) { return Array.from(val) } else if (val instanceof ArrayBuffer) { return Array.from(new Uint8Array(val)) - } else if ( + } else if (typeof val === "object" && val !== null && SERIALIZE_TO_IPC_FN in val) { + return val[SERIALIZE_TO_IPC_FN]() + } else if ( val instanceof Object && '__TAURI_CHANNEL_MARKER__' in val && typeof val.id === 'number' ) { return `__CHANNEL__:${val.id}` - } else { + } else { return val } }) diff --git a/crates/tauri/src/window/mod.rs b/crates/tauri/src/window/mod.rs index 40de751171ff..7f0ffe3cf728 100644 --- a/crates/tauri/src/window/mod.rs +++ b/crates/tauri/src/window/mod.rs @@ -2052,7 +2052,7 @@ tauri::Builder::default() docsrs, doc(cfg(any(target_os = "macos", target_os = "linux", windows))) )] -#[derive(serde::Deserialize)] +#[derive(serde::Deserialize, Debug)] pub struct ProgressBarState { /// The progress bar status. pub status: Option, diff --git a/packages/api/eslint.config.js b/packages/api/eslint.config.js index 71aecc1136eb..803c0178107a 100644 --- a/packages/api/eslint.config.js +++ b/packages/api/eslint.config.js @@ -8,7 +8,7 @@ import prettierConfig from 'eslint-config-prettier' import securityPlugin from 'eslint-plugin-security' import tseslint from 'typescript-eslint' -/** @type {import('eslint').Linter.FlatConfig[]} */ +/** @type {import('eslint').Linter.Config} */ export default [ eslint.configs.recommended, prettierConfig, diff --git a/packages/api/package.json b/packages/api/package.json index 6cc4702fd46f..6187b784ede7 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -40,8 +40,8 @@ "npm-pack": "pnpm build && cd ./dist && npm pack", "npm-publish": "pnpm build && cd ./dist && pnpm publish --access public --loglevel silly --no-git-checks", "ts:check": "tsc --noEmit", - "eslint:check": "eslint src/**.ts", - "eslint:fix": "eslint src/**.ts --fix" + "eslint:check": "eslint src/**/*.ts", + "eslint:fix": "eslint src/**/*.ts --fix" }, "devDependencies": { "@eslint/js": "^9.4.0", diff --git a/packages/api/src/core.ts b/packages/api/src/core.ts index 5986e68abb72..995e5c07b21a 100644 --- a/packages/api/src/core.ts +++ b/packages/api/src/core.ts @@ -9,6 +9,56 @@ * @module */ +/** + * A key to be used to implement a special function + * on your types that define how your type should be serialized + * when passing across the IPC. + * @example + * Given a type in Rust that looks like this + * ```rs + * #[derive(serde::Serialize, serde::Deserialize) + * enum UserId { + * String(String), + * Number(u32), + * } + * ``` + * `UserId::String("id")` would be serialized into `{ String: "id" }` + * and so we need to pass the same structure back to Rust + * ```ts + * import { SERIALIZE_TO_IPC_FN } from "@tauri-apps/api/core" + * + * class UserIdString { + * id + * constructor(id) { + * this.id = id + * } + * + * [SERIALIZE_TO_IPC_FN]() { + * return { String: this.id } + * } + * } + * + * class UserIdNumber { + * id + * constructor(id) { + * this.id = id + * } + * + * [SERIALIZE_TO_IPC_FN]() { + * return { Number: this.id } + * } + * } + * + * + * type UserId = UserIdString | UserIdNumber + * ``` + * + */ +// if this value changes, make sure to update it in: +// 1. ipc.js +// 2. process-ipc-message-fn.js +export const SERIALIZE_TO_IPC_FN = '__TAURI_TO_IPC_KEY__' + /** * Transforms a callback function to a string identifier that can be passed to the backend. * The backend uses the identifier to `eval()` the callback. @@ -80,9 +130,14 @@ class Channel { return this.#onmessage } - toJSON(): string { + [SERIALIZE_TO_IPC_FN]() { return `__CHANNEL__:${this.id}` } + + toJSON(): string { + // eslint-disable-next-line security/detect-object-injection + return this[SERIALIZE_TO_IPC_FN]() + } } class PluginListener { diff --git a/packages/api/src/dpi.ts b/packages/api/src/dpi.ts index e82d7b6add41..8ea676d7dc6a 100644 --- a/packages/api/src/dpi.ts +++ b/packages/api/src/dpi.ts @@ -2,26 +2,48 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT +import { SERIALIZE_TO_IPC_FN } from './core' + /** * A size represented in logical pixels. * * @since 2.0.0 */ class LogicalSize { - type = 'Logical' + readonly type = 'Logical' width: number height: number - constructor(width: number, height: number) { - this.width = width - this.height = height + constructor(width: number, height: number) + constructor(object: { Logical: { width: number; height: number } }) + constructor(object: { width: number; height: number }) + constructor( + ...args: + | [number, number] + | [{ width: number; height: number }] + | [{ Logical: { width: number; height: number } }] + ) { + if (args.length === 1) { + if ('Logical' in args[0]) { + this.width = args[0].Logical.width + this.height = args[0].Logical.height + } else { + this.width = args[0].width + this.height = args[0].height + } + } else { + this.width = args[0] + this.height = args[1] + } } /** * Converts the logical size to a physical one. * @example * ```typescript + * import { LogicalSize } from '@tauri-apps/api/dpi'; * import { getCurrentWindow } from '@tauri-apps/api/window'; + * * const appWindow = getCurrentWindow(); * const factor = await appWindow.scaleFactor(); * const size = new LogicalSize(400, 500); @@ -33,6 +55,18 @@ class LogicalSize { toPhysical(scaleFactor: number): PhysicalSize { return new PhysicalSize(this.width * scaleFactor, this.height * scaleFactor) } + + [SERIALIZE_TO_IPC_FN]() { + return { + width: this.width, + height: this.height + } + } + + toJSON() { + // eslint-disable-next-line security/detect-object-injection + return this[SERIALIZE_TO_IPC_FN]() + } } /** @@ -41,13 +75,31 @@ class LogicalSize { * @since 2.0.0 */ class PhysicalSize { - type = 'Physical' + readonly type = 'Physical' width: number height: number - constructor(width: number, height: number) { - this.width = width - this.height = height + constructor(width: number, height: number) + constructor(object: { Physical: { width: number; height: number } }) + constructor(object: { width: number; height: number }) + constructor( + ...args: + | [number, number] + | [{ width: number; height: number }] + | [{ Physical: { width: number; height: number } }] + ) { + if (args.length === 1) { + if ('Physical' in args[0]) { + this.width = args[0].Physical.width + this.height = args[0].Physical.height + } else { + this.width = args[0].width + this.height = args[0].height + } + } else { + this.width = args[0] + this.height = args[1] + } } /** @@ -57,13 +109,90 @@ class PhysicalSize { * import { getCurrentWindow } from '@tauri-apps/api/window'; * const appWindow = getCurrentWindow(); * const factor = await appWindow.scaleFactor(); - * const size = await appWindow.innerSize(); + * const size = await appWindow.innerSize(); // PhysicalSize * const logical = size.toLogical(factor); * ``` */ toLogical(scaleFactor: number): LogicalSize { return new LogicalSize(this.width / scaleFactor, this.height / scaleFactor) } + + [SERIALIZE_TO_IPC_FN]() { + return { + width: this.width, + height: this.height + } + } + + toJSON() { + // eslint-disable-next-line security/detect-object-injection + return this[SERIALIZE_TO_IPC_FN]() + } +} + +/** + * A size represented either in physical or in logical pixels. + * + * This type is basically a union type of {@linkcode LogicalSize} and {@linkcode PhysicalSize} + * but comes in handy when using `tauri::Size` in Rust as an argument to a command, as this class + * automatically serializes into a valid format so it can be deserialized correctly into `tauri::Size` + * + * So instead of + * ```typescript + * import { invoke } from '@tauri-apps/api/core'; + * import { LogicalSize, PhysicalSize } from '@tauri-apps/api/dpi'; + * + * const size: LogicalSize | PhysicalSize = someFunction(); // where someFunction returns either LogicalSize or PhysicalSize + * const validSize = size instanceof LogicalSize + * ? { Logical: { width: size.width, height: size.height } } + * : { Physical: { width: size.width, height: size.height } } + * await invoke("do_something_with_size", { size: validSize }); + * ``` + * + * You can just use {@linkcode Size} + * ```typescript + * import { invoke } from '@tauri-apps/api/core'; + * import { LogicalSize, PhysicalSize, Size } from '@tauri-apps/api/dpi'; + * + * const size: LogicalSize | PhysicalSize = someFunction(); // where someFunction returns either LogicalSize or PhysicalSize + * const validSize = new Size(size); + * await invoke("do_something_with_size", { size: validSize }); + * ``` + * + * @since 2.1.0 + */ +class Size { + size: LogicalSize | PhysicalSize + + constructor(size: LogicalSize | PhysicalSize) { + this.size = size + } + + toLogical(scaleFactor: number): LogicalSize { + return this.size instanceof LogicalSize + ? this.size + : this.size.toLogical(scaleFactor) + } + + toPhysical(scaleFactor: number): PhysicalSize { + return this.size instanceof PhysicalSize + ? this.size + : this.size.toPhysical(scaleFactor) + } + + [SERIALIZE_TO_IPC_FN]() { + return { + [`${this.size.type}`]: { + width: this.size.width, + height: this.size.height + } + } + } + + toJSON() { + // eslint-disable-next-line security/detect-object-injection + return this[SERIALIZE_TO_IPC_FN]() + } } /** @@ -72,20 +201,40 @@ class PhysicalSize { * @since 2.0.0 */ class LogicalPosition { - type = 'Logical' + readonly type = 'Logical' x: number y: number - constructor(x: number, y: number) { - this.x = x - this.y = y + constructor(x: number, y: number) + constructor(object: { Logical: { x: number; y: number } }) + constructor(object: { x: number; y: number }) + constructor( + ...args: + | [number, number] + | [{ x: number; y: number }] + | [{ Logical: { x: number; y: number } }] + ) { + if (args.length === 1) { + if ('Logical' in args[0]) { + this.x = args[0].Logical.x + this.y = args[0].Logical.y + } else { + this.x = args[0].x + this.y = args[0].y + } + } else { + this.x = args[0] + this.y = args[1] + } } /** * Converts the logical position to a physical one. * @example * ```typescript + * import { LogicalPosition } from '@tauri-apps/api/dpi'; * import { getCurrentWindow } from '@tauri-apps/api/window'; + * * const appWindow = getCurrentWindow(); * const factor = await appWindow.scaleFactor(); * const position = new LogicalPosition(400, 500); @@ -97,6 +246,18 @@ class LogicalPosition { toPhysical(scaleFactor: number): PhysicalPosition { return new PhysicalPosition(this.x * scaleFactor, this.x * scaleFactor) } + + [SERIALIZE_TO_IPC_FN]() { + return { + x: this.x, + y: this.y + } + } + + toJSON() { + // eslint-disable-next-line security/detect-object-injection + return this[SERIALIZE_TO_IPC_FN]() + } } /** @@ -105,29 +266,135 @@ class LogicalPosition { * @since 2.0.0 */ class PhysicalPosition { - type = 'Physical' + readonly type = 'Physical' x: number y: number - constructor(x: number, y: number) { - this.x = x - this.y = y + constructor(x: number, y: number) + constructor(object: { Physical: { x: number; y: number } }) + constructor(object: { x: number; y: number }) + constructor( + ...args: + | [number, number] + | [{ x: number; y: number }] + | [{ Physical: { x: number; y: number } }] + ) { + if (args.length === 1) { + if ('Physical' in args[0]) { + this.x = args[0].Physical.x + this.y = args[0].Physical.y + } else { + this.x = args[0].x + this.y = args[0].y + } + } else { + this.x = args[0] + this.y = args[1] + } } /** * Converts the physical position to a logical one. * @example * ```typescript + * import { PhysicalPosition } from '@tauri-apps/api/dpi'; * import { getCurrentWindow } from '@tauri-apps/api/window'; + * * const appWindow = getCurrentWindow(); * const factor = await appWindow.scaleFactor(); - * const position = await appWindow.innerPosition(); - * const logical = position.toLogical(factor); + * const position = new PhysicalPosition(400, 500); + * const physical = position.toLogical(factor); * ``` + * + * @since 2.0.0 */ toLogical(scaleFactor: number): LogicalPosition { - return new LogicalPosition(this.x / scaleFactor, this.y / scaleFactor) + return new LogicalPosition(this.x / scaleFactor, this.x / scaleFactor) + } + + [SERIALIZE_TO_IPC_FN]() { + return { + x: this.x, + y: this.y + } + } + + toJSON() { + // eslint-disable-next-line security/detect-object-injection + return this[SERIALIZE_TO_IPC_FN]() } } -export { LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize } +/** + * A position represented either in physical or in logical pixels. + * + * This type is basically a union type of {@linkcode LogicalSize} and {@linkcode PhysicalSize} + * but comes in handy when using `tauri::Position` in Rust as an argument to a command, as this class + * automatically serializes into a valid format so it can be deserialized correctly into `tauri::Position` + * + * So instead of + * ```typescript + * import { invoke } from '@tauri-apps/api/core'; + * import { LogicalPosition, PhysicalPosition } from '@tauri-apps/api/dpi'; + * + * const position: LogicalPosition | PhysicalPosition = someFunction(); // where someFunction returns either LogicalPosition or PhysicalPosition + * const validPosition = position instanceof LogicalPosition + * ? { Logical: { x: position.x, y: position.y } } + * : { Physical: { x: position.x, y: position.y } } + * await invoke("do_something_with_position", { position: validPosition }); + * ``` + * + * You can just use {@linkcode Position} + * ```typescript + * import { invoke } from '@tauri-apps/api/core'; + * import { LogicalPosition, PhysicalPosition, Position } from '@tauri-apps/api/dpi'; + * + * const position: LogicalPosition | PhysicalPosition = someFunction(); // where someFunction returns either LogicalPosition or PhysicalPosition + * const validPosition = new Position(position); + * await invoke("do_something_with_position", { position: validPosition }); + * ``` + * + * @since 2.1.0 + */ +class Position { + position: LogicalPosition | PhysicalPosition + + constructor(position: LogicalPosition | PhysicalPosition) { + this.position = position + } + + toLogical(scaleFactor: number): LogicalPosition { + return this.position instanceof LogicalPosition + ? this.position + : this.position.toLogical(scaleFactor) + } + + toPhysical(scaleFactor: number): PhysicalPosition { + return this.position instanceof PhysicalPosition + ? this.position + : this.position.toPhysical(scaleFactor) + } + + [SERIALIZE_TO_IPC_FN]() { + return { + [`${this.position.type}`]: { + x: this.position.x, + y: this.position.y + } + } + } + + toJSON() { + // eslint-disable-next-line security/detect-object-injection + return this[SERIALIZE_TO_IPC_FN]() + } +} + +export { + LogicalPosition, + LogicalSize, + Size, + PhysicalPosition, + PhysicalSize, + Position +} diff --git a/packages/api/src/menu/menu.ts b/packages/api/src/menu/menu.ts index ae16701d438c..0b703c965125 100644 --- a/packages/api/src/menu/menu.ts +++ b/packages/api/src/menu/menu.ts @@ -14,7 +14,7 @@ import { CheckMenuItem } from './checkMenuItem' import { IconMenuItem } from './iconMenuItem' import { PredefinedMenuItem } from './predefinedMenuItem' import { Submenu } from './submenu' -import { type LogicalPosition, PhysicalPosition } from '../dpi' +import { type LogicalPosition, PhysicalPosition, Position } from '../dpi' import { type Window } from '../window' import { invoke } from '../core' import { type ItemKind, MenuItemBase, newMenu } from './base' @@ -244,22 +244,14 @@ export class Menu extends MenuItemBase { * If the position, is provided, it is relative to the window's top-left corner. */ async popup( - at?: PhysicalPosition | LogicalPosition, + at?: PhysicalPosition | LogicalPosition | Position, window?: Window ): Promise { - let atValue = null - if (at) { - atValue = {} as Record - atValue[`${at instanceof PhysicalPosition ? 'Physical' : 'Logical'}`] = { - x: at.x, - y: at.y - } - } return invoke('plugin:menu|popup', { rid: this.rid, kind: this.kind, window: window?.label ?? null, - at: atValue + at: at instanceof Position ? at : at ? new Position(at) : null }) } diff --git a/packages/api/src/menu/submenu.ts b/packages/api/src/menu/submenu.ts index edfd090d1246..ca594a69fdbe 100644 --- a/packages/api/src/menu/submenu.ts +++ b/packages/api/src/menu/submenu.ts @@ -15,6 +15,7 @@ import { invoke } from '../core' import { type LogicalPosition, PhysicalPosition, type Window } from '../window' import { type ItemKind, MenuItemBase, newMenu } from './base' import { type MenuOptions } from './menu' +import { Position } from '../dpi' function itemFromKind([rid, id, kind]: [number, string, ItemKind]): | Submenu @@ -243,19 +244,11 @@ export class Submenu extends MenuItemBase { at?: PhysicalPosition | LogicalPosition, window?: Window ): Promise { - let atValue = null - if (at) { - atValue = {} as Record - atValue[`${at instanceof PhysicalPosition ? 'Physical' : 'Logical'}`] = { - x: at.x, - y: at.y - } - } return invoke('plugin:menu|popup', { rid: this.rid, kind: this.kind, window: window?.label ?? null, - at: atValue + at: at instanceof Position ? at : at ? new Position(at) : null }) } diff --git a/packages/api/src/tray.ts b/packages/api/src/tray.ts index b919d8fc6124..91f748bc5a68 100644 --- a/packages/api/src/tray.ts +++ b/packages/api/src/tray.ts @@ -290,16 +290,9 @@ export class TrayIcon extends Resource { function mapEvent(e: RustTrayIconEvent): TrayIconEvent { const out = e as unknown as TrayIconEvent - out.position = new PhysicalPosition(e.position.x, e.position.y) - - out.rect.position = new PhysicalPosition( - e.rect.position.Physical.x, - e.rect.position.Physical.y - ) - out.rect.size = new PhysicalSize( - e.rect.size.Physical.width, - e.rect.size.Physical.height - ) + out.position = new PhysicalPosition(e.position) + out.rect.position = new PhysicalPosition(e.rect.position) + out.rect.size = new PhysicalSize(e.rect.size) return out } diff --git a/packages/api/src/webview.ts b/packages/api/src/webview.ts index d986de39a946..42a2643d0d05 100644 --- a/packages/api/src/webview.ts +++ b/packages/api/src/webview.ts @@ -18,6 +18,7 @@ import { PhysicalPosition, PhysicalSize } from './dpi' import type { LogicalPosition, LogicalSize } from './dpi' +import { Position, Size } from './dpi' import type { EventName, EventCallback, UnlistenFn } from './event' import { TauriEvent, @@ -361,7 +362,7 @@ class Webview { async position(): Promise { return invoke<{ x: number; y: number }>('plugin:webview|webview_position', { label: this.label - }).then(({ x, y }) => new PhysicalPosition(x, y)) + }).then((p) => new PhysicalPosition(p)) } /** @@ -381,7 +382,7 @@ class Webview { { label: this.label } - ).then(({ width, height }) => new PhysicalSize(width, height)) + ).then((s) => new PhysicalSize(s)) } // Setters @@ -413,22 +414,10 @@ class Webview { * @param size The logical or physical size. * @returns A promise indicating the success or failure of the operation. */ - async setSize(size: LogicalSize | PhysicalSize): Promise { - if (!size || (size.type !== 'Logical' && size.type !== 'Physical')) { - throw new Error( - 'the `size` argument must be either a LogicalSize or a PhysicalSize instance' - ) - } - - const value = {} as Record - value[`${size.type}`] = { - width: size.width, - height: size.height - } - + async setSize(size: LogicalSize | PhysicalSize | Size): Promise { return invoke('plugin:webview|set_webview_size', { label: this.label, - value + value: size instanceof Size ? size : new Size(size) }) } @@ -444,26 +433,11 @@ class Webview { * @returns A promise indicating the success or failure of the operation. */ async setPosition( - position: LogicalPosition | PhysicalPosition + position: LogicalPosition | PhysicalPosition | Position ): Promise { - if ( - !position || - (position.type !== 'Logical' && position.type !== 'Physical') - ) { - throw new Error( - 'the `position` argument must be either a LogicalPosition or a PhysicalPosition instance' - ) - } - - const value = {} as Record - value[`${position.type}`] = { - x: position.x, - y: position.y - } - return invoke('plugin:webview|set_webview_position', { label: this.label, - value + value: position instanceof Position ? position : new Position(position) }) } @@ -603,7 +577,7 @@ class Webview { payload: { type: 'enter', paths: event.payload.paths, - position: mapPhysicalPosition(event.payload.position) + position: new PhysicalPosition(event.payload.position) } }) } @@ -616,7 +590,7 @@ class Webview { ...event, payload: { type: 'over', - position: mapPhysicalPosition(event.payload.position) + position: new PhysicalPosition(event.payload.position) } }) } @@ -630,7 +604,7 @@ class Webview { payload: { type: 'drop', paths: event.payload.paths, - position: mapPhysicalPosition(event.payload.position) + position: new PhysicalPosition(event.payload.position) } }) } @@ -652,10 +626,6 @@ class Webview { } } -function mapPhysicalPosition(m: PhysicalPosition): PhysicalPosition { - return new PhysicalPosition(m.x, m.y) -} - /** * Configuration for the webview to create. * diff --git a/packages/api/src/window.ts b/packages/api/src/window.ts index c242e3dd2160..037f06e6523d 100644 --- a/packages/api/src/window.ts +++ b/packages/api/src/window.ts @@ -20,7 +20,9 @@ import { LogicalPosition, LogicalSize, PhysicalPosition, - PhysicalSize + PhysicalSize, + Position, + Size } from './dpi' import type { Event, EventName, EventCallback, UnlistenFn } from './event' import { @@ -530,7 +532,7 @@ class Window { async innerPosition(): Promise { return invoke<{ x: number; y: number }>('plugin:window|inner_position', { label: this.label - }).then(({ x, y }) => new PhysicalPosition(x, y)) + }).then((p) => new PhysicalPosition(p)) } /** @@ -546,7 +548,7 @@ class Window { async outerPosition(): Promise { return invoke<{ x: number; y: number }>('plugin:window|outer_position', { label: this.label - }).then(({ x, y }) => new PhysicalPosition(x, y)) + }).then((p) => new PhysicalPosition(p)) } /** @@ -566,7 +568,7 @@ class Window { { label: this.label } - ).then(({ width, height }) => new PhysicalSize(width, height)) + ).then((s) => new PhysicalSize(s)) } /** @@ -586,7 +588,7 @@ class Window { { label: this.label } - ).then(({ width, height }) => new PhysicalSize(width, height)) + ).then((s) => new PhysicalSize(s)) } /** @@ -1268,22 +1270,10 @@ class Window { * @param size The logical or physical inner size. * @returns A promise indicating the success or failure of the operation. */ - async setSize(size: LogicalSize | PhysicalSize): Promise { - if (!size || (size.type !== 'Logical' && size.type !== 'Physical')) { - throw new Error( - 'the `size` argument must be either a LogicalSize or a PhysicalSize instance' - ) - } - - const value = {} as Record - value[`${size.type}`] = { - width: size.width, - height: size.height - } - + async setSize(size: LogicalSize | PhysicalSize | Size): Promise { return invoke('plugin:window|set_size', { label: this.label, - value + value: size instanceof Size ? size : new Size(size) }) } @@ -1299,26 +1289,11 @@ class Window { * @returns A promise indicating the success or failure of the operation. */ async setMinSize( - size: LogicalSize | PhysicalSize | null | undefined + size: LogicalSize | PhysicalSize | Size | null | undefined ): Promise { - if (size && size.type !== 'Logical' && size.type !== 'Physical') { - throw new Error( - 'the `size` argument must be either a LogicalSize or a PhysicalSize instance' - ) - } - - let value = null as Record | null - if (size) { - value = {} - value[`${size.type}`] = { - width: size.width, - height: size.height - } - } - return invoke('plugin:window|set_min_size', { label: this.label, - value + value: size instanceof Size ? size : size ? new Size(size) : null }) } @@ -1334,26 +1309,11 @@ class Window { * @returns A promise indicating the success or failure of the operation. */ async setMaxSize( - size: LogicalSize | PhysicalSize | null | undefined + size: LogicalSize | PhysicalSize | Size | null | undefined ): Promise { - if (size && size.type !== 'Logical' && size.type !== 'Physical') { - throw new Error( - 'the `size` argument must be either a LogicalSize or a PhysicalSize instance' - ) - } - - let value = null as Record | null - if (size) { - value = {} - value[`${size.type}`] = { - width: size.width, - height: size.height - } - } - return invoke('plugin:window|set_max_size', { label: this.label, - value + value: size instanceof Size ? size : size ? new Size(size) : null }) } @@ -1398,26 +1358,11 @@ class Window { * @returns A promise indicating the success or failure of the operation. */ async setPosition( - position: LogicalPosition | PhysicalPosition + position: LogicalPosition | PhysicalPosition | Position ): Promise { - if ( - !position || - (position.type !== 'Logical' && position.type !== 'Physical') - ) { - throw new Error( - 'the `position` argument must be either a LogicalPosition or a PhysicalPosition instance' - ) - } - - const value = {} as Record - value[`${position.type}`] = { - x: position.x, - y: position.y - } - return invoke('plugin:window|set_position', { label: this.label, - value + value: position instanceof Position ? position : new Position(position) }) } @@ -1584,26 +1529,11 @@ class Window { * @returns A promise indicating the success or failure of the operation. */ async setCursorPosition( - position: LogicalPosition | PhysicalPosition + position: LogicalPosition | PhysicalPosition | Position ): Promise { - if ( - !position || - (position.type !== 'Logical' && position.type !== 'Physical') - ) { - throw new Error( - 'the `position` argument must be either a LogicalPosition or a PhysicalPosition instance' - ) - } - - const value = {} as Record - value[`${position.type}`] = { - x: position.x, - y: position.y - } - return invoke('plugin:window|set_cursor_position', { label: this.label, - value + value: position instanceof Position ? position : new Position(position) }) } @@ -1751,7 +1681,7 @@ class Window { */ async onResized(handler: EventCallback): Promise { return this.listen(TauriEvent.WINDOW_RESIZED, (e) => { - e.payload = mapPhysicalSize(e.payload) + e.payload = new PhysicalSize(e.payload) handler(e) }) } @@ -1775,7 +1705,7 @@ class Window { */ async onMoved(handler: EventCallback): Promise { return this.listen(TauriEvent.WINDOW_MOVED, (e) => { - e.payload = mapPhysicalPosition(e.payload) + e.payload = new PhysicalPosition(e.payload) handler(e) }) } @@ -1853,7 +1783,7 @@ class Window { payload: { type: 'enter', paths: event.payload.paths, - position: mapPhysicalPosition(event.payload.position) + position: new PhysicalPosition(event.payload.position) } }) } @@ -1866,7 +1796,7 @@ class Window { ...event, payload: { type: 'over', - position: mapPhysicalPosition(event.payload.position) + position: new PhysicalPosition(event.payload.position) } }) } @@ -1880,7 +1810,7 @@ class Window { payload: { type: 'drop', paths: event.payload.paths, - position: mapPhysicalPosition(event.payload.position) + position: new PhysicalPosition(event.payload.position) } }) } @@ -2310,19 +2240,11 @@ function mapMonitor(m: Monitor | null): Monitor | null { : { name: m.name, scaleFactor: m.scaleFactor, - position: mapPhysicalPosition(m.position), - size: mapPhysicalSize(m.size) + position: new PhysicalPosition(m.position), + size: new PhysicalSize(m.size) } } -function mapPhysicalPosition(m: PhysicalPosition): PhysicalPosition { - return new PhysicalPosition(m.x, m.y) -} - -function mapPhysicalSize(m: PhysicalSize): PhysicalSize { - return new PhysicalSize(m.width, m.height) -} - /** * Returns the monitor on which the window currently resides. * Returns `null` if current monitor can't be detected. @@ -2402,7 +2324,7 @@ async function availableMonitors(): Promise { */ async function cursorPosition(): Promise { return invoke('plugin:window|cursor_position').then( - mapPhysicalPosition + (v) => new PhysicalPosition(v) ) }