Răsfoiți Sursa

refactor(core): split endpoint API matching into modules (#1219)

Lucas Fernandes Nogueira 4 ani în urmă
părinte
comite
77fc730671
43 a modificat fișierele cu 4515 adăugiri și 1108 ștergeri
  1. 3 1
      api/package.json
  2. 1 1
      api/rollup.config.js
  3. 2 2
      api/src/bundle.ts
  4. 4 1
      api/src/cli.ts
  5. 10 4
      api/src/dialog.ts
  6. 13 7
      api/src/event.ts
  7. 64 34
      api/src/fs.ts
  8. 5 2
      api/src/http.ts
  9. 4 1
      api/src/notification.ts
  10. 114 57
      api/src/path.ts
  11. 0 25
      api/src/process.ts
  12. 43 0
      api/src/shell.ts
  13. 6 15
      api/src/window.ts
  14. 33 15
      cli/core/src/templates/tauri.js
  15. 1 1
      cli/tauri.js/templates/src-tauri/src/main.rs
  16. 1 1
      cli/tauri.js/test/jest/fixtures/app/src-tauri/src/main.rs
  17. 1 1
      tauri/examples/api/src-tauri/src/main.rs
  18. 0 0
      tauri/examples/communication/dist/__tauri.js
  19. 298 311
      tauri/examples/communication/dist/index.html
  20. 1 1
      tauri/examples/communication/dist/window.js
  21. 2 1
      tauri/examples/communication/src-tauri/Cargo.lock
  22. 1 1
      tauri/examples/communication/src-tauri/src/main.rs
  23. 0 0
      tauri/examples/multiwindow/dist/__tauri.js
  24. 3089 0
      tauri/examples/multiwindow/src-tauri/Cargo.lock
  25. 1 1
      tauri/examples/multiwindow/src-tauri/Cargo.toml
  26. 3 3
      tauri/src/app.rs
  27. 8 5
      tauri/src/app/runner.rs
  28. 70 328
      tauri/src/endpoints.rs
  29. 0 8
      tauri/src/endpoints/browser.rs
  30. 35 0
      tauri/src/endpoints/cli.rs
  31. 0 228
      tauri/src/endpoints/cmd.rs
  32. 121 6
      tauri/src/endpoints/dialog.rs
  33. 64 0
      tauri/src/endpoints/event.rs
  34. 276 2
      tauri/src/endpoints/file_system.rs
  35. 34 0
      tauri/src/endpoints/http.rs
  36. 49 0
      tauri/src/endpoints/internal.rs
  37. 63 1
      tauri/src/endpoints/notification.rs
  38. 0 19
      tauri/src/endpoints/path.rs
  39. 0 20
      tauri/src/endpoints/salt.rs
  40. 65 0
      tauri/src/endpoints/shell.rs
  41. 25 0
      tauri/src/endpoints/window.rs
  42. 3 3
      tauri/src/error.rs
  43. 2 2
      tauri/src/plugin.rs

+ 3 - 1
api/package.json

@@ -9,10 +9,12 @@
     "./dialog": "./dist/dialog.js",
     "./event": "./dist/event.js",
     "./fs": "./dist/fs.js",
+    "./path": "./dist/path.js",
     "./http": "./dist/http.js",
     "./notification": "./dist/notification.js",
     "./tauri": "./dist/tauri.js",
-    "./window": "./dist/window.js"
+    "./window": "./dist/window.js",
+    "./shell": "./dist/shell.js"
   },
   "funding": {
     "type": "opencollective",

+ 1 - 1
api/rollup.config.js

@@ -16,7 +16,7 @@ export default [
       event: './src/event.ts',
       http: './src/http.ts',
       index: './src/index.ts',
-      process: './src/process.ts',
+      shell: './src/shell.ts',
       tauri: './src/tauri.ts',
       window: './src/window.ts',
       cli: './src/cli.ts',

+ 2 - 2
api/src/bundle.ts

@@ -5,7 +5,7 @@ import * as event from './event'
 import * as fs from './fs'
 import * as path from './path'
 import http from './http'
-import * as process from './process'
+import * as shell from './shell'
 import * as tauri from './tauri'
 import * as window from './window'
 import * as notification from './notification'
@@ -17,7 +17,7 @@ export {
   fs,
   path,
   http,
-  process,
+  shell,
   tauri,
   window,
   notification

+ 4 - 1
api/src/cli.ts

@@ -28,7 +28,10 @@ export interface CliMatches {
  */
 async function getMatches(): Promise<CliMatches> {
   return await promisified<CliMatches>({
-    cmd: 'cliMatches'
+    module: 'Cli',
+    message: {
+      cmd: 'cliMatches'
+    }
   })
 }
 

+ 10 - 4
api/src/dialog.ts

@@ -30,8 +30,11 @@ async function open(
   }
 
   return await promisified({
-    cmd: 'openDialog',
-    options
+    module: 'Dialog',
+    message: {
+      cmd: 'openDialog',
+      options
+    }
   })
 }
 
@@ -49,8 +52,11 @@ async function save(options: SaveDialogOptions = {}): Promise<string> {
   }
 
   return await promisified({
-    cmd: 'saveDialog',
-    options
+    module: 'Dialog',
+    message: {
+      cmd: 'saveDialog',
+      options
+    }
   })
 }
 

+ 13 - 7
api/src/event.ts

@@ -19,10 +19,13 @@ function listen<T>(
   once = false
 ): void {
   invoke({
-    cmd: 'listen',
-    event,
-    handler: transformCallback(handler, once),
-    once
+    module: 'Event',
+    message: {
+      cmd: 'listen',
+      event,
+      handler: transformCallback(handler, once),
+      once
+    }
   })
 }
 
@@ -34,9 +37,12 @@ function listen<T>(
  */
 function emit(event: string, payload?: string): void {
   invoke({
-    cmd: 'emit',
-    event,
-    payload
+    module: 'Event',
+    message: {
+      cmd: 'emit',
+      event,
+      payload
+    }
   })
 }
 

+ 64 - 34
api/src/fs.ts

@@ -62,9 +62,12 @@ async function readTextFile(
   options: FsOptions = {}
 ): Promise<string> {
   return await promisified<string>({
-    cmd: 'readTextFile',
-    path: filePath,
-    options
+    module: 'Fs',
+    message: {
+      cmd: 'readTextFile',
+      path: filePath,
+      options
+    }
   })
 }
 
@@ -81,9 +84,12 @@ async function readBinaryFile(
   options: FsOptions = {}
 ): Promise<number[]> {
   return await promisified<number[]>({
-    cmd: 'readBinaryFile',
-    path: filePath,
-    options
+    module: 'Fs',
+    message: {
+      cmd: 'readBinaryFile',
+      path: filePath,
+      options
+    }
   })
 }
 
@@ -109,10 +115,13 @@ async function writeFile(
   }
 
   return await promisified({
-    cmd: 'writeFile',
-    path: file.path,
-    contents: file.contents,
-    options
+    module: 'Fs',
+    message: {
+      cmd: 'writeFile',
+      path: file.path,
+      contents: file.contents,
+      options
+    }
   })
 }
 
@@ -171,10 +180,13 @@ async function writeBinaryFile(
   }
 
   return await promisified({
-    cmd: 'writeBinaryFile',
-    path: file.path,
-    contents: arrayBufferToBase64(file.contents),
-    options
+    module: 'Fs',
+    message: {
+      cmd: 'writeBinaryFile',
+      path: file.path,
+      contents: arrayBufferToBase64(file.contents),
+      options
+    }
   })
 }
 
@@ -192,9 +204,12 @@ async function readDir(
   options: FsDirOptions = {}
 ): Promise<FileEntry[]> {
   return await promisified({
-    cmd: 'readDir',
-    path: dir,
-    options
+    module: 'Fs',
+    message: {
+      cmd: 'readDir',
+      path: dir,
+      options
+    }
   })
 }
 
@@ -214,9 +229,12 @@ async function createDir(
   options: FsDirOptions = {}
 ): Promise<void> {
   return await promisified({
-    cmd: 'createDir',
-    path: dir,
-    options
+    module: 'Fs',
+    message: {
+      cmd: 'createDir',
+      path: dir,
+      options
+    }
   })
 }
 
@@ -235,9 +253,12 @@ async function removeDir(
   options: FsDirOptions = {}
 ): Promise<void> {
   return await promisified({
-    cmd: 'removeDir',
-    path: dir,
-    options
+    module: 'Fs',
+    message: {
+      cmd: 'removeDir',
+      path: dir,
+      options
+    }
   })
 }
 
@@ -256,10 +277,13 @@ async function copyFile(
   options: FsOptions = {}
 ): Promise<void> {
   return await promisified({
-    cmd: 'copyFile',
-    source,
-    destination,
-    options
+    module: 'Fs',
+    message: {
+      cmd: 'copyFile',
+      source,
+      destination,
+      options
+    }
   })
 }
 
@@ -276,9 +300,12 @@ async function removeFile(
   options: FsOptions = {}
 ): Promise<void> {
   return await promisified({
-    cmd: 'removeFile',
-    path: file,
-    options: options
+    module: 'Fs',
+    message: {
+      cmd: 'removeFile',
+      path: file,
+      options: options
+    }
   })
 }
 
@@ -297,10 +324,13 @@ async function renameFile(
   options: FsOptions = {}
 ): Promise<void> {
   return await promisified({
-    cmd: 'renameFile',
-    oldPath,
-    newPath,
-    options
+    module: 'Fs',
+    message: {
+      cmd: 'renameFile',
+      oldPath,
+      newPath,
+      options
+    }
   })
 }
 

+ 5 - 2
api/src/http.ts

@@ -52,8 +52,11 @@ export type PartialOptions = Omit<HttpOptions, 'method' | 'url'>
  */
 async function request<T>(options: HttpOptions): Promise<T> {
   return await promisified({
-    cmd: 'httpRequest',
-    options: options
+    module: 'Http',
+    message: {
+      cmd: 'httpRequest',
+      options: options
+    }
   })
 }
 

+ 4 - 1
api/src/notification.ts

@@ -14,7 +14,10 @@ async function isPermissionGranted(): Promise<boolean | null> {
     return await Promise.resolve(window.Notification.permission === 'granted')
   }
   return await promisified({
-    cmd: 'isNotificationPermissionGranted'
+    module: 'Notification',
+    message: {
+      cmd: 'isNotificationPermissionGranted'
+    }
   })
 }
 

+ 114 - 57
api/src/path.ts

@@ -8,9 +8,12 @@ import { BaseDirectory } from './fs'
  */
 async function appDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.App
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.App
+    }
   })
 }
 
@@ -21,9 +24,12 @@ async function appDir(): Promise<string> {
  */
 async function audioDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Audio
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Audio
+    }
   })
 }
 
@@ -34,9 +40,12 @@ async function audioDir(): Promise<string> {
  */
 async function cacheDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Cache
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Cache
+    }
   })
 }
 
@@ -47,9 +56,12 @@ async function cacheDir(): Promise<string> {
  */
 async function configDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Config
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Config
+    }
   })
 }
 
@@ -60,9 +72,12 @@ async function configDir(): Promise<string> {
  */
 async function dataDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Data
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Data
+    }
   })
 }
 
@@ -73,9 +88,12 @@ async function dataDir(): Promise<string> {
  */
 async function desktopDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Desktop
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Desktop
+    }
   })
 }
 
@@ -86,9 +104,12 @@ async function desktopDir(): Promise<string> {
  */
 async function documentDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Document
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Document
+    }
   })
 }
 
@@ -99,9 +120,12 @@ async function documentDir(): Promise<string> {
  */
 async function downloadDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Download
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Download
+    }
   })
 }
 
@@ -112,9 +136,12 @@ async function downloadDir(): Promise<string> {
  */
 async function executableDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Executable
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Executable
+    }
   })
 }
 
@@ -125,9 +152,12 @@ async function executableDir(): Promise<string> {
  */
 async function fontDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Font
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Font
+    }
   })
 }
 
@@ -138,9 +168,12 @@ async function fontDir(): Promise<string> {
  */
 async function homeDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Home
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Home
+    }
   })
 }
 
@@ -151,9 +184,12 @@ async function homeDir(): Promise<string> {
  */
 async function localDataDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.LocalData
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.LocalData
+    }
   })
 }
 
@@ -164,9 +200,12 @@ async function localDataDir(): Promise<string> {
  */
 async function pictureDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Picture
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Picture
+    }
   })
 }
 
@@ -177,9 +216,12 @@ async function pictureDir(): Promise<string> {
  */
 async function publicDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Public
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Public
+    }
   })
 }
 
@@ -190,9 +232,12 @@ async function publicDir(): Promise<string> {
  */
 async function resourceDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Resource
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Resource
+    }
   })
 }
 
@@ -203,9 +248,12 @@ async function resourceDir(): Promise<string> {
  */
 async function runtimeDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Runtime
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Runtime
+    }
   })
 }
 
@@ -216,9 +264,12 @@ async function runtimeDir(): Promise<string> {
  */
 async function templateDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Template
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Template
+    }
   })
 }
 
@@ -229,9 +280,12 @@ async function templateDir(): Promise<string> {
  */
 async function videoDir(): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path: '',
-    directory: BaseDirectory.Video
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path: '',
+      directory: BaseDirectory.Video
+    }
   })
 }
 
@@ -245,9 +299,12 @@ async function resolvePath(
   directory: BaseDirectory
 ): Promise<string> {
   return await promisified<string>({
-    cmd: 'resolvePath',
-    path,
-    directory
+    module: 'Fs',
+    message: {
+      cmd: 'resolvePath',
+      path,
+      directory
+    }
   })
 }
 

+ 0 - 25
api/src/process.ts

@@ -1,25 +0,0 @@
-import { promisified } from './tauri'
-
-/**
- * spawns a process
- *
- * @param command the name of the cmd to execute e.g. 'mkdir' or 'node'
- * @param [args] command args
- * @return promise resolving to the stdout text
- */
-async function execute(
-  command: string,
-  args?: string | string[]
-): Promise<string> {
-  if (typeof args === 'object') {
-    Object.freeze(args)
-  }
-
-  return await promisified({
-    cmd: 'execute',
-    command,
-    args: typeof args === 'string' ? [args] : args
-  })
-}
-
-export { execute }

+ 43 - 0
api/src/shell.ts

@@ -0,0 +1,43 @@
+import { promisified, invoke } from './tauri'
+
+/**
+ * spawns a process
+ *
+ * @param command the name of the cmd to execute e.g. 'mkdir' or 'node'
+ * @param [args] command args
+ * @return promise resolving to the stdout text
+ */
+async function execute(
+  command: string,
+  args?: string | string[]
+): Promise<string> {
+  if (typeof args === 'object') {
+    Object.freeze(args)
+  }
+
+  return await promisified({
+    module: 'Shell',
+    message: {
+      cmd: 'execute',
+      command,
+      args: typeof args === 'string' ? [args] : args
+    }
+  })
+}
+
+/**
+ * opens an URL on the user default browser
+ *
+ * @param url the URL to open
+ */
+function open(url: string): void {
+  invoke({
+    module: 'Shell',
+    message: {
+      cmd: 'open',
+      uri: url
+    }
+  })
+}
+
+export { execute, open }

+ 6 - 15
api/src/window.ts

@@ -7,21 +7,12 @@ import { invoke } from './tauri'
  */
 function setTitle(title: string): void {
   invoke({
-    cmd: 'setTitle',
-    title
+    module: 'Window',
+    message: {
+      cmd: 'setTitle',
+      title
+    }
   })
 }
 
-/**
- * opens an URL on the user default browser
- *
- * @param url the URL to open
- */
-function open(url: string): void {
-  invoke({
-    cmd: 'open',
-    uri: url
-  })
-}
-
-export { setTitle, open }
+export { setTitle }

+ 33 - 15
cli/core/src/templates/tauri.js

@@ -158,8 +158,11 @@ if (!String.prototype.startsWith) {
               target.target === '_blank'
             ) {
               window.__TAURI_INVOKE_HANDLER__(JSON.stringify({
-                cmd: 'open',
-                uri: target.href
+                module: 'Shell',
+                message: {
+                  cmd: 'open',
+                  uri: target.href
+                }
               }))
               e.preventDefault()
             }
@@ -195,7 +198,10 @@ if (!String.prototype.startsWith) {
       return Promise.resolve(window.Notification.permission === 'granted')
     }
     return window.__TAURI__.promisified({
-      cmd: 'isNotificationPermissionGranted'
+      module: 'Notification',
+      message: {
+        cmd: 'isNotificationPermissionGranted'
+      }
     })
   }
 
@@ -208,7 +214,10 @@ if (!String.prototype.startsWith) {
   function requestPermission() {
     return window.__TAURI__
       .promisified({
-        cmd: 'requestNotificationPermission'
+        module: 'Notification',
+        message: {
+          cmd: 'requestNotificationPermission'
+        }
       })
       .then(function (permission) {
         setNotificationPermission(permission)
@@ -224,13 +233,16 @@ if (!String.prototype.startsWith) {
     isPermissionGranted().then(function (permission) {
       if (permission) {
         return window.__TAURI__.promisified({
-          cmd: 'notification',
-          options:
-            typeof options === 'string'
-              ? {
-                  title: options
-                }
-              : options
+          module: 'Notification',
+          message: {
+            cmd: 'notification',
+            options:
+              typeof options === 'string'
+                ? {
+                    title: options
+                  }
+                : options
+          }
         })
       }
     })
@@ -270,15 +282,21 @@ if (!String.prototype.startsWith) {
 
   window.alert = function (message) {
     window.__TAURI_INVOKE_HANDLER__(JSON.stringify({
-      cmd: 'messageDialog',
-      message: message
+      module: 'Dialog',
+      message: {
+        cmd: 'messageDialog',
+        message: message
+      }
     }))
   }
 
   window.confirm = function (message) {
     return window.__TAURI__.promisified({
-      cmd: 'askDialog',
-      message: message
+      module: 'Dialog',
+      message: {
+        cmd: 'askDialog',
+        message: message
+      }
     })
   }
 })()

+ 1 - 1
cli/tauri.js/templates/src-tauri/src/main.rs

@@ -13,7 +13,7 @@ fn main() {
     .invoke_handler(|_webview, arg| async move {
       use cmd::Cmd::*;
       match serde_json::from_str(&arg) {
-        Err(e) => Err(e.to_string()),
+        Err(e) => Err(e.into()),
         Ok(command) => {
           match command {
             // definitions for your custom commands from Cmd here

+ 1 - 1
cli/tauri.js/test/jest/fixtures/app/src-tauri/src/main.rs

@@ -24,7 +24,7 @@ fn main() {
     .invoke_handler(|webview_manager, arg| async move {
       use cmd::Cmd::*;
       match serde_json::from_str(&arg) {
-        Err(e) => Err(e.to_string()),
+        Err(e) => Err(e.into()),
         Ok(command) => {
           match command {
             // definitions for your custom commands from Cmd here

+ 1 - 1
tauri/examples/api/src-tauri/src/main.rs

@@ -34,7 +34,7 @@ fn main() {
     .invoke_handler(|webview_manager, arg| async move {
       use cmd::Cmd::*;
       match serde_json::from_str(&arg) {
-        Err(e) => Err(e.to_string()),
+        Err(e) => Err(e.into()),
         Ok(command) => {
           match command {
             LogOperation { event, payload } => {

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
tauri/examples/communication/dist/__tauri.js


+ 298 - 311
tauri/examples/communication/dist/index.html

@@ -1,330 +1,317 @@
 <!DOCTYPE html>
 <html>
-  <head>
-    <style>
-      * {
-        font-family: Arial, Helvetica, sans-serif;
-      }
-
-      body {
-        background: #889;
-      }
-
-      .logo-container {
-        width: 95%;
-        margin: 0px auto;
-        overflow: hidden;
-      }
-
-      .logo-link {
-        font-weight: 700;
-        position: absolute;
-        top: 150px;
-        right: 10px;
-      }
-
-      .logo {
-        width: 32px;
-        height: 32px;
-        cursor: pointer;
-        position: fixed;
-        z-index: 10;
-        top: 7px;
-        right: 10px;
-      }
-
-      #response {
-        position: absolute;
-        left: 10px;
-        right: 10px;
-        top: 440px;
-        min-height: 110px;
-        background: #aab;
-        font-family: "Courier New", Courier, monospace;
-        font-size: 12px;
-        word-wrap: break-word;
-        padding: 5px;
-        border-radius: 5px;
-        overflow-y: auto;
-      }
-
-      input,
-      select {
-        background: white;
-        font-family: system-ui, sans-serif;
-        border: 0;
-        border-radius: 0.25rem;
-        font-size: 1rem;
-        line-height: 1.2;
-        padding: 0.25rem 0.5rem;
-        margin: 0.25rem;
-      }
-
-      button:hover,
-      button:focus {
-        background: #0053ba;
-      }
-
-      button:focus {
-        outline: 1px solid #fff;
-        outline-offset: -4px;
-      }
 
-      button:active {
-        transform: scale(0.99);
-      }
-
-      .button {
-        border: 0;
-        border-radius: 0.25rem;
-        background: #1e88e5;
-        color: white;
-        font-family: system-ui, sans-serif;
-        font-size: 1rem;
-        line-height: 1.2;
-        white-space: nowrap;
-        text-decoration: none;
-        padding: 0.25rem 0.5rem;
-        margin: 0.25rem;
-        cursor: pointer;
-      }
-
-      .bottom {
-        position: fixed;
-        bottom: 0;
-        left: 0;
-        text-align: center;
-        width: 100%;
-        padding: 5px;
-        background: #333;
-        color: #eef;
-      }
-
-      .dark-link {
-        color: white;
-        text-decoration: none !important;
-      }
-
-      .tabs-container {
-        position: fixed;
-        height: 400px;
-        top: 20px;
-        left: 10px;
-        right: 10px;
-        z-index: 9;
-      }
-
-      .tabs {
-        position: relative;
-        min-height: 400px;
-        clear: both;
-      }
-
-      .tab {
-        float: left;
-      }
-
-      .tab > label {
-        background: #eee;
-        padding: 10px;
-        border: 1px solid transparent;
-        margin-left: -1px;
-        position: relative;
-        left: 1px;
-      }
-
-      .tabs > .tabber {
-        border-top-left-radius: 5px;
-      }
-
-      .tabs > .tabber ~ .tabber {
-        border-top-left-radius: none;
-      }
-
-      .tab [type="radio"] {
-        display: none;
-      }
-
-      .content {
-        position: absolute;
-        top: 28px;
-        left: 0;
-        background: #bbc;
-        right: 0;
-        bottom: 0;
-        padding: 20px;
-        border: 1px solid transparent;
-        border-top-right-radius: 5px;
-        border-bottom-left-radius: 5px;
-        border-bottom-right-radius: 5px;
-      }
-
-      [type="radio"]:checked ~ label {
-        background: #bbc;
-        border-bottom: 1px solid transparent;
-        z-index: 2;
-      }
-
-      [type="radio"]:checked ~ label ~ .content {
-        z-index: 1;
-      }
-    </style>
-  </head>
-
-  <body>
-    <div class="logo-container">
-      <img src="icon.png" class="logo" />
-    </div>
-
-    <div class="tabs-container">
-      <div class="tabs">
-        <div class="tab">
-          <input type="radio" id="tab-1" name="tab-group-1" checked />
-          <label class="tabber" for="tab-1">Messages</label>
-          <div class="content">
-            <button class="button" id="log">Call Log API</button>
-            <button class="button" id="request">
-              Call Request (async) API
-            </button>
-            <button class="button" id="event">Send event to Rust</button>
-            <button class="button" id="notification">
-              Send test notification
-            </button>
-
-            <div style="margin-top: 24px">
-              <input id="title" value="Awesome Tauri Example!" />
-              <button class="button" id="set-title">Set title</button>
-            </div>
+<head>
+  <style>
+    * {
+      font-family: Arial, Helvetica, sans-serif;
+    }
+
+    body {
+      background: #889;
+    }
+
+    .logo-container {
+      width: 95%;
+      margin: 0px auto;
+      overflow: hidden;
+    }
+
+    .logo-link {
+      font-weight: 700;
+      position: absolute;
+      top: 150px;
+      right: 10px;
+    }
+
+    .logo {
+      width: 32px;
+      height: 32px;
+      cursor: pointer;
+      position: fixed;
+      z-index: 10;
+      top: 7px;
+      right: 10px;
+    }
+
+    #response {
+      position: absolute;
+      left: 10px;
+      right: 10px;
+      top: 440px;
+      min-height: 110px;
+      background: #aab;
+      font-family: "Courier New", Courier, monospace;
+      font-size: 12px;
+      word-wrap: break-word;
+      padding: 5px;
+      border-radius: 5px;
+      overflow-y: auto;
+    }
+
+    input,
+    select {
+      background: white;
+      font-family: system-ui, sans-serif;
+      border: 0;
+      border-radius: 0.25rem;
+      font-size: 1rem;
+      line-height: 1.2;
+      padding: 0.25rem 0.5rem;
+      margin: 0.25rem;
+    }
+
+    button:hover,
+    button:focus {
+      background: #0053ba;
+    }
+
+    button:focus {
+      outline: 1px solid #fff;
+      outline-offset: -4px;
+    }
+
+    button:active {
+      transform: scale(0.99);
+    }
+
+    .button {
+      border: 0;
+      border-radius: 0.25rem;
+      background: #1e88e5;
+      color: white;
+      font-family: system-ui, sans-serif;
+      font-size: 1rem;
+      line-height: 1.2;
+      white-space: nowrap;
+      text-decoration: none;
+      padding: 0.25rem 0.5rem;
+      margin: 0.25rem;
+      cursor: pointer;
+    }
+
+    .bottom {
+      position: fixed;
+      bottom: 0;
+      left: 0;
+      text-align: center;
+      width: 100%;
+      padding: 5px;
+      background: #333;
+      color: #eef;
+    }
+
+    .dark-link {
+      color: white;
+      text-decoration: none !important;
+    }
+
+    .tabs-container {
+      position: fixed;
+      height: 400px;
+      top: 20px;
+      left: 10px;
+      right: 10px;
+      z-index: 9;
+    }
+
+    .tabs {
+      position: relative;
+      min-height: 400px;
+      clear: both;
+    }
+
+    .tab {
+      float: left;
+    }
+
+    .tab>label {
+      background: #eee;
+      padding: 10px;
+      border: 1px solid transparent;
+      margin-left: -1px;
+      position: relative;
+      left: 1px;
+    }
+
+    .tabs>.tabber {
+      border-top-left-radius: 5px;
+    }
+
+    .tabs>.tabber~.tabber {
+      border-top-left-radius: none;
+    }
+
+    .tab [type="radio"] {
+      display: none;
+    }
+
+    .content {
+      position: absolute;
+      top: 28px;
+      left: 0;
+      background: #bbc;
+      right: 0;
+      bottom: 0;
+      padding: 20px;
+      border: 1px solid transparent;
+      border-top-right-radius: 5px;
+      border-bottom-left-radius: 5px;
+      border-bottom-right-radius: 5px;
+    }
+
+    [type="radio"]:checked~label {
+      background: #bbc;
+      border-bottom: 1px solid transparent;
+      z-index: 2;
+    }
+
+    [type="radio"]:checked~label~.content {
+      z-index: 1;
+    }
+  </style>
+</head>
+
+<body>
+  <div class="logo-container">
+    <img src="icon.png" class="logo" />
+  </div>
+
+  <div class="tabs-container">
+    <div class="tabs">
+      <div class="tab">
+        <input type="radio" id="tab-1" name="tab-group-1" checked />
+        <label class="tabber" for="tab-1">Messages</label>
+        <div class="content">
+          <button class="button" id="log">Call Log API</button>
+          <button class="button" id="request">
+            Call Request (async) API
+          </button>
+          <button class="button" id="event">Send event to Rust</button>
+          <button class="button" id="notification">
+            Send test notification
+          </button>
+
+          <div style="margin-top: 24px">
+            <input id="title" value="Awesome Tauri Example!" />
+            <button class="button" id="set-title">Set title</button>
           </div>
         </div>
-        <div class="tab">
-          <input type="radio" id="tab-2" name="tab-group-1" />
-          <label class="tabber" for="tab-2">File System</label>
-          <div class="content">
-            <div style="margin-top: 24px">
-              <select class="button" id="dir">
-                <option value="">None</option>
-              </select>
-              <input id="path-to-read" placeholder="Type the path to read..." />
-              <button class="button" id="read">Read</button>
+      </div>
+      <div class="tab">
+        <input type="radio" id="tab-2" name="tab-group-1" />
+        <label class="tabber" for="tab-2">File System</label>
+        <div class="content">
+          <div style="margin-top: 24px">
+            <select class="button" id="dir">
+              <option value="">None</option>
+            </select>
+            <input id="path-to-read" placeholder="Type the path to read..." />
+            <button class="button" id="read">Read</button>
+          </div>
+          <div style="margin-top: 24px">
+            <input id="dialog-default-path" placeholder="Default path" />
+            <input id="dialog-filter" placeholder="Extensions filter" />
+            <div>
+              <input type="checkbox" id="dialog-multiple" />
+              <label>Multiple</label>
             </div>
-            <div style="margin-top: 24px">
-              <input id="dialog-default-path" placeholder="Default path" />
-              <input id="dialog-filter" placeholder="Extensions filter" />
-              <div>
-                <input type="checkbox" id="dialog-multiple" />
-                <label>Multiple</label>
-              </div>
-              <div>
-                <input type="checkbox" id="dialog-directory" />
-                <label>Directory</label>
-              </div>
-
-              <button class="button" id="open-dialog">Open dialog</button>
-              <button class="button" id="save-dialog">Open save dialog</button>
+            <div>
+              <input type="checkbox" id="dialog-directory" />
+              <label>Directory</label>
             </div>
+
+            <button class="button" id="open-dialog">Open dialog</button>
+            <button class="button" id="save-dialog">Open save dialog</button>
           </div>
         </div>
+      </div>
 
-        <div class="tab">
-          <input type="radio" id="tab-3" name="tab-group-1" />
-          <label class="tabber" for="tab-3">Communication</label>
-          <div class="content">
-            <div style="margin-top: 24px">
-              <input id="url" value="https://tauri.studio" />
-              <button class="button" id="open-url">Open URL</button>
-            </div>
+      <div class="tab">
+        <input type="radio" id="tab-3" name="tab-group-1" />
+        <label class="tabber" for="tab-3">Communication</label>
+        <div class="content">
+          <div style="margin-top: 24px">
+            <input id="url" value="https://tauri.studio" />
+            <button class="button" id="open-url">Open URL</button>
+          </div>
 
-            <div style="margin-top: 24px">
-              <select class="button" id="request-method">
-                <option value="GET">GET</option>
-                <option value="POST">POST</option>
-                <option value="PUT">PUT</option>
-                <option value="PATCH">PATCH</option>
-                <option value="DELETE">DELETE</option>
-              </select>
-              <input id="request-url" placeholder="Type the request URL..." />
-              <br />
-              <textarea
-                id="request-body"
-                placeholder="Request body"
-                rows="5"
-                style="width: 100%; margin-right: 10px; font-size: 12px"
-              ></textarea>
-              <br />
-              <button class="button" id="make-request">Make request</button>
-            </div>
+          <div style="margin-top: 24px">
+            <select class="button" id="request-method">
+              <option value="GET">GET</option>
+              <option value="POST">POST</option>
+              <option value="PUT">PUT</option>
+              <option value="PATCH">PATCH</option>
+              <option value="DELETE">DELETE</option>
+            </select>
+            <input id="request-url" placeholder="Type the request URL..." />
+            <br />
+            <textarea id="request-body" placeholder="Request body" rows="5"
+              style="width: 100%; margin-right: 10px; font-size: 12px"></textarea>
+            <br />
+            <button class="button" id="make-request">Make request</button>
           </div>
         </div>
-        <div class="tab">
-          <input type="radio" id="tab-4" name="tab-group-1" />
-          <label class="tabber" for="tab-4">CLI</label>
-          <div class="content">
-            <div style="margin-top: 24px">
-              <button class="button" id="cli-matches">Get matches</button>
-            </div>
+      </div>
+      <div class="tab">
+        <input type="radio" id="tab-4" name="tab-group-1" />
+        <label class="tabber" for="tab-4">CLI</label>
+        <div class="content">
+          <div style="margin-top: 24px">
+            <button class="button" id="cli-matches">Get matches</button>
           </div>
         </div>
       </div>
     </div>
-    <div id="response"></div>
-    <div class="bottom">
-      <a class="dark-link" target="_blank" href="https://tauri.studio"
-        >Tauri Documentation</a
-      >&nbsp;&nbsp;&nbsp;
-      <a
-        class="dark-link"
-        target="_blank"
-        href="https://github.com/tauri-apps/tauri"
-        >Github Repo</a
-      >&nbsp;&nbsp;&nbsp;
-      <a
-        class="dark-link"
-        target="_blank"
-        href="https://github.com/tauri-apps/tauri/tree/dev/tauri/examples/communication"
-        >Source for this App</a
-      >
-    </div>
-    <script>
-      function registerResponse(response) {
-        document.getElementById("response").innerHTML =
-          typeof response === "object" ? JSON.stringify(response) : response;
-      }
-
-      function addClickEnterHandler(button, input, handler) {
-        button.addEventListener("click", handler);
-        input.addEventListener("keyup", function (e) {
-          if (e.keyCode === 13) {
-            handler();
-          }
-        });
-      }
-
-      window.__TAURI__.event.listen("rust-event", function (res) {
-        document.getElementById("response").innerHTML = JSON.stringify(res);
-      });
-
-      document.querySelector(".logo").addEventListener("click", function () {
-        window.__TAURI__.window.open("https://tauri.studio/");
-      });
-
-      var dirSelect = document.getElementById("dir");
-      for (var key in window.__TAURI__.fs.Dir) {
-        if (isNaN(parseInt(key))) {
-          var value = window.__TAURI__.fs.Dir[key];
-          var opt = document.createElement("option");
-          opt.value = value;
-          opt.innerHTML = key;
-          dirSelect.appendChild(opt);
+  </div>
+  <div id="response"></div>
+  <div class="bottom">
+    <a class="dark-link" target="_blank" href="https://tauri.studio">Tauri Documentation</a>&nbsp;&nbsp;&nbsp;
+    <a class="dark-link" target="_blank" href="https://github.com/tauri-apps/tauri">Github Repo</a>&nbsp;&nbsp;&nbsp;
+    <a class="dark-link" target="_blank"
+      href="https://github.com/tauri-apps/tauri/tree/dev/tauri/examples/communication">Source for this App</a>
+  </div>
+  <script>
+    function registerResponse(response) {
+      document.getElementById("response").innerHTML =
+        typeof response === "object" ? JSON.stringify(response) : response;
+    }
+
+    function addClickEnterHandler(button, input, handler) {
+      button.addEventListener("click", handler);
+      input.addEventListener("keyup", function (e) {
+        if (e.keyCode === 13) {
+          handler();
         }
+      });
+    }
+
+    window.__TAURI__.event.listen("rust-event", function (res) {
+      document.getElementById("response").innerHTML = JSON.stringify(res);
+    });
+
+    document.querySelector(".logo").addEventListener("click", function () {
+      window.__TAURI__.shell.open("https://tauri.studio/");
+    });
+
+    var dirSelect = document.getElementById("dir");
+    for (var key in window.__TAURI__.fs.Dir) {
+      if (isNaN(parseInt(key))) {
+        var value = window.__TAURI__.fs.Dir[key];
+        var opt = document.createElement("option");
+        opt.value = value;
+        opt.innerHTML = key;
+        dirSelect.appendChild(opt);
       }
-    </script>
-    <script src="communication.js"></script>
-    <script src="fs.js"></script>
-    <script src="window.js"></script>
-    <script src="dialog.js"></script>
-    <script src="http.js"></script>
-    <script src="cli.js"></script>
-    <script src="notification.js"></script>
-  </body>
-</html>
+    }
+  </script>
+  <script src="communication.js"></script>
+  <script src="fs.js"></script>
+  <script src="window.js"></script>
+  <script src="dialog.js"></script>
+  <script src="http.js"></script>
+  <script src="cli.js"></script>
+  <script src="notification.js"></script>
+</body>
+
+</html>

+ 1 - 1
tauri/examples/communication/dist/window.js

@@ -4,7 +4,7 @@ addClickEnterHandler(
   document.getElementById("open-url"),
   urlInput,
   function () {
-    window.__TAURI__.window.open(urlInput.value);
+    window.__TAURI__.shell.open(urlInput.value);
   }
 );
 

+ 2 - 1
tauri/examples/communication/src-tauri/Cargo.lock

@@ -3094,11 +3094,12 @@ dependencies = [
 [[package]]
 name = "wry"
 version = "0.4.1"
-source = "git+https://github.com/tauri-apps/wry?rev=42f4f2133f7921ed5adc47908787094da8abeac5#42f4f2133f7921ed5adc47908787094da8abeac5"
+source = "git+https://github.com/tauri-apps/wry?rev=f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4#f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4"
 dependencies = [
  "cc",
  "cocoa",
  "core-graphics 0.22.2",
+ "gdk",
  "gio",
  "glib",
  "gtk",

+ 1 - 1
tauri/examples/communication/src-tauri/src/main.rs

@@ -35,7 +35,7 @@ fn main() {
     .invoke_handler(|webview_manager, arg| async move {
       use cmd::Cmd::*;
       match serde_json::from_str(&arg) {
-        Err(e) => Err(e.to_string()),
+        Err(e) => Err(e.into()),
         Ok(command) => {
           match command {
             LogOperation { event, payload } => {

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
tauri/examples/multiwindow/dist/__tauri.js


+ 3089 - 0
tauri/examples/multiwindow/src-tauri/Cargo.lock

@@ -0,0 +1,3089 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "ab_glyph_rasterizer"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9fe5e32de01730eb1f6b7f5b51c17e03e2325bf40a74f754f04f130043affff"
+
+[[package]]
+name = "addr2line"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
+
+[[package]]
+name = "adler32"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
+
+[[package]]
+name = "andrew"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c4afb09dd642feec8408e33f92f3ffc4052946f6b20f32fb99c1f58cd4fa7cf"
+dependencies = [
+ "bitflags 1.2.1",
+ "rusttype",
+ "walkdir",
+ "xdg",
+ "xml-rs 0.8.3",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
+
+[[package]]
+name = "app"
+version = "0.1.0"
+dependencies = [
+ "tauri",
+ "winres",
+]
+
+[[package]]
+name = "arrayref"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
+
+[[package]]
+name = "arrayvec"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
+
+[[package]]
+name = "ascii"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109"
+
+[[package]]
+name = "async-trait"
+version = "0.1.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "atk"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "812b4911e210bd51b24596244523c856ca749e6223c50a7fbbba3f89ee37c426"
+dependencies = [
+ "atk-sys",
+ "bitflags 1.2.1",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+]
+
+[[package]]
+name = "atk-sys"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f530e4af131d94cc4fa15c5c9d0348f0ef28bac64ba660b6b2a1cf2605dedfce"
+dependencies = [
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "system-deps",
+]
+
+[[package]]
+name = "attohttpc"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba5b30bf3a0aead269fd5dd69b385a3e90c2b55f4f215d1bdf52c3883f5fa7fa"
+dependencies = [
+ "flate2",
+ "http",
+ "log",
+ "native-tls",
+ "openssl",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "url",
+ "wildmatch",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "backtrace"
+version = "0.3.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc"
+dependencies = [
+ "addr2line",
+ "cfg-if 1.0.0",
+ "libc",
+ "miniz_oxide 0.4.3",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "base64"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+
+[[package]]
+name = "bitflags"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+
+[[package]]
+name = "blake2b_simd"
+version = "0.5.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "constant_time_eq",
+]
+
+[[package]]
+name = "block"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
+
+[[package]]
+name = "bumpalo"
+version = "3.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
+
+[[package]]
+name = "byteorder"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
+
+[[package]]
+name = "bytes"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
+
+[[package]]
+name = "bzip2"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b"
+dependencies = [
+ "bzip2-sys",
+ "libc",
+]
+
+[[package]]
+name = "bzip2-sys"
+version = "0.1.10+1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17fa3d1ac1ca21c5c4e36a97f3c3eb25084576f6fc47bf0139c1123434216c6c"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
+name = "cairo-rs"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5c0f2e047e8ca53d0ff249c54ae047931d7a6ebe05d00af73e0ffeb6e34bdb8"
+dependencies = [
+ "bitflags 1.2.1",
+ "cairo-sys-rs",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "thiserror",
+]
+
+[[package]]
+name = "cairo-sys-rs"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ed2639b9ad5f1d6efa76de95558e11339e7318426d84ac4890b86c03e828ca7"
+dependencies = [
+ "glib-sys",
+ "libc",
+ "system-deps",
+]
+
+[[package]]
+name = "calloop"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b036167e76041694579972c28cf4877b4f92da222560ddb49008937b6a6727c"
+dependencies = [
+ "log",
+ "nix",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "cfg_aliases"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
+
+[[package]]
+name = "chrono"
+version = "0.4.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
+dependencies = [
+ "libc",
+ "num-integer",
+ "num-traits",
+ "time",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "chunked_transfer"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
+
+[[package]]
+name = "cocoa"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832"
+dependencies = [
+ "bitflags 1.2.1",
+ "block",
+ "cocoa-foundation",
+ "core-foundation 0.9.1",
+ "core-graphics 0.22.2",
+ "foreign-types",
+ "libc",
+ "objc",
+]
+
+[[package]]
+name = "cocoa-foundation"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318"
+dependencies = [
+ "bitflags 1.2.1",
+ "block",
+ "core-foundation 0.9.1",
+ "core-graphics-types",
+ "foreign-types",
+ "libc",
+ "objc",
+]
+
+[[package]]
+name = "const-sha1"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb58b6451e8c2a812ad979ed1d83378caa5e927eef2622017a45f251457c2c9d"
+
+[[package]]
+name = "const_fn"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
+
+[[package]]
+name = "constant_time_eq"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
+
+[[package]]
+name = "core-foundation"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
+dependencies = [
+ "core-foundation-sys 0.7.0",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62"
+dependencies = [
+ "core-foundation-sys 0.8.2",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
+
+[[package]]
+name = "core-graphics"
+version = "0.19.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923"
+dependencies = [
+ "bitflags 1.2.1",
+ "core-foundation 0.7.0",
+ "foreign-types",
+ "libc",
+]
+
+[[package]]
+name = "core-graphics"
+version = "0.22.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "269f35f69b542b80e736a20a89a05215c0ce80c2c03c514abb2e318b78379d86"
+dependencies = [
+ "bitflags 1.2.1",
+ "core-foundation 0.9.1",
+ "core-graphics-types",
+ "foreign-types",
+ "libc",
+]
+
+[[package]]
+name = "core-graphics-types"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
+dependencies = [
+ "bitflags 1.2.1",
+ "core-foundation 0.9.1",
+ "foreign-types",
+ "libc",
+]
+
+[[package]]
+name = "core-video-sys"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828"
+dependencies = [
+ "cfg-if 0.1.10",
+ "core-foundation-sys 0.7.0",
+ "core-graphics 0.19.2",
+ "libc",
+ "objc",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
+dependencies = [
+ "cfg-if 1.0.0",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
+dependencies = [
+ "cfg-if 1.0.0",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
+dependencies = [
+ "cfg-if 1.0.0",
+ "const_fn",
+ "crossbeam-utils",
+ "lazy_static",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
+dependencies = [
+ "autocfg",
+ "cfg-if 1.0.0",
+ "lazy_static",
+]
+
+[[package]]
+name = "darling"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote 1.0.8",
+ "strsim",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
+dependencies = [
+ "darling_core",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "dbus"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b1334c0161ddfccd239ac81b188d62015b049c986c5cd0b7f9447cf2c54f4a3"
+dependencies = [
+ "libc",
+ "libdbus-sys",
+]
+
+[[package]]
+name = "derivative"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "dirs"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
+dependencies = [
+ "libc",
+ "redox_users 0.3.5",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "dirs-next"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
+dependencies = [
+ "cfg-if 1.0.0",
+ "dirs-sys-next",
+]
+
+[[package]]
+name = "dirs-sys-next"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
+dependencies = [
+ "libc",
+ "redox_users 0.4.0",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "dispatch"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
+
+[[package]]
+name = "dlib"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76"
+dependencies = [
+ "libloading",
+]
+
+[[package]]
+name = "doc-comment"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+
+[[package]]
+name = "downcast-rs"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
+
+[[package]]
+name = "dtoa"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e"
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "failure"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
+dependencies = [
+ "backtrace",
+]
+
+[[package]]
+name = "filetime"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "redox_syscall 0.2.4",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "flate2"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42"
+dependencies = [
+ "cfg-if 0.1.10",
+ "crc32fast",
+ "libc",
+ "miniz_oxide 0.3.7",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00"
+dependencies = [
+ "matches",
+ "percent-encoding",
+]
+
+[[package]]
+name = "fuchsia-zircon"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+dependencies = [
+ "bitflags 1.2.1",
+ "fuchsia-zircon-sys",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+
+[[package]]
+name = "futures"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9e59fdc009a4b3096bf94f740a0f2424c082521f20a9b08c5c07c48d90fd9b9"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd"
+dependencies = [
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caf5c69029bda2e743fddd0582d1083951d65cc9539aebf8812f36c3491342d6"
+
+[[package]]
+name = "futures-task"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "futures-util"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "proc-macro-hack",
+ "proc-macro-nested",
+ "slab",
+]
+
+[[package]]
+name = "gcc"
+version = "0.3.55"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
+
+[[package]]
+name = "gdk"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db00839b2a68a7a10af3fa28dfb3febaba3a20c3a9ac2425a33b7df1f84a6b7d"
+dependencies = [
+ "bitflags 1.2.1",
+ "cairo-rs",
+ "cairo-sys-rs",
+ "gdk-pixbuf",
+ "gdk-sys",
+ "gio",
+ "gio-sys",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "pango",
+]
+
+[[package]]
+name = "gdk-pixbuf"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f6dae3cb99dd49b758b88f0132f8d401108e63ae8edd45f432d42cdff99998a"
+dependencies = [
+ "gdk-pixbuf-sys",
+ "gio",
+ "gio-sys",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+]
+
+[[package]]
+name = "gdk-pixbuf-sys"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3bfe468a7f43e97b8d193a762b6c5cf67a7d36cacbc0b9291dbcae24bfea1e8f"
+dependencies = [
+ "gio-sys",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "system-deps",
+]
+
+[[package]]
+name = "gdk-sys"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a9653cfc500fd268015b1ac055ddbc3df7a5c9ea3f4ccef147b3957bd140d69"
+dependencies = [
+ "cairo-sys-rs",
+ "gdk-pixbuf-sys",
+ "gio-sys",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "pango-sys",
+ "pkg-config",
+ "system-deps",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "wasi 0.10.2+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "gimli"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
+
+[[package]]
+name = "gio"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fb60242bfff700772dae5d9e3a1f7aa2e4ebccf18b89662a16acb2822568561"
+dependencies = [
+ "bitflags 1.2.1",
+ "futures",
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-util",
+ "gio-sys",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "once_cell",
+ "thiserror",
+]
+
+[[package]]
+name = "gio-sys"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e24fb752f8f5d2cf6bbc2c606fd2bc989c81c5e2fe321ab974d54f8b6344eac"
+dependencies = [
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "system-deps",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "glib"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c685013b7515e668f1b57a165b009d4d28cb139a8a989bbd699c10dad29d0c5"
+dependencies = [
+ "bitflags 1.2.1",
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-task",
+ "futures-util",
+ "glib-macros",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "once_cell",
+]
+
+[[package]]
+name = "glib-macros"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41486a26d1366a8032b160b59065a59fb528530a46a49f627e7048fb8c064039"
+dependencies = [
+ "anyhow",
+ "heck",
+ "itertools",
+ "proc-macro-crate",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "glib-sys"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1"
+dependencies = [
+ "libc",
+ "system-deps",
+]
+
+[[package]]
+name = "gobject-sys"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "952133b60c318a62bf82ee75b93acc7e84028a093e06b9e27981c2b6fe68218c"
+dependencies = [
+ "glib-sys",
+ "libc",
+ "system-deps",
+]
+
+[[package]]
+name = "gtk"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f022f2054072b3af07666341984562c8e626a79daa8be27b955d12d06a5ad6a"
+dependencies = [
+ "atk",
+ "bitflags 1.2.1",
+ "cairo-rs",
+ "cairo-sys-rs",
+ "cc",
+ "gdk",
+ "gdk-pixbuf",
+ "gdk-pixbuf-sys",
+ "gdk-sys",
+ "gio",
+ "gio-sys",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "gtk-sys",
+ "libc",
+ "once_cell",
+ "pango",
+ "pango-sys",
+ "pkg-config",
+]
+
+[[package]]
+name = "gtk-sys"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89acda6f084863307d948ba64a4b1ef674e8527dddab147ee4cdcc194c880457"
+dependencies = [
+ "atk-sys",
+ "cairo-sys-rs",
+ "gdk-pixbuf-sys",
+ "gdk-sys",
+ "gio-sys",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "pango-sys",
+ "system-deps",
+]
+
+[[package]]
+name = "heck"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "http"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
+name = "idna"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de910d521f7cc3135c4de8db1cb910e0b5ed1dc6f57c381cd07e8e661ce10094"
+dependencies = [
+ "matches",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "iovec"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "itertools"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
+
+[[package]]
+name = "javascriptcore-rs"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ecc697657edc9cd3d85d5ec6941f74cc9bb2ae84bec320f55c9397c5a8d8722"
+dependencies = [
+ "glib",
+ "javascriptcore-rs-sys",
+]
+
+[[package]]
+name = "javascriptcore-rs-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f46ada8a08dcd75a10afae872fbfb51275df4a8ae0d46b8cc7c708f08dd2998"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "jni-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
+
+[[package]]
+name = "js-sys"
+version = "0.3.47"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
+[[package]]
+name = "libc"
+version = "0.2.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
+
+[[package]]
+name = "libdbus-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc12a3bc971424edbbf7edaf6e5740483444db63aa8e23d3751ff12a30f306f0"
+dependencies = [
+ "pkg-config",
+]
+
+[[package]]
+name = "libloading"
+version = "0.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
+dependencies = [
+ "cfg-if 1.0.0",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "mac-notification-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dfb6b71a9a89cd38b395d994214297447e8e63b1ba5708a9a2b0b1048ceda76"
+dependencies = [
+ "cc",
+ "chrono",
+ "dirs",
+ "objc-foundation",
+]
+
+[[package]]
+name = "malloc_buf"
+version = "0.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "matches"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
+
+[[package]]
+name = "maybe-uninit"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
+
+[[package]]
+name = "memchr"
+version = "2.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
+
+[[package]]
+name = "memmap2"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
+dependencies = [
+ "adler32",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
+dependencies = [
+ "adler",
+ "autocfg",
+]
+
+[[package]]
+name = "mio"
+version = "0.6.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
+dependencies = [
+ "cfg-if 0.1.10",
+ "fuchsia-zircon",
+ "fuchsia-zircon-sys",
+ "iovec",
+ "kernel32-sys",
+ "libc",
+ "log",
+ "miow",
+ "net2",
+ "slab",
+ "winapi 0.2.8",
+]
+
+[[package]]
+name = "mio-extras"
+version = "2.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
+dependencies = [
+ "lazycell",
+ "log",
+ "mio",
+ "slab",
+]
+
+[[package]]
+name = "miow"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
+dependencies = [
+ "kernel32-sys",
+ "net2",
+ "winapi 0.2.8",
+ "ws2_32-sys",
+]
+
+[[package]]
+name = "native-tls"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4"
+dependencies = [
+ "lazy_static",
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
+[[package]]
+name = "ndk"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5eb167c1febed0a496639034d0c76b3b74263636045db5489eee52143c246e73"
+dependencies = [
+ "jni-sys",
+ "ndk-sys",
+ "num_enum",
+ "thiserror",
+]
+
+[[package]]
+name = "ndk-glue"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdf399b8b7a39c6fb153c4ec32c72fd5fe789df24a647f229c239aa7adb15241"
+dependencies = [
+ "lazy_static",
+ "libc",
+ "log",
+ "ndk",
+ "ndk-macro",
+ "ndk-sys",
+]
+
+[[package]]
+name = "ndk-macro"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d"
+dependencies = [
+ "darling",
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "ndk-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d"
+
+[[package]]
+name = "net2"
+version = "0.2.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae"
+dependencies = [
+ "cfg-if 0.1.10",
+ "libc",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "nfd"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e752e3c216bc8a491c5b59fa46da10f1379ae450b19ac688e07f4bb55042e98"
+dependencies = [
+ "gcc",
+]
+
+[[package]]
+name = "nix"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055"
+dependencies = [
+ "bitflags 1.2.1",
+ "cc",
+ "cfg-if 0.1.10",
+ "libc",
+]
+
+[[package]]
+name = "nom"
+version = "6.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab6f70b46d6325aa300f1c7bb3d470127dfc27806d8ea6bf294ee0ce643ce2b1"
+dependencies = [
+ "memchr",
+ "version_check",
+]
+
+[[package]]
+name = "notify-rust"
+version = "4.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95a3a5dd7b4b415b112ce0fae1988f3e6dee90a96918bf3950b5f2289b19a04b"
+dependencies = [
+ "dbus",
+ "mac-notification-sys",
+ "winrt-notification",
+]
+
+[[package]]
+name = "ntapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
+dependencies = [
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "num_enum"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4"
+dependencies = [
+ "derivative",
+ "num_enum_derive",
+]
+
+[[package]]
+name = "num_enum_derive"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "objc"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
+dependencies = [
+ "malloc_buf",
+]
+
+[[package]]
+name = "objc-foundation"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
+dependencies = [
+ "block",
+ "objc",
+ "objc_id",
+]
+
+[[package]]
+name = "objc_id"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
+dependencies = [
+ "objc",
+]
+
+[[package]]
+name = "object"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
+
+[[package]]
+name = "once_cell"
+version = "1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
+
+[[package]]
+name = "openssl"
+version = "0.10.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70"
+dependencies = [
+ "bitflags 1.2.1",
+ "cfg-if 1.0.0",
+ "foreign-types",
+ "lazy_static",
+ "libc",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6"
+dependencies = [
+ "autocfg",
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "owned_ttf_parser"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3"
+dependencies = [
+ "ttf-parser",
+]
+
+[[package]]
+name = "pango"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9937068580bebd8ced19975938573803273ccbcbd598c58d4906efd4ac87c438"
+dependencies = [
+ "bitflags 1.2.1",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "once_cell",
+ "pango-sys",
+]
+
+[[package]]
+name = "pango-sys"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d2650c8b62d116c020abd0cea26a4ed96526afda89b1c4ea567131fdefc890"
+dependencies = [
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "system-deps",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272"
+dependencies = [
+ "cfg-if 1.0.0",
+ "instant",
+ "libc",
+ "redox_syscall 0.1.57",
+ "smallvec",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+
+[[package]]
+name = "pest"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+dependencies = [
+ "ucd-trie",
+]
+
+[[package]]
+name = "phf"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
+dependencies = [
+ "phf_macros",
+ "phf_shared",
+ "proc-macro-hack",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
+dependencies = [
+ "phf_shared",
+ "rand 0.7.3",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
+name = "proc-macro-crate"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
+dependencies = [
+ "toml",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
+
+[[package]]
+name = "proc-macro-nested"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
+dependencies = [
+ "unicode-xid 0.2.1",
+]
+
+[[package]]
+name = "quote"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
+
+[[package]]
+name = "quote"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom 0.1.16",
+ "libc",
+ "rand_chacha 0.2.2",
+ "rand_core 0.5.1",
+ "rand_hc 0.2.0",
+ "rand_pcg",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+dependencies = [
+ "libc",
+ "rand_chacha 0.3.0",
+ "rand_core 0.6.1",
+ "rand_hc 0.3.0",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.6.1",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom 0.1.16",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5"
+dependencies = [
+ "getrandom 0.2.2",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
+dependencies = [
+ "rand_core 0.6.1",
+]
+
+[[package]]
+name = "rand_pcg"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "raw-window-handle"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "rayon"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
+dependencies = [
+ "autocfg",
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "lazy_static",
+ "num_cpus",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.1.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
+dependencies = [
+ "bitflags 1.2.1",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
+dependencies = [
+ "getrandom 0.1.16",
+ "redox_syscall 0.1.57",
+ "rust-argon2",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
+dependencies = [
+ "getrandom 0.2.2",
+ "redox_syscall 0.2.4",
+]
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "runas"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a620b0994a180cdfa25c0439e6d58c0628272571501880d626ffff58e96a0799"
+dependencies = [
+ "cc",
+ "which",
+]
+
+[[package]]
+name = "rust-argon2"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb"
+dependencies = [
+ "base64",
+ "blake2b_simd",
+ "constant_time_eq",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
+
+[[package]]
+name = "rusttype"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59"
+dependencies = [
+ "ab_glyph_rasterizer",
+ "owned_ttf_parser",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
+dependencies = [
+ "lazy_static",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "scoped-tls"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "security-framework"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69"
+dependencies = [
+ "bitflags 1.2.1",
+ "core-foundation 0.9.1",
+ "core-foundation-sys 0.8.2",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b"
+dependencies = [
+ "core-foundation-sys 0.8.2",
+ "libc",
+]
+
+[[package]]
+name = "semver"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
+dependencies = [
+ "pest",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.123"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.123"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.62"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_repr"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
+dependencies = [
+ "dtoa",
+ "itoa",
+ "serde",
+ "url",
+]
+
+[[package]]
+name = "sha1"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
+
+[[package]]
+name = "siphasher"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
+
+[[package]]
+name = "slab"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
+
+[[package]]
+name = "smallvec"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
+
+[[package]]
+name = "smithay-client-toolkit"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "316e13a3eb853ce7bf72ad3530dc186cb2005c57c521ef5f4ada5ee4eed74de6"
+dependencies = [
+ "andrew",
+ "bitflags 1.2.1",
+ "calloop",
+ "dlib",
+ "lazy_static",
+ "log",
+ "memmap2",
+ "nix",
+ "wayland-client",
+ "wayland-cursor",
+ "wayland-protocols",
+]
+
+[[package]]
+name = "soup-sys"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3c7adf08565630bbb71f955f11f8a68464817ded2703a3549747c235b58a13e"
+dependencies = [
+ "bitflags 1.2.1",
+ "gio-sys",
+ "glib-sys",
+ "gobject-sys",
+ "libc",
+ "pkg-config",
+ "system-deps",
+]
+
+[[package]]
+name = "squote"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fccf17fd09e2455ea796d2ad267b64fa2c5cbd8701b2a93b555d2aa73449f7d"
+
+[[package]]
+name = "strsim"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
+
+[[package]]
+name = "strum"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ca6e4730f517e041e547ffe23d29daab8de6b73af4b6ae2a002108169f5e7da"
+
+[[package]]
+name = "strum"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
+
+[[package]]
+name = "strum_macros"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3384590878eb0cab3b128e844412e2d010821e7e091211b9d87324173ada7db8"
+dependencies = [
+ "quote 0.3.15",
+ "syn 0.11.11",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "syn"
+version = "0.11.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
+dependencies = [
+ "quote 0.3.15",
+ "synom",
+ "unicode-xid 0.0.4",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "unicode-xid 0.2.1",
+]
+
+[[package]]
+name = "synom"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
+dependencies = [
+ "unicode-xid 0.0.4",
+]
+
+[[package]]
+name = "sysinfo"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8834e42be61ae4f6338b216fbb69837c7f33c3d4d3a139fb073735b25af4d9e"
+dependencies = [
+ "cfg-if 0.1.10",
+ "doc-comment",
+ "libc",
+ "ntapi",
+ "once_cell",
+ "rayon",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "system-deps"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b"
+dependencies = [
+ "heck",
+ "pkg-config",
+ "strum 0.18.0",
+ "strum_macros 0.18.0",
+ "thiserror",
+ "toml",
+ "version-compare",
+]
+
+[[package]]
+name = "tar"
+version = "0.4.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0313546c01d59e29be4f09687bcb4fb6690cec931cc3607b6aec7a0e417f4cc6"
+dependencies = [
+ "filetime",
+ "libc",
+ "xattr",
+]
+
+[[package]]
+name = "tauri"
+version = "0.11.1"
+dependencies = [
+ "async-trait",
+ "base64",
+ "cfg_aliases",
+ "futures",
+ "lazy_static",
+ "once_cell",
+ "runas",
+ "serde",
+ "serde_json",
+ "tauri-api",
+ "tauri-macros",
+ "thiserror",
+ "tiny_http",
+ "tokio",
+ "uuid",
+ "webbrowser",
+ "wry",
+]
+
+[[package]]
+name = "tauri-api"
+version = "0.7.5"
+dependencies = [
+ "attohttpc",
+ "dirs-next",
+ "either",
+ "flate2",
+ "http",
+ "nfd",
+ "notify-rust",
+ "once_cell",
+ "rand 0.8.3",
+ "semver",
+ "serde",
+ "serde_json",
+ "serde_repr",
+ "tar",
+ "tauri-dialog",
+ "tauri-utils",
+ "tempfile",
+ "thiserror",
+ "zip",
+]
+
+[[package]]
+name = "tauri-dialog"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d5797e1fadcc36b32e29b9dc521abba8ebbc1847378ec96917cdcf548ba6fdc"
+dependencies = [
+ "tauri-dialog-sys",
+]
+
+[[package]]
+name = "tauri-dialog-sys"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3eba3890c956c0234a27bc5648af00738c81e193351ce5f47faec7efc9156c02"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
+
+[[package]]
+name = "tauri-macros"
+version = "0.1.0"
+dependencies = [
+ "flate2",
+ "proc-macro2",
+ "quote 1.0.8",
+ "serde",
+ "serde_json",
+ "syn 1.0.60",
+ "tauri-utils",
+ "walkdir",
+]
+
+[[package]]
+name = "tauri-utils"
+version = "0.5.1"
+dependencies = [
+ "flate2",
+ "phf",
+ "serde",
+ "serde_json",
+ "sysinfo",
+ "thiserror",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "rand 0.8.3",
+ "redox_syscall 0.2.4",
+ "remove_dir_all",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "time"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
+dependencies = [
+ "libc",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "tiny_http"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eded47106b8e52d8ed8119f0ea6e8c0f5881e69783e0297b5a8462958f334bc1"
+dependencies = [
+ "ascii",
+ "chrono",
+ "chunked_transfer",
+ "log",
+ "url",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
+
+[[package]]
+name = "tokio"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a"
+dependencies = [
+ "autocfg",
+ "num_cpus",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "ttf-parser"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
+dependencies = [
+ "matches",
+]
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
+
+[[package]]
+name = "unicode-xid"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+
+[[package]]
+name = "url"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "matches",
+ "percent-encoding",
+]
+
+[[package]]
+name = "uuid"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
+dependencies = [
+ "getrandom 0.2.2",
+]
+
+[[package]]
+name = "vcpkg"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
+
+[[package]]
+name = "version-compare"
+version = "0.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1"
+
+[[package]]
+name = "version_check"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
+
+[[package]]
+name = "walkdir"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
+dependencies = [
+ "same-file",
+ "winapi 0.3.9",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
+dependencies = [
+ "cfg-if 1.0.0",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7"
+dependencies = [
+ "bumpalo",
+ "lazy_static",
+ "log",
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
+dependencies = [
+ "quote 1.0.8",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64"
+
+[[package]]
+name = "wayland-client"
+version = "0.28.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdbdbe01d03b2267809f3ed99495b37395387fde789e0f2ebb78e8b43f75b6d7"
+dependencies = [
+ "bitflags 1.2.1",
+ "downcast-rs",
+ "libc",
+ "nix",
+ "scoped-tls",
+ "wayland-commons",
+ "wayland-scanner",
+ "wayland-sys",
+]
+
+[[package]]
+name = "wayland-commons"
+version = "0.28.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "480450f76717edd64ad04a4426280d737fc3d10a236b982df7b1aee19f0e2d56"
+dependencies = [
+ "nix",
+ "once_cell",
+ "smallvec",
+ "wayland-sys",
+]
+
+[[package]]
+name = "wayland-cursor"
+version = "0.28.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6eb122c160223a7660feeaf949d0100281d1279acaaed3720eb3c9894496e5f"
+dependencies = [
+ "nix",
+ "wayland-client",
+ "xcursor",
+]
+
+[[package]]
+name = "wayland-protocols"
+version = "0.28.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "319a82b4d3054dd25acc32d9aee0f84fa95b63bc983fffe4703b6b8d47e01a30"
+dependencies = [
+ "bitflags 1.2.1",
+ "wayland-client",
+ "wayland-commons",
+ "wayland-scanner",
+]
+
+[[package]]
+name = "wayland-scanner"
+version = "0.28.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7010ba5767b3fcd350decc59055390b4ebe6bd1b9279a9feb1f1888987f1133d"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "xml-rs 0.8.3",
+]
+
+[[package]]
+name = "wayland-sys"
+version = "0.28.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6793834e0c35d11fd96a97297abe03d37be627e1847da52e17d7e0e3b51cc099"
+dependencies = [
+ "dlib",
+ "lazy_static",
+ "pkg-config",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.47"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webbrowser"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecad156490d6b620308ed411cfee90d280b3cbd13e189ea0d3fada8acc89158a"
+dependencies = [
+ "web-sys",
+ "widestring",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "webkit2gtk"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02b7e9eb04d30f8423e9c8435f686f42bc497cfcac2cfe4b43ce4139fb1a7cb6"
+dependencies = [
+ "bitflags 1.2.1",
+ "cairo-rs",
+ "gdk",
+ "gdk-sys",
+ "gio",
+ "gio-sys",
+ "glib",
+ "glib-sys",
+ "gobject-sys",
+ "gtk",
+ "gtk-sys",
+ "javascriptcore-rs",
+ "libc",
+ "webkit2gtk-sys",
+]
+
+[[package]]
+name = "webkit2gtk-sys"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72d10cf73685359cd8611740db241a231f4d74d7e353348dc5332a1a132d6f24"
+dependencies = [
+ "atk-sys",
+ "bitflags 1.2.1",
+ "cairo-sys-rs",
+ "gdk-pixbuf-sys",
+ "gdk-sys",
+ "gio-sys",
+ "glib-sys",
+ "gobject-sys",
+ "gtk-sys",
+ "javascriptcore-rs-sys",
+ "libc",
+ "pango-sys",
+ "pkg-config",
+ "soup-sys",
+]
+
+[[package]]
+name = "which"
+version = "3.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
+dependencies = [
+ "failure",
+ "libc",
+]
+
+[[package]]
+name = "widestring"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
+
+[[package]]
+name = "wildmatch"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2399814fda0d6999a6bfe9b5c7660d836334deb162a09db8b73d5b38fd8c40a"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8577253c781c3aa634017840854139a65a51de658fb61577e5c91e995ebdd18e"
+dependencies = [
+ "const-sha1",
+ "windows_gen",
+ "windows_macros",
+ "windows_winmd",
+]
+
+[[package]]
+name = "windows_gen"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de23e2765bf82678467efef4ccdeb150a2456b2b01688fbd7c86292c1c931ee7"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "rayon",
+ "sha1",
+ "squote",
+ "syn 1.0.60",
+ "windows_gen_macros",
+ "windows_winmd",
+]
+
+[[package]]
+name = "windows_gen_macros"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "878ecff0c53decca3851547869b5473081198cfe97405b14412be9283a05ae34"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "windows_macros"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aaedcc12658411370a43f9c194c40ed4bae0047c39e48ebf67e92d241a97f0c7"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "rayon",
+ "squote",
+ "syn 1.0.60",
+ "windows_gen",
+ "windows_winmd",
+]
+
+[[package]]
+name = "windows_winmd"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40a0769bcad04692eb69e92ff93ce49c89ca5aeda188e98f5cc9b8502b41d6c0"
+dependencies = [
+ "serde",
+ "serde_json",
+ "windows_winmd_macros",
+]
+
+[[package]]
+name = "windows_winmd_macros"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f67ec9020d1bbfeaa8847ababe33b8dc190d683624cd72a48a4a117de50d6559"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.8",
+ "syn 1.0.60",
+]
+
+[[package]]
+name = "winit"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da4eda6fce0eb84bd0a33e3c8794eb902e1033d0a1d5a31bc4f19b1b4bbff597"
+dependencies = [
+ "bitflags 1.2.1",
+ "cocoa",
+ "core-foundation 0.9.1",
+ "core-graphics 0.22.2",
+ "core-video-sys",
+ "dispatch",
+ "instant",
+ "lazy_static",
+ "libc",
+ "log",
+ "mio",
+ "mio-extras",
+ "ndk",
+ "ndk-glue",
+ "ndk-sys",
+ "objc",
+ "parking_lot",
+ "percent-encoding",
+ "raw-window-handle",
+ "smithay-client-toolkit",
+ "wayland-client",
+ "winapi 0.3.9",
+ "x11-dl",
+]
+
+[[package]]
+name = "winres"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff4fb510bbfe5b8992ff15f77a2e6fe6cf062878f0eda00c0f44963a807ca5dc"
+dependencies = [
+ "toml",
+]
+
+[[package]]
+name = "winrt"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e30cba82e22b083dc5a422c2ee77e20dc7927271a0dc981360c57c1453cb48d"
+dependencies = [
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "winrt-notification"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c31a65da50d792c6f9bd2e3216249566c4fb1d2d34f9b7d2d66d2e93f62a242"
+dependencies = [
+ "strum 0.8.0",
+ "strum_macros 0.8.0",
+ "winapi 0.3.9",
+ "winrt",
+ "xml-rs 0.6.1",
+]
+
+[[package]]
+name = "wry"
+version = "0.4.1"
+source = "git+https://github.com/tauri-apps/wry?rev=f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4#f4edf89de5dc40b77a94f6b94fcaf76fdac6bbf4"
+dependencies = [
+ "cc",
+ "cocoa",
+ "core-graphics 0.22.2",
+ "gdk",
+ "gio",
+ "glib",
+ "gtk",
+ "libc",
+ "objc",
+ "once_cell",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "url",
+ "webkit2gtk",
+ "windows",
+ "winit",
+]
+
+[[package]]
+name = "ws2_32-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
+]
+
+[[package]]
+name = "x11-dl"
+version = "2.18.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8"
+dependencies = [
+ "lazy_static",
+ "libc",
+ "maybe-uninit",
+ "pkg-config",
+]
+
+[[package]]
+name = "xattr"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "xcursor"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a9a231574ae78801646617cefd13bfe94be907c0e4fa979cfd8b770aa3c5d08"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "xdg"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
+
+[[package]]
+name = "xml-rs"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1945e12e16b951721d7976520b0832496ef79c31602c7a29d950de79ba74621"
+dependencies = [
+ "bitflags 0.9.1",
+]
+
+[[package]]
+name = "xml-rs"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
+
+[[package]]
+name = "zip"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc2896475a242c41366941faa27264df2cb935185a92e059a004d0048feb2ac5"
+dependencies = [
+ "byteorder",
+ "bzip2",
+ "crc32fast",
+ "flate2",
+ "thiserror",
+ "time",
+]

+ 1 - 1
tauri/examples/multiwindow/src-tauri/Cargo.toml

@@ -22,7 +22,7 @@ icon = [
 ]
 
 [dependencies]
-tauri = { path = "../../..", features =["all-api", "cli"]}
+tauri = { path = "../../..", features =["all-api"]}
 
 [target."cfg(windows)".build-dependencies]
 winres = "0.1"

+ 3 - 3
tauri/src/app.rs

@@ -10,7 +10,7 @@ mod webview_manager;
 pub use webview_manager::{WebviewDispatcher, WebviewManager};
 
 type InvokeHandler<D> =
-  dyn Fn(WebviewManager<D>, String) -> BoxFuture<'static, Result<(), String>> + Send + Sync;
+  dyn Fn(WebviewManager<D>, String) -> BoxFuture<'static, crate::Result<()>> + Send + Sync;
 type Setup<D> = dyn Fn(WebviewManager<D>) -> BoxFuture<'static, ()> + Send + Sync;
 
 /// `App` runtime information.
@@ -53,7 +53,7 @@ impl<A: ApplicationExt + 'static> App<A> {
     &self,
     dispatcher: &WebviewManager<A::Dispatcher>,
     arg: &str,
-  ) -> Result<bool, String> {
+  ) -> crate::Result<bool> {
     if let Some(ref invoke_handler) = self.invoke_handler {
       let fut = invoke_handler(dispatcher.clone(), arg.to_string());
       fut.await.map(|_| true)
@@ -94,7 +94,7 @@ impl<A: ApplicationExt + 'static, C: AsTauriContext> AppBuilder<A, C> {
 
   /// Defines the JS message handler callback.
   pub fn invoke_handler<
-    T: futures::Future<Output = Result<(), String>> + Send + Sync + 'static,
+    T: futures::Future<Output = crate::Result<()>> + Send + Sync + 'static,
     F: Fn(WebviewManager<A::Dispatcher>, String) -> T + Send + Sync + 'static,
   >(
     mut self,

+ 8 - 5
tauri/src/app/runner.rs

@@ -208,8 +208,11 @@ pub fn event_initialization_script() -> String {
 
       if (listeners.length > 0) {{
         window.__TAURI__.promisified({{
-          cmd: 'validateSalt',
-          salt: salt
+          module: 'Internal',
+          message: {{
+            cmd: 'validateSalt',
+            salt: salt
+          }}
         }}).then(function () {{
           for (let i = listeners.length - 1; i >= 0; i--) {{
             const listener = listeners[i]
@@ -296,7 +299,7 @@ fn build_webview<A: ApplicationExt + 'static>(
           } else {
             let mut endpoint_handle =
               crate::endpoints::handle(&webview_manager, &arg, &application.context).await;
-            if let Err(crate::Error::UnknownApi) = endpoint_handle {
+            if let Err(crate::Error::UnknownApi(_)) = endpoint_handle {
               let response = match application.run_invoke_handler(&webview_manager, &arg).await {
                 Ok(handled) => {
                   if handled {
@@ -305,11 +308,11 @@ fn build_webview<A: ApplicationExt + 'static>(
                     endpoint_handle
                   }
                 }
-                Err(_) => Err(crate::Error::UnknownApi),
+                Err(e) => Err(e),
               };
               endpoint_handle = response;
             }
-            if let Err(crate::Error::UnknownApi) = endpoint_handle {
+            if let Err(crate::Error::UnknownApi(_)) = endpoint_handle {
               endpoint_handle =
                 crate::plugin::extend_api(A::plugin_store(), &webview_manager, &arg)
                   .await

+ 70 - 328
tauri/src/endpoints.rs

@@ -1,325 +1,90 @@
-mod cmd;
-#[allow(unused_imports)]
-mod file_system;
-mod path;
-mod salt;
-
-#[cfg(open)]
-mod browser;
+mod cli;
 mod dialog;
 #[cfg(event)]
 mod event;
+#[allow(unused_imports)]
+mod file_system;
 #[cfg(http_request)]
 mod http;
+mod internal;
 #[cfg(notification)]
 mod notification;
+mod shell;
+mod window;
+
+use crate::{app::Context, ApplicationDispatcherExt};
 
-use crate::{app::Context, webview::Event, ApplicationDispatcherExt};
+use serde::Deserialize;
+use serde_json::Value;
+
+#[derive(Deserialize)]
+struct ModuleDto {
+  module: String,
+  callback: Option<String>,
+  error: Option<String>,
+  message: Value,
+}
+
+#[derive(Deserialize)]
+#[serde(tag = "module")]
+enum Module {
+  Fs(file_system::Cmd),
+  Window(window::Cmd),
+  Shell(shell::Cmd),
+  Event(event::Cmd),
+  Internal(internal::Cmd),
+  Dialog(dialog::Cmd),
+  Cli(cli::Cmd),
+  Notification(notification::Cmd),
+  Http(http::Cmd),
+}
+
+impl Module {
+  async fn run<D: ApplicationDispatcherExt + 'static>(
+    self,
+    webview_manager: &crate::WebviewManager<D>,
+    context: &Context,
+  ) -> crate::Result<()> {
+    match self {
+      Self::Fs(cmd) => cmd.run(webview_manager).await,
+      Self::Window(cmd) => cmd.run(webview_manager).await?,
+      Self::Shell(cmd) => cmd.run(webview_manager).await,
+      Self::Event(cmd) => cmd.run(webview_manager).await?,
+      Self::Internal(cmd) => cmd.run(webview_manager).await?,
+      Self::Dialog(cmd) => cmd.run(webview_manager).await?,
+      Self::Cli(cmd) => cmd.run(webview_manager, context).await,
+      Self::Notification(cmd) => cmd.run(webview_manager, context).await?,
+      Self::Http(cmd) => cmd.run(webview_manager).await,
+    }
+    Ok(())
+  }
+}
 
-#[allow(unused_variables)]
 pub(crate) async fn handle<D: ApplicationDispatcherExt + 'static>(
   webview_manager: &crate::WebviewManager<D>,
   arg: &str,
   context: &Context,
 ) -> crate::Result<()> {
-  use cmd::Cmd::*;
-  match serde_json::from_str(arg) {
-    Err(e) => Err(e.into()),
-    Ok(command) => {
-      match command {
-        ReadTextFile {
-          path,
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(read_text_file)]
-          file_system::read_text_file(webview_manager, path, options, callback, error).await;
-          #[cfg(not(read_text_file))]
-          allowlist_error(webview_manager, error, "readTextFile");
-        }
-        ReadBinaryFile {
-          path,
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(read_binary_file)]
-          file_system::read_binary_file(webview_manager, path, options, callback, error).await;
-          #[cfg(not(read_binary_file))]
-          allowlist_error(webview_manager, error, "readBinaryFile");
-        }
-        WriteFile {
-          path,
-          contents,
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(write_file)]
-          file_system::write_file(webview_manager, path, contents, options, callback, error).await;
-          #[cfg(not(write_file))]
-          allowlist_error(webview_manager, error, "writeFile");
-        }
-        WriteBinaryFile {
-          path,
-          contents,
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(write_binary_file)]
-          file_system::write_binary_file(webview_manager, path, contents, options, callback, error)
-            .await;
-          #[cfg(not(write_binary_file))]
-          allowlist_error(webview_manager, error, "writeBinaryFile");
-        }
-        ReadDir {
-          path,
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(read_dir)]
-          file_system::read_dir(webview_manager, path, options, callback, error).await;
-          #[cfg(not(read_dir))]
-          allowlist_error(webview_manager, error, "readDir");
-        }
-        CopyFile {
-          source,
-          destination,
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(copy_file)]
-          file_system::copy_file(
-            webview_manager,
-            source,
-            destination,
-            options,
-            callback,
-            error,
-          )
-          .await;
-          #[cfg(not(copy_file))]
-          allowlist_error(webview_manager, error, "copyFile");
-        }
-        CreateDir {
-          path,
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(create_dir)]
-          file_system::create_dir(webview_manager, path, options, callback, error).await;
-          #[cfg(not(create_dir))]
-          allowlist_error(webview_manager, error, "createDir");
-        }
-        RemoveDir {
-          path,
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(remove_dir)]
-          file_system::remove_dir(webview_manager, path, options, callback, error).await;
-          #[cfg(not(remove_dir))]
-          allowlist_error(webview_manager, error, "removeDir");
-        }
-        RemoveFile {
-          path,
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(remove_file)]
-          file_system::remove_file(webview_manager, path, options, callback, error).await;
-          #[cfg(not(remove_file))]
-          allowlist_error(webview_manager, error, "removeFile");
-        }
-        RenameFile {
-          old_path,
-          new_path,
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(rename_file)]
-          file_system::rename_file(
-            webview_manager,
-            old_path,
-            new_path,
-            options,
-            callback,
-            error,
-          )
-          .await;
-          #[cfg(not(rename_file))]
-          allowlist_error(webview_manager, error, "renameFile");
-        }
-        ResolvePath {
-          path,
-          directory,
-          callback,
-          error,
-        } => {
-          #[cfg(path_api)]
-          path::resolve_path(webview_manager, path, directory, callback, error).await;
-          #[cfg(not(path_api))]
-          allowlist_error(webview_manager, error, "pathApi");
-        }
-        SetTitle { title } => {
-          webview_manager.current_webview()?.set_title(&title);
-          #[cfg(not(set_title))]
-          throw_allowlist_error(webview_manager, "title");
-        }
-        Execute {
-          command,
-          args,
-          callback,
-          error,
-        } => {
-          #[cfg(execute)]
-          crate::call(webview_manager, command, args, callback, error).await;
-          #[cfg(not(execute))]
-          throw_allowlist_error(webview_manager, "execute");
-        }
-        Open { uri } => {
-          #[cfg(open)]
-          browser::open(uri);
-          #[cfg(not(open))]
-          throw_allowlist_error(webview_manager, "open");
-        }
-        ValidateSalt {
-          salt,
-          callback,
-          error,
-        } => {
-          salt::validate(webview_manager, salt, callback, error)?;
-        }
-        Listen {
-          event,
-          handler,
-          once,
-        } => {
-          #[cfg(event)]
-          {
-            let js_string = event::listen_fn(event, handler, once)?;
-            webview_manager.current_webview()?.eval(&js_string);
-          }
-          #[cfg(not(event))]
-          throw_allowlist_error(webview_manager, "event");
-        }
-        Emit { event, payload } => {
-          // TODO emit to optional window
-          #[cfg(event)]
-          webview_manager.current_webview()?.on_event(event, payload);
-          #[cfg(not(event))]
-          throw_allowlist_error(webview_manager, "event");
-        }
-        OpenDialog {
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(open_dialog)]
-          dialog::open(webview_manager, options, callback, error)?;
-          #[cfg(not(open_dialog))]
-          allowlist_error(webview_manager, error, "title");
-        }
-        SaveDialog {
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(save_dialog)]
-          dialog::save(webview_manager, options, callback, error)?;
-          #[cfg(not(save_dialog))]
-          throw_allowlist_error(webview_manager, "saveDialog");
-        }
-        MessageDialog { message } => {
-          let exe = std::env::current_exe()?;
-          let exe_dir = exe.parent().expect("failed to get exe directory");
-          let app_name = exe
-            .file_name()
-            .expect("failed to get exe filename")
-            .to_string_lossy()
-            .to_string();
-          webview_manager
-            .current_webview()?
-            .send_event(Event::Run(Box::new(move || {
-              dialog::message(app_name, message);
-            })));
-        }
-        AskDialog {
-          title,
-          message,
-          callback,
-          error,
-        } => {
-          let exe = std::env::current_exe()?;
-          dialog::ask(
-            webview_manager,
-            title.unwrap_or_else(|| {
-              let exe_dir = exe.parent().expect("failed to get exe directory");
-              exe
-                .file_name()
-                .expect("failed to get exe filename")
-                .to_string_lossy()
-                .to_string()
-            }),
-            message,
-            callback,
-            error,
-          )?;
-        }
-        HttpRequest {
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(http_request)]
-          http::make_request(webview_manager, *options, callback, error).await;
-          #[cfg(not(http_request))]
-          allowlist_error(webview_manager, error, "httpRequest");
-        }
-        CliMatches { callback, error } => {
-          #[cfg(cli)]
-          {
-            let matches = tauri_api::cli::get_matches(&context.config).map_err(|e| e.into());
-            crate::execute_promise(webview_manager, async move { matches }, callback, error).await;
-          }
-          #[cfg(not(cli))]
-          api_error(
-            webview_manager,
-            error,
-            "CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.studio/docs/api/config#tauri.cli)",
-          );
-        }
-        Notification {
-          options,
-          callback,
-          error,
-        } => {
-          #[cfg(notification)]
-          notification::send(webview_manager, options, callback, error, &context.config).await;
-          #[cfg(not(notification))]
-          allowlist_error(webview_manager, error, "notification");
-        }
-        IsNotificationPermissionGranted { callback, error } => {
-          #[cfg(notification)]
-          notification::is_permission_granted(webview_manager, callback, error).await;
-          #[cfg(not(notification))]
-          allowlist_error(webview_manager, error, "notification");
+  match serde_json::from_str::<ModuleDto>(arg) {
+    Err(e) => {
+      if e.to_string().contains("missing field `module`") {
+        Err(crate::Error::UnknownApi(Some(e)))
+      } else {
+        Err(e.into())
+      }
+    }
+    Ok(mut module_dto) => {
+      if let Value::Object(ref mut obj) = module_dto.message {
+        obj.insert("module".to_string(), Value::String(module_dto.module));
+        if let Some(callback) = module_dto.callback {
+          obj.insert("callback".to_string(), Value::String(callback));
         }
-        RequestNotificationPermission { callback, error } => {
-          #[cfg(notification)]
-          notification::request_permission(webview_manager, callback, error)?;
-          #[cfg(not(notification))]
-          allowlist_error(webview_manager, error, "notification");
+        if let Some(error) = module_dto.error {
+          obj.insert("error".to_string(), Value::String(error));
         }
       }
+      let module: Module = serde_json::from_str(&module_dto.message.to_string())?;
+      module.run(webview_manager, context).await?;
       Ok(())
     }
   }
@@ -366,26 +131,3 @@ fn throw_allowlist_error<D: ApplicationDispatcherExt>(
     dispatcher.eval(&reject_code);
   }
 }
-
-#[cfg(test)]
-mod test {
-  use proptest::prelude::*;
-
-  // check the listen_fn for various usecases.
-  proptest! {
-    #[cfg(event)]
-    #[test]
-    fn check_listen_fn(event in "", handler in "", once in proptest::bool::ANY) {
-      super::event::listen_fn(event, handler, once).expect("listen_fn failed");
-    }
-  }
-
-  // Test the open func to see if proper uris can be opened by the browser.
-  proptest! {
-    #[cfg(open)]
-    #[test]
-    fn check_open(uri in r"(http://)([\\w\\d\\.]+([\\w]{2,6})?)") {
-      super::browser::open(uri);
-  }
-  }
-}

+ 0 - 8
tauri/src/endpoints/browser.rs

@@ -1,8 +0,0 @@
-#[cfg(open)]
-pub fn open(uri: String) {
-  #[cfg(test)]
-  assert!(uri.contains("http://"));
-
-  #[cfg(not(test))]
-  webbrowser::open(&uri).expect("Failed to open webbrowser with uri");
-}

+ 35 - 0
tauri/src/endpoints/cli.rs

@@ -0,0 +1,35 @@
+use serde::Deserialize;
+
+/// The API descriptor.
+#[derive(Deserialize)]
+#[serde(tag = "cmd", rename_all = "camelCase")]
+pub enum Cmd {
+  /// The get CLI matches API.
+  CliMatches { callback: String, error: String },
+}
+
+impl Cmd {
+  #[allow(unused_variables)]
+  pub async fn run<D: crate::ApplicationDispatcherExt + 'static>(
+    self,
+    webview_manager: &crate::WebviewManager<D>,
+    context: &crate::app::Context,
+  ) {
+    match self {
+      #[allow(unused_variables)]
+      Self::CliMatches { callback, error } => {
+        #[cfg(cli)]
+        {
+          let matches = tauri_api::cli::get_matches(&context.config).map_err(|e| e.into());
+          crate::execute_promise(webview_manager, async move { matches }, callback, error).await;
+        }
+        #[cfg(not(cli))]
+          super::api_error(
+            webview_manager,
+            error,
+            "CLI definition not set under tauri.conf.json > tauri > cli (https://tauri.studio/docs/api/config#tauri.cli)",
+          );
+      }
+    }
+  }
+}

+ 0 - 228
tauri/src/endpoints/cmd.rs

@@ -1,228 +0,0 @@
-use std::path::PathBuf;
-
-use crate::api::path::BaseDirectory;
-use serde::Deserialize;
-use tauri_api::http::HttpRequestOptions;
-
-/// The options for the directory functions on the file system API.
-#[derive(Deserialize)]
-pub struct DirOperationOptions {
-  /// Whether the API should recursively perform the operation on the directory.
-  #[serde(default)]
-  pub recursive: bool,
-  /// The base directory of the operation.
-  /// The directory path of the BaseDirectory will be the prefix of the defined directory path.
-  pub dir: Option<BaseDirectory>,
-}
-
-/// The options for the file functions on the file system API.
-#[derive(Deserialize)]
-pub struct FileOperationOptions {
-  /// The base directory of the operation.
-  /// The directory path of the BaseDirectory will be the prefix of the defined file path.
-  pub dir: Option<BaseDirectory>,
-}
-
-/// The options for the open dialog API.
-#[derive(Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct OpenDialogOptions {
-  /// The initial path of the dialog.
-  pub filter: Option<String>,
-  /// Whether the dialog allows multiple selection or not.
-  #[serde(default)]
-  pub multiple: bool,
-  /// Whether the dialog is a directory selection (`true` value) or file selection (`false` value).
-  #[serde(default)]
-  pub directory: bool,
-  /// The initial path of the dialog.
-  pub default_path: Option<PathBuf>,
-}
-
-/// The options for the save dialog API.
-#[derive(Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SaveDialogOptions {
-  /// The initial path of the dialog.
-  pub filter: Option<String>,
-  /// The initial path of the dialog.
-  pub default_path: Option<PathBuf>,
-}
-
-/// The options for the notification API.
-#[derive(Deserialize)]
-pub struct NotificationOptions {
-  /// The notification title.
-  pub title: String,
-  /// The notification body.
-  pub body: Option<String>,
-  /// The notification icon.
-  pub icon: Option<String>,
-}
-
-/// The API descriptor.
-#[derive(Deserialize)]
-#[serde(tag = "cmd", rename_all = "camelCase")]
-pub enum Cmd {
-  /// The read text file API.
-  ReadTextFile {
-    path: PathBuf,
-    options: Option<FileOperationOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The read binary file API.
-  ReadBinaryFile {
-    path: PathBuf,
-    options: Option<FileOperationOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The write file API.
-  WriteFile {
-    path: PathBuf,
-    contents: String,
-    options: Option<FileOperationOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The write binary file API.
-  WriteBinaryFile {
-    path: PathBuf,
-    contents: String,
-    options: Option<FileOperationOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The read dir API.
-  ReadDir {
-    path: PathBuf,
-    options: Option<DirOperationOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The copy file API.
-  CopyFile {
-    source: PathBuf,
-    destination: PathBuf,
-    options: Option<FileOperationOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The create dir API.
-  CreateDir {
-    path: PathBuf,
-    options: Option<DirOperationOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The remove dir API.
-  RemoveDir {
-    path: PathBuf,
-    options: Option<DirOperationOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The remove file API.
-  RemoveFile {
-    path: PathBuf,
-    options: Option<FileOperationOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The rename file API.
-  #[serde(rename_all = "camelCase")]
-  RenameFile {
-    old_path: PathBuf,
-    new_path: PathBuf,
-    options: Option<FileOperationOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The resolve path API
-  ResolvePath {
-    path: String,
-    directory: Option<BaseDirectory>,
-    callback: String,
-    error: String,
-  },
-  /// The set webview title API.
-  SetTitle {
-    title: String,
-  },
-  /// The execute script API.
-  Execute {
-    command: String,
-    args: Vec<String>,
-    callback: String,
-    error: String,
-  },
-  /// The open URL in browser API
-  Open {
-    uri: String,
-  },
-  ValidateSalt {
-    salt: String,
-    callback: String,
-    error: String,
-  },
-  /// The event listen API.
-  Listen {
-    event: String,
-    handler: String,
-    once: bool,
-  },
-  /// The event emit API.
-  Emit {
-    event: String,
-    payload: Option<String>,
-  },
-  /// The open dialog API.
-  OpenDialog {
-    options: OpenDialogOptions,
-    callback: String,
-    error: String,
-  },
-  /// The save dialog API.
-  SaveDialog {
-    options: SaveDialogOptions,
-    callback: String,
-    error: String,
-  },
-  MessageDialog {
-    message: String,
-  },
-  AskDialog {
-    title: Option<String>,
-    message: String,
-    callback: String,
-    error: String,
-  },
-  /// The HTTP request API.
-  HttpRequest {
-    options: Box<HttpRequestOptions>,
-    callback: String,
-    error: String,
-  },
-  /// The get CLI matches API.
-  CliMatches {
-    callback: String,
-    error: String,
-  },
-  /// The show notification API.
-  Notification {
-    options: NotificationOptions,
-    callback: String,
-    error: String,
-  },
-  /// The request notification permission API.
-  RequestNotificationPermission {
-    callback: String,
-    error: String,
-  },
-  /// The notification permission check API.
-  IsNotificationPermissionGranted {
-    callback: String,
-    error: String,
-  },
-}

+ 121 - 6
tauri/src/endpoints/dialog.rs

@@ -1,4 +1,3 @@
-use super::cmd::{OpenDialogOptions, SaveDialogOptions};
 use crate::{
   api::dialog::{
     ask as ask_dialog, message as message_dialog, pick_folder, save_file, select, select_multiple,
@@ -6,8 +5,129 @@ use crate::{
   },
   ApplicationDispatcherExt,
 };
+use serde::Deserialize;
 use serde_json::Value as JsonValue;
 
+use std::path::PathBuf;
+
+/// The options for the open dialog API.
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct OpenDialogOptions {
+  /// The initial path of the dialog.
+  pub filter: Option<String>,
+  /// Whether the dialog allows multiple selection or not.
+  #[serde(default)]
+  pub multiple: bool,
+  /// Whether the dialog is a directory selection (`true` value) or file selection (`false` value).
+  #[serde(default)]
+  pub directory: bool,
+  /// The initial path of the dialog.
+  pub default_path: Option<PathBuf>,
+}
+
+/// The options for the save dialog API.
+#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SaveDialogOptions {
+  /// The initial path of the dialog.
+  pub filter: Option<String>,
+  /// The initial path of the dialog.
+  pub default_path: Option<PathBuf>,
+}
+
+/// The API descriptor.
+#[derive(Deserialize)]
+#[serde(tag = "cmd", rename_all = "camelCase")]
+pub enum Cmd {
+  /// The open dialog API.
+  OpenDialog {
+    options: OpenDialogOptions,
+    callback: String,
+    error: String,
+  },
+  /// The save dialog API.
+  SaveDialog {
+    options: SaveDialogOptions,
+    callback: String,
+    error: String,
+  },
+  MessageDialog {
+    message: String,
+  },
+  AskDialog {
+    title: Option<String>,
+    message: String,
+    callback: String,
+    error: String,
+  },
+}
+
+impl Cmd {
+  pub async fn run<D: ApplicationDispatcherExt + 'static>(
+    self,
+    webview_manager: &crate::WebviewManager<D>,
+  ) -> crate::Result<()> {
+    match self {
+      Self::OpenDialog {
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(open_dialog)]
+        open(webview_manager, options, callback, error)?;
+        #[cfg(not(open_dialog))]
+        allowlist_error(webview_manager, error, "title");
+      }
+      Self::SaveDialog {
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(save_dialog)]
+        save(webview_manager, options, callback, error)?;
+        #[cfg(not(save_dialog))]
+        throw_allowlist_error(webview_manager, "saveDialog");
+      }
+      Self::MessageDialog { message } => {
+        let exe = std::env::current_exe()?;
+        let app_name = exe
+          .file_name()
+          .expect("failed to get exe filename")
+          .to_string_lossy()
+          .to_string();
+        webview_manager
+          .current_webview()?
+          .send_event(crate::webview::Event::Run(Box::new(move || {
+            message_dialog(app_name, message);
+          })));
+      }
+      Self::AskDialog {
+        title,
+        message,
+        callback,
+        error,
+      } => {
+        let exe = std::env::current_exe()?;
+        ask(
+          webview_manager,
+          title.unwrap_or_else(|| {
+            exe
+              .file_name()
+              .expect("failed to get exe filename")
+              .to_string_lossy()
+              .to_string()
+          }),
+          message,
+          callback,
+          error,
+        )?;
+      }
+    }
+    Ok(())
+  }
+}
+
 /// maps a dialog response to a JS value to eval
 #[cfg(any(open_dialog, save_dialog))]
 fn map_response(response: Response) -> JsonValue {
@@ -66,11 +186,6 @@ pub fn save<D: ApplicationDispatcherExt + 'static>(
   Ok(())
 }
 
-/// Shows a message in a dialog.
-pub fn message(title: String, message: String) {
-  message_dialog(message, title);
-}
-
 /// Shows a dialog with a yes/no question.
 pub fn ask<D: ApplicationDispatcherExt + 'static>(
   webview_manager: &crate::WebviewManager<D>,

+ 64 - 0
tauri/src/endpoints/event.rs

@@ -1,3 +1,53 @@
+use serde::Deserialize;
+
+/// The API descriptor.
+#[derive(Deserialize)]
+#[serde(tag = "cmd", rename_all = "camelCase")]
+pub enum Cmd {
+  /// The event listen API.
+  Listen {
+    event: String,
+    handler: String,
+    once: bool,
+  },
+  /// The event emit API.
+  Emit {
+    event: String,
+    payload: Option<String>,
+  },
+}
+
+impl Cmd {
+  pub async fn run<D: crate::ApplicationDispatcherExt + 'static>(
+    self,
+    webview_manager: &crate::WebviewManager<D>,
+  ) -> crate::Result<()> {
+    match self {
+      Self::Listen {
+        event,
+        handler,
+        once,
+      } => {
+        #[cfg(event)]
+        {
+          let js_string = listen_fn(event, handler, once)?;
+          webview_manager.current_webview()?.eval(&js_string);
+        }
+        #[cfg(not(event))]
+        throw_allowlist_error(webview_manager, "event");
+      }
+      Self::Emit { event, payload } => {
+        // TODO emit to optional window
+        #[cfg(event)]
+        webview_manager.current_webview()?.on_event(event, payload);
+        #[cfg(not(event))]
+        throw_allowlist_error(webview_manager, "event");
+      }
+    }
+    Ok(())
+  }
+}
+
 #[cfg(event)]
 pub fn listen_fn(event: String, handler: String, once: bool) -> crate::Result<String> {
   Ok(format!(
@@ -25,3 +75,17 @@ pub fn listen_fn(event: String, handler: String, once: bool) -> crate::Result<St
     once_flag = if once { "true" } else { "false" }
   ))
 }
+
+#[cfg(test)]
+mod test {
+  use proptest::prelude::*;
+
+  // check the listen_fn for various usecases.
+  proptest! {
+    #[cfg(event)]
+    #[test]
+    fn check_listen_fn(event in "", handler in "", once in proptest::bool::ANY) {
+      super::listen_fn(event, handler, once).expect("listen_fn failed");
+    }
+  }
+}

+ 276 - 2
tauri/src/endpoints/file_system.rs

@@ -1,10 +1,268 @@
-use crate::ApplicationDispatcherExt;
+use super::allowlist_error;
+use crate::{api::path::BaseDirectory, ApplicationDispatcherExt};
 
+use serde::Deserialize;
 use tauri_api::{dir, file, path::resolve_path};
 
 use std::{fs, fs::File, io::Write, path::PathBuf};
 
-use super::cmd::{DirOperationOptions, FileOperationOptions};
+/// The options for the directory functions on the file system API.
+#[derive(Deserialize)]
+pub struct DirOperationOptions {
+  /// Whether the API should recursively perform the operation on the directory.
+  #[serde(default)]
+  pub recursive: bool,
+  /// The base directory of the operation.
+  /// The directory path of the BaseDirectory will be the prefix of the defined directory path.
+  pub dir: Option<BaseDirectory>,
+}
+
+/// The options for the file functions on the file system API.
+#[derive(Deserialize)]
+pub struct FileOperationOptions {
+  /// The base directory of the operation.
+  /// The directory path of the BaseDirectory will be the prefix of the defined file path.
+  pub dir: Option<BaseDirectory>,
+}
+
+/// The API descriptor.
+#[derive(Deserialize)]
+#[serde(tag = "cmd", rename_all = "camelCase")]
+pub enum Cmd {
+  /// The read text file API.
+  ReadTextFile {
+    path: PathBuf,
+    options: Option<FileOperationOptions>,
+    callback: String,
+    error: String,
+  },
+  /// The read binary file API.
+  ReadBinaryFile {
+    path: PathBuf,
+    options: Option<FileOperationOptions>,
+    callback: String,
+    error: String,
+  },
+  /// The write file API.
+  WriteFile {
+    path: PathBuf,
+    contents: String,
+    options: Option<FileOperationOptions>,
+    callback: String,
+    error: String,
+  },
+  /// The write binary file API.
+  WriteBinaryFile {
+    path: PathBuf,
+    contents: String,
+    options: Option<FileOperationOptions>,
+    callback: String,
+    error: String,
+  },
+  /// The read dir API.
+  ReadDir {
+    path: PathBuf,
+    options: Option<DirOperationOptions>,
+    callback: String,
+    error: String,
+  },
+  /// The copy file API.
+  CopyFile {
+    source: PathBuf,
+    destination: PathBuf,
+    options: Option<FileOperationOptions>,
+    callback: String,
+    error: String,
+  },
+  /// The create dir API.
+  CreateDir {
+    path: PathBuf,
+    options: Option<DirOperationOptions>,
+    callback: String,
+    error: String,
+  },
+  /// The remove dir API.
+  RemoveDir {
+    path: PathBuf,
+    options: Option<DirOperationOptions>,
+    callback: String,
+    error: String,
+  },
+  /// The remove file API.
+  RemoveFile {
+    path: PathBuf,
+    options: Option<FileOperationOptions>,
+    callback: String,
+    error: String,
+  },
+  /// The rename file API.
+  #[serde(rename_all = "camelCase")]
+  RenameFile {
+    old_path: PathBuf,
+    new_path: PathBuf,
+    options: Option<FileOperationOptions>,
+    callback: String,
+    error: String,
+  },
+  /// The resolve path API
+  ResolvePath {
+    path: String,
+    directory: Option<BaseDirectory>,
+    callback: String,
+    error: String,
+  },
+}
+
+impl Cmd {
+  pub async fn run<D: ApplicationDispatcherExt + 'static>(
+    self,
+    webview_manager: &crate::WebviewManager<D>,
+  ) {
+    match self {
+      Self::ReadTextFile {
+        path,
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(read_text_file)]
+        read_text_file(webview_manager, path, options, callback, error).await;
+        #[cfg(not(read_text_file))]
+        allowlist_error(webview_manager, error, "readTextFile");
+      }
+      Self::ReadBinaryFile {
+        path,
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(read_binary_file)]
+        read_binary_file(webview_manager, path, options, callback, error).await;
+        #[cfg(not(read_binary_file))]
+        allowlist_error(webview_manager, error, "readBinaryFile");
+      }
+      Self::WriteFile {
+        path,
+        contents,
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(write_file)]
+        write_file(webview_manager, path, contents, options, callback, error).await;
+        #[cfg(not(write_file))]
+        allowlist_error(webview_manager, error, "writeFile");
+      }
+      Self::WriteBinaryFile {
+        path,
+        contents,
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(write_binary_file)]
+        write_binary_file(webview_manager, path, contents, options, callback, error).await;
+        #[cfg(not(write_binary_file))]
+        allowlist_error(webview_manager, error, "writeBinaryFile");
+      }
+      Self::ReadDir {
+        path,
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(read_dir)]
+        read_dir(webview_manager, path, options, callback, error).await;
+        #[cfg(not(read_dir))]
+        allowlist_error(webview_manager, error, "readDir");
+      }
+      Self::CopyFile {
+        source,
+        destination,
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(copy_file)]
+        copy_file(
+          webview_manager,
+          source,
+          destination,
+          options,
+          callback,
+          error,
+        )
+        .await;
+        #[cfg(not(copy_file))]
+        allowlist_error(webview_manager, error, "copyFile");
+      }
+      Self::CreateDir {
+        path,
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(create_dir)]
+        create_dir(webview_manager, path, options, callback, error).await;
+        #[cfg(not(create_dir))]
+        allowlist_error(webview_manager, error, "createDir");
+      }
+      Self::RemoveDir {
+        path,
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(remove_dir)]
+        remove_dir(webview_manager, path, options, callback, error).await;
+        #[cfg(not(remove_dir))]
+        allowlist_error(webview_manager, error, "removeDir");
+      }
+      Self::RemoveFile {
+        path,
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(remove_file)]
+        remove_file(webview_manager, path, options, callback, error).await;
+        #[cfg(not(remove_file))]
+        allowlist_error(webview_manager, error, "removeFile");
+      }
+      Self::RenameFile {
+        old_path,
+        new_path,
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(rename_file)]
+        rename_file(
+          webview_manager,
+          old_path,
+          new_path,
+          options,
+          callback,
+          error,
+        )
+        .await;
+        #[cfg(not(rename_file))]
+        allowlist_error(webview_manager, error, "renameFile");
+      }
+      Self::ResolvePath {
+        path,
+        directory,
+        callback,
+        error,
+      } => {
+        #[cfg(path_api)]
+        resolve_path_handler(webview_manager, path, directory, callback, error).await;
+        #[cfg(not(path_api))]
+        allowlist_error(webview_manager, error, "pathApi");
+      }
+    }
+  }
+}
 
 /// Reads a directory.
 #[cfg(read_dir)]
@@ -268,6 +526,22 @@ pub async fn read_binary_file<D: ApplicationDispatcherExt>(
   .await;
 }
 
+pub async fn resolve_path_handler<D: ApplicationDispatcherExt>(
+  webview_manager: &crate::WebviewManager<D>,
+  path: String,
+  directory: Option<BaseDirectory>,
+  callback: String,
+  error: String,
+) {
+  crate::execute_promise(
+    webview_manager,
+    async move { resolve_path(path, directory).map_err(|e| e.into()) },
+    callback,
+    error,
+  )
+  .await
+}
+
 // test webview functionality.
 #[cfg(test)]
 mod test {

+ 34 - 0
tauri/src/endpoints/http.rs

@@ -1,6 +1,40 @@
 use crate::ApplicationDispatcherExt;
+
+use serde::Deserialize;
 use tauri_api::http::{make_request as request, HttpRequestOptions};
 
+/// The API descriptor.
+#[derive(Deserialize)]
+#[serde(tag = "cmd", rename_all = "camelCase")]
+pub enum Cmd {
+  /// The HTTP request API.
+  HttpRequest {
+    options: Box<HttpRequestOptions>,
+    callback: String,
+    error: String,
+  },
+}
+
+impl Cmd {
+  pub async fn run<D: ApplicationDispatcherExt + 'static>(
+    self,
+    webview_manager: &crate::WebviewManager<D>,
+  ) {
+    match self {
+      Self::HttpRequest {
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(http_request)]
+        make_request(webview_manager, *options, callback, error).await;
+        #[cfg(not(http_request))]
+        allowlist_error(webview_manager, error, "httpRequest");
+      }
+    }
+  }
+}
+
 /// Makes an HTTP request and resolves the response to the webview
 pub async fn make_request<D: ApplicationDispatcherExt>(
   webview_manager: &crate::WebviewManager<D>,

+ 49 - 0
tauri/src/endpoints/internal.rs

@@ -0,0 +1,49 @@
+use serde::Deserialize;
+
+/// The API descriptor.
+#[derive(Deserialize)]
+#[serde(tag = "cmd", rename_all = "camelCase")]
+pub enum Cmd {
+  ValidateSalt {
+    salt: String,
+    callback: String,
+    error: String,
+  },
+}
+
+impl Cmd {
+  pub async fn run<D: crate::ApplicationDispatcherExt + 'static>(
+    self,
+    webview_manager: &crate::WebviewManager<D>,
+  ) -> crate::Result<()> {
+    match self {
+      Self::ValidateSalt {
+        salt,
+        callback,
+        error,
+      } => {
+        validate_salt(webview_manager, salt, callback, error)?;
+      }
+    }
+    Ok(())
+  }
+}
+
+/// Validates a salt.
+pub fn validate_salt<D: crate::ApplicationDispatcherExt>(
+  webview_manager: &crate::WebviewManager<D>,
+  salt: String,
+  callback: String,
+  error: String,
+) -> crate::Result<()> {
+  let response = if crate::salt::is_valid(salt) {
+    Ok("Valid")
+  } else {
+    Err("Invalid salt")
+  };
+  let callback_string = crate::api::rpc::format_callback_result(response, callback, error)?;
+  webview_manager
+    .current_webview()?
+    .eval(callback_string.as_str());
+  Ok(())
+}

+ 63 - 1
tauri/src/endpoints/notification.rs

@@ -1,8 +1,70 @@
-use super::cmd::NotificationOptions;
 use crate::ApplicationDispatcherExt;
+
+use serde::Deserialize;
 use serde_json::Value as JsonValue;
 use tauri_api::{config::Config, notification::Notification};
 
+/// The options for the notification API.
+#[derive(Deserialize)]
+pub struct NotificationOptions {
+  /// The notification title.
+  pub title: String,
+  /// The notification body.
+  pub body: Option<String>,
+  /// The notification icon.
+  pub icon: Option<String>,
+}
+
+/// The API descriptor.
+#[derive(Deserialize)]
+#[serde(tag = "cmd", rename_all = "camelCase")]
+pub enum Cmd {
+  /// The show notification API.
+  Notification {
+    options: NotificationOptions,
+    callback: String,
+    error: String,
+  },
+  /// The request notification permission API.
+  RequestNotificationPermission { callback: String, error: String },
+  /// The notification permission check API.
+  IsNotificationPermissionGranted { callback: String, error: String },
+}
+
+impl Cmd {
+  pub async fn run<D: ApplicationDispatcherExt + 'static>(
+    self,
+    webview_manager: &crate::WebviewManager<D>,
+    context: &crate::app::Context,
+  ) -> crate::Result<()> {
+    match self {
+      Self::Notification {
+        options,
+        callback,
+        error,
+      } => {
+        #[cfg(notification)]
+        send(webview_manager, options, callback, error, &context.config).await;
+        #[cfg(not(notification))]
+        allowlist_error(webview_manager, error, "notification");
+      }
+      Self::IsNotificationPermissionGranted { callback, error } => {
+        #[cfg(notification)]
+        is_permission_granted(webview_manager, callback, error).await;
+        #[cfg(not(notification))]
+        allowlist_error(webview_manager, error, "notification");
+      }
+      Self::RequestNotificationPermission { callback, error } => {
+        #[cfg(notification)]
+        request_permission(webview_manager, callback, error)?;
+        #[cfg(not(notification))]
+        allowlist_error(webview_manager, error, "notification");
+      }
+    }
+    Ok(())
+  }
+}
+
 pub async fn send<D: ApplicationDispatcherExt>(
   webview_manager: &crate::WebviewManager<D>,
   options: NotificationOptions,

+ 0 - 19
tauri/src/endpoints/path.rs

@@ -1,19 +0,0 @@
-#![cfg(path_api)]
-use crate::ApplicationDispatcherExt;
-use tauri_api::{path, path::BaseDirectory};
-
-pub async fn resolve_path<D: ApplicationDispatcherExt>(
-  webview_manager: &crate::WebviewManager<D>,
-  path: String,
-  directory: Option<BaseDirectory>,
-  callback: String,
-  error: String,
-) {
-  crate::execute_promise(
-    webview_manager,
-    async move { path::resolve_path(path, directory).map_err(|e| e.into()) },
-    callback,
-    error,
-  )
-  .await
-}

+ 0 - 20
tauri/src/endpoints/salt.rs

@@ -1,20 +0,0 @@
-use crate::ApplicationDispatcherExt;
-
-/// Validates a salt.
-pub fn validate<D: ApplicationDispatcherExt>(
-  webview_manager: &crate::WebviewManager<D>,
-  salt: String,
-  callback: String,
-  error: String,
-) -> crate::Result<()> {
-  let response = if crate::salt::is_valid(salt) {
-    Ok("Valid")
-  } else {
-    Err("Invalid salt")
-  };
-  let callback_string = crate::api::rpc::format_callback_result(response, callback, error)?;
-  webview_manager
-    .current_webview()?
-    .eval(callback_string.as_str());
-  Ok(())
-}

+ 65 - 0
tauri/src/endpoints/shell.rs

@@ -0,0 +1,65 @@
+use serde::Deserialize;
+
+/// The API descriptor.
+#[derive(Deserialize)]
+#[serde(tag = "cmd", rename_all = "camelCase")]
+pub enum Cmd {
+  /// The execute script API.
+  Execute {
+    command: String,
+    args: Vec<String>,
+    callback: String,
+    error: String,
+  },
+  /// The open URL in browser API
+  Open { uri: String },
+}
+
+impl Cmd {
+  pub async fn run<D: crate::ApplicationDispatcherExt + 'static>(
+    self,
+    webview_manager: &crate::WebviewManager<D>,
+  ) {
+    match self {
+      Self::Execute {
+        command,
+        args,
+        callback,
+        error,
+      } => {
+        #[cfg(execute)]
+        crate::call(webview_manager, command, args, callback, error).await;
+        #[cfg(not(execute))]
+        super::throw_allowlist_error(webview_manager, "execute");
+      }
+      Self::Open { uri } => {
+        #[cfg(open)]
+        open_browser(uri);
+        #[cfg(not(open))]
+        super::throw_allowlist_error(webview_manager, "open");
+      }
+    }
+  }
+}
+
+#[cfg(open)]
+pub fn open_browser(uri: String) {
+  #[cfg(test)]
+  assert!(uri.contains("http://"));
+
+  #[cfg(not(test))]
+  webbrowser::open(&uri).expect("Failed to open webbrowser with uri");
+}
+
+#[cfg(test)]
+mod test {
+  use proptest::prelude::*;
+  // Test the open func to see if proper uris can be opened by the browser.
+  proptest! {
+    #[cfg(open)]
+    #[test]
+    fn check_open(uri in r"(http://)([\\w\\d\\.]+([\\w]{2,6})?)") {
+      super::open_browser(uri);
+    }
+  }
+}

+ 25 - 0
tauri/src/endpoints/window.rs

@@ -0,0 +1,25 @@
+use serde::Deserialize;
+
+/// The API descriptor.
+#[derive(Deserialize)]
+#[serde(tag = "cmd", rename_all = "camelCase")]
+pub enum Cmd {
+  /// The set webview title API.
+  SetTitle { title: String },
+}
+
+impl Cmd {
+  pub async fn run<D: crate::ApplicationDispatcherExt + 'static>(
+    self,
+    webview_manager: &crate::WebviewManager<D>,
+  ) -> crate::Result<()> {
+    match self {
+      Self::SetTitle { title } => {
+        webview_manager.current_webview()?.set_title(&title);
+        #[cfg(not(set_title))]
+        throw_allowlist_error(webview_manager, "title");
+      }
+    }
+    Ok(())
+  }
+}

+ 3 - 3
tauri/src/error.rs

@@ -20,8 +20,8 @@ pub enum Error {
   #[error("JSON error: {0}")]
   Json(serde_json::Error),
   /// Unknown API type.
-  #[error("unknown API")]
-  UnknownApi,
+  #[error("unknown API: {0:?}")]
+  UnknownApi(Option<serde_json::Error>),
   /// Failed to execute tauri API.
   #[error("failed to execute API: {0}")]
   FailedToExecuteApi(#[from] tauri_api::Error),
@@ -36,7 +36,7 @@ pub enum Error {
 impl From<serde_json::Error> for Error {
   fn from(error: serde_json::Error) -> Self {
     if error.to_string().contains("unknown variant") {
-      Self::UnknownApi
+      Self::UnknownApi(Some(error))
     } else {
       Self::Json(error)
     }

+ 2 - 2
tauri/src/plugin.rs

@@ -42,7 +42,7 @@ pub trait Plugin<D: ApplicationDispatcherExt + 'static>: Send + Sync {
     webview_manager: WebviewManager<D>,
     payload: &str,
   ) -> crate::Result<()> {
-    Err(crate::Error::UnknownApi)
+    Err(crate::Error::UnknownApi(None))
   }
 }
 
@@ -133,7 +133,7 @@ pub(crate) async fn extend_api<D: ApplicationDispatcherExt + 'static>(
         return Ok(true);
       }
       Err(e) => match e {
-        crate::Error::UnknownApi => {}
+        crate::Error::UnknownApi(_) => {}
         _ => return Err(e),
       },
     }

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff