Browse Source

feat(core) add cargo examples (#499)

* add cargo example

* change name to communication

* update scripts to set environment vars for example

* remove build key
Tensor-Programming 5 years ago
parent
commit
4e76f42d8a
32 changed files with 606 additions and 7 deletions
  1. 2 2
      .scripts/init_env.bat
  2. 2 2
      .scripts/init_env.ps1
  3. 2 2
      .scripts/init_env.sh
  4. 8 1
      tauri/Cargo.toml
  5. 43 0
      tauri/examples/communication/dist/index.html
  6. 347 0
      tauri/examples/communication/dist/index.tauri.html
  7. 10 0
      tauri/examples/communication/package.json
  8. 11 0
      tauri/examples/communication/src-tauri/.gitignore
  9. 39 0
      tauri/examples/communication/src-tauri/Cargo.toml
  10. BIN
      tauri/examples/communication/src-tauri/icons/128x128.png
  11. BIN
      tauri/examples/communication/src-tauri/icons/128x128@2x.png
  12. BIN
      tauri/examples/communication/src-tauri/icons/32x32.png
  13. BIN
      tauri/examples/communication/src-tauri/icons/Square107x107Logo.png
  14. BIN
      tauri/examples/communication/src-tauri/icons/Square142x142Logo.png
  15. BIN
      tauri/examples/communication/src-tauri/icons/Square150x150Logo.png
  16. BIN
      tauri/examples/communication/src-tauri/icons/Square284x284Logo.png
  17. BIN
      tauri/examples/communication/src-tauri/icons/Square30x30Logo.png
  18. BIN
      tauri/examples/communication/src-tauri/icons/Square310x310Logo.png
  19. BIN
      tauri/examples/communication/src-tauri/icons/Square44x44Logo.png
  20. BIN
      tauri/examples/communication/src-tauri/icons/Square71x71Logo.png
  21. BIN
      tauri/examples/communication/src-tauri/icons/Square89x89Logo.png
  22. BIN
      tauri/examples/communication/src-tauri/icons/StoreLogo.png
  23. BIN
      tauri/examples/communication/src-tauri/icons/icon.icns
  24. BIN
      tauri/examples/communication/src-tauri/icons/icon.ico
  25. BIN
      tauri/examples/communication/src-tauri/icons/icon.png
  26. 13 0
      tauri/examples/communication/src-tauri/rustfmt.toml
  27. 16 0
      tauri/examples/communication/src-tauri/src/build.rs
  28. 14 0
      tauri/examples/communication/src-tauri/src/cmd.rs
  29. 64 0
      tauri/examples/communication/src-tauri/src/main.rs
  30. 33 0
      tauri/examples/communication/src-tauri/tauri.conf.json
  31. 1 0
      tauri/src/lib.rs
  32. 1 0
      tauri/src/view.rs

+ 2 - 2
.scripts/init_env.bat

@@ -8,8 +8,8 @@ IF "%cd%\"=="%~dp0" (
 )
 
 rem setup relative paths from root folder
-set "TAURI_DIST_DIR=%~1tauri\test\fixture\dist"
-set "TAURI_DIR=%~1tauri\test\fixture\src-tauri"
+set "TAURI_DIST_DIR=%~1tauri\examples\communication\dist"
+set "TAURI_DIR=%~1tauri\examples\communication\src-tauri"
 rem convert relative path to absolute path and re-set it into the enviroment var
 for /F "delims=" %%F IN ("%TAURI_DIST_DIR%") DO SET "TAURI_DIST_DIR=%%~fF"
 for /F "delims=" %%F IN ("%TAURI_DIR%") DO SET "TAURI_DIR=%%~fF"

+ 2 - 2
.scripts/init_env.ps1

@@ -1,7 +1,7 @@
 Write-Output "Setting up enviromental Variables"
 # setup relative paths
-$dist_path = "tauri\test\fixture\dist"
-$src_path = "tauri\test\fixture\src-tauri"
+$dist_path = "tauri\examples\communication\dist"
+$src_path = "tauri\examples\communication\src-tauri"
 
 # check to see if path variables are directories
 if ((Test-Path $dist_path -PathType Any) -Or (Test-Path $src_path -PathType Any)) {

+ 2 - 2
.scripts/init_env.sh

@@ -2,8 +2,8 @@
 # Note: Script must be run like this `. .init_env.sh` to setup variables for your current shell
 # define relative paths
 
-DistPath='tauri/test/fixture/dist'
-SrcPath='tauri/test/fixture/src-tauri'
+DistPath='tauri/examples/communication/dist'
+SrcPath='tauri/examples/communication/src-tauri'
 
 echo "Setting up enviroment Variables"
 

+ 8 - 1
tauri/Cargo.toml

@@ -31,6 +31,9 @@ tauri_includedir_codegen = "0.5.2"
 
 [dev-dependencies]
 proptest = "0.9.5"
+serde_json = "1.0"
+tauri = {path = ".", features = [ "all-api", "edge" ]}
+serde = { version = "1.0", features = [ "derive" ] }
 
 [features]
 edge = ["web-view/edge"]
@@ -50,5 +53,9 @@ event = []
 updater = []
 
 [package.metadata.docs.rs]
+features = ["dev-server", "all-api"]
+
+[[example]]
+name = "communication"
+path = "examples/communication/src-tauri/src/main.rs"
 
-features = ["dev-server", "all-api"]

+ 43 - 0
tauri/examples/communication/dist/index.html

@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <div>
+      <button id="log">Call Log API</button>
+      <button id="request">Call Request (async) API</button>
+      <button id="event">Send event to Rust</button>
+      <div id="response"></div>
+    </div>
+    <script>
+      window.onTauriInit = function () {
+        window.tauri.listen('rust-event', function (res) {
+          document.getElementById('response').innerHTML = JSON.stringify(res)
+        })
+      }
+
+      document.getElementById('log').addEventListener('click', function () {
+        window.tauri.invoke({
+          cmd: 'logOperation',
+          event: 'tauri-click',
+          payload: 'this payload is optional because we used Option in Rust'
+        })
+      })
+
+      document.getElementById('request').addEventListener('click', function () {
+        window.tauri.promisified({
+          cmd: 'performRequest',
+          endpoint: 'dummy endpoint arg',
+          body: {
+            id: 5,
+            name: 'test'
+          }
+        }).then(function (response) {
+          document.getElementById('response').innerHTML = JSON.stringify(response)
+        })
+      })
+
+      document.getElementById('event').addEventListener('click', function () {
+        window.tauri.emit('js-event', 'this is the payload string')
+      })
+    </script>
+  </body>
+</html>

+ 347 - 0
tauri/examples/communication/dist/index.tauri.html

@@ -0,0 +1,347 @@
+<!DOCTYPE html><html><head><meta http-equiv="Content-Security-Policy" content="default-src blob: data: filesystem: ws: http: https: 'unsafe-eval' 'unsafe-inline'"></head><body><script>/* eslint-disable */
+
+/**
+ *  * THIS FILE IS GENERATED AUTOMATICALLY.
+ * DO NOT EDIT.
+ *
+ * Please whitelist these API functions in tauri.conf.json
+ *
+ **/
+
+/**
+ * @module tauri
+ * @description This API interface makes powerful interactions available
+ * to be run on client side applications. They are opt-in features, and
+ * must be enabled in tauri.conf.json
+ *
+ * Each binding MUST provide these interfaces in order to be compliant,
+ * and also whitelist them based upon the developer's settings.
+ */
+
+// polyfills
+if (!String.prototype.startsWith) {
+  String.prototype.startsWith = function (searchString, position) {
+    position = position || 0
+    return this.substr(position, searchString.length) === searchString
+  }
+}
+
+// makes the window.external.invoke API available after window.location.href changes
+
+switch (navigator.platform) {
+  case "Macintosh":
+  case "MacPPC":
+  case "MacIntel":
+  case "Mac68K":
+    window.external = this
+    invoke = function (x) {
+      webkit.messageHandlers.invoke.postMessage(x);
+    }
+    break;
+  case "Windows":
+  case "WinCE":
+  case "Win32":
+  case "Win64":
+    break;
+  default: 
+    window.external = this
+    invoke = function (x) {
+      window.webkit.messageHandlers.external.postMessage(x);
+    }
+    break;
+}
+
+
+function s4() {
+  return Math.floor((1 + Math.random()) * 0x10000)
+    .toString(16)
+    .substring(1)
+}
+
+var uid = function () {
+  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
+    s4() + '-' + s4() + s4() + s4()
+}
+
+function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
+
+function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
+
+function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+
+
+
+var __reject = function () {
+  return new Promise(function (_, reject) {
+    reject();
+  });
+}
+
+window.tauri = {
+  
+  invoke: function invoke(args) {
+    window.external.invoke(JSON.stringify(args));
+  },
+
+  
+  listen: function listen(event, handler) {
+    
+    var once = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+      this.invoke({
+        cmd: 'listen',
+        event: event,
+        handler: window.tauri.transformCallback(handler, once),
+        once: once
+      });
+    
+  },
+
+  
+  emit: function emit(evt, payload) {
+    
+      this.invoke({
+        cmd: 'emit',
+        event: evt,
+        payload: payload || ''
+      });
+    
+  },
+
+  
+  transformCallback: function transformCallback(callback) {
+    var once = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+    var identifier = uid();
+
+    window[identifier] = function (result) {
+      if (once) {
+        delete window[identifier];
+      }
+
+      return callback && callback(result);
+    };
+
+    return identifier;
+  },
+
+  
+  promisified: function promisified(args) {
+    var _this = this;
+
+    return new Promise(function (resolve, reject) {
+      _this.invoke(_objectSpread({
+        callback: _this.transformCallback(resolve),
+        error: _this.transformCallback(reject)
+      }, args));
+    });
+  },
+
+  
+  readTextFile: function readTextFile(path) {
+    
+      return this.promisified({
+        cmd: 'readTextFile',
+        path: path
+      });
+    
+  },
+
+  
+  readBinaryFile: function readBinaryFile(path) {
+    
+      return this.promisified({
+        cmd: 'readBinaryFile',
+        path: path
+      });
+    
+  },
+
+  
+  writeFile: function writeFile(cfg) {
+    
+      if (_typeof(cfg) === 'object') {
+        Object.freeze(cfg);
+      }
+      this.invoke({
+        cmd: 'writeFile',
+        file: cfg.file,
+        contents: cfg.contents
+      });
+    
+  },
+
+  
+  listFiles: function listFiles(path) {
+    
+      return this.promisified({
+        cmd: 'listFiles',
+        path: path
+      });
+    
+  },
+
+  
+  listDirs: function listDirs(path) {
+    
+      return this.promisified({
+        cmd: 'listDirs',
+        path: path
+      });
+    
+  },
+
+  
+  setTitle: function setTitle(title) {
+    
+      this.invoke({
+        cmd: 'setTitle',
+        title: title
+      });
+    
+  },
+
+  
+  open: function open(uri) {
+    
+      this.invoke({
+        cmd: 'open',
+        uri: uri
+      });
+    
+  },
+
+  
+  execute: function execute(command, args) {
+    
+
+      if (_typeof(args) === 'object') {
+        Object.freeze(args);
+      }
+
+      return this.promisified({
+        cmd: 'execute',
+        command: command,
+        args: typeof args === 'string' ? [args] : args
+      });
+    
+  },
+
+bridge: function bridge(command, payload) {
+    
+
+    if (_typeof(payload) === 'object') {
+      Object.freeze(payload);
+    }
+
+    return this.promisified({
+      cmd: 'bridge',
+      command: command,
+      payload: _typeof(payload) === 'object' ? [payload] : payload
+    });
+    
+  },
+
+loadAsset: function loadAsset(assetName, assetType) {
+  return this.promisified({
+    cmd: 'loadAsset',
+    asset: assetName,
+    asset_type: assetType || 'unknown'
+  })
+}
+};
+
+// init tauri API
+try {
+  window.tauri.invoke({
+    cmd: 'init'
+  })
+} catch (e) {
+  window.addEventListener('DOMContentLoaded', function () {
+    window.tauri.invoke({
+      cmd: 'init'
+    })
+  }, true)
+}
+
+document.addEventListener('error', function (e) {
+  var target = e.target
+  while (target != null) {
+    if (target.matches ? target.matches('img') : target.msMatchesSelector('img')) {
+      window.tauri.loadAsset(target.src, 'image')
+        .then(function (img) {
+          target.src = img
+        })
+      break
+    }
+    target = target.parentElement
+  }
+}, true)
+
+// open <a href="..."> links with the Tauri API
+function __openLinks() {
+  document.querySelector('body').addEventListener('click', function (e) {
+    var target = e.target
+    while (target != null) {
+      if (target.matches ? target.matches('a') : target.msMatchesSelector('a')) {
+        if (target.href && target.href.startsWith('http') && target.target === '_blank') {
+          window.tauri.open(target.href)
+          e.preventDefault()
+        }
+        break
+      }
+      target = target.parentElement
+    }
+  }, true)
+}
+
+if (document.readyState === 'complete' || document.readyState === 'interactive') {
+  __openLinks()
+} else {
+  window.addEventListener('DOMContentLoaded', function () {
+    __openLinks()
+  }, true)
+}
+</script>
+    <div>
+      <button id="log">Call Log API</button>
+      <button id="request">Call Request (async) API</button>
+      <button id="event">Send event to Rust</button>
+      <div id="response"></div>
+    </div>
+    <script>
+      window.onTauriInit = function () {
+        window.tauri.listen('rust-event', function (res) {
+          document.getElementById('response').innerHTML = JSON.stringify(res)
+        })
+      }
+
+      document.getElementById('log').addEventListener('click', function () {
+        window.tauri.invoke({
+          cmd: 'logOperation',
+          event: 'tauri-click',
+          payload: 'this payload is optional because we used Option in Rust'
+        })
+      })
+
+      document.getElementById('request').addEventListener('click', function () {
+        window.tauri.promisified({
+          cmd: 'performRequest',
+          endpoint: 'dummy endpoint arg',
+          body: {
+            id: 5,
+            name: 'test'
+          }
+        }).then(function (response) {
+          document.getElementById('response').innerHTML = JSON.stringify(response)
+        })
+      })
+
+      document.getElementById('event').addEventListener('click', function () {
+        window.tauri.emit('js-event', 'this is the payload string')
+      })
+    </script>
+  
+</body></html>

+ 10 - 0
tauri/examples/communication/package.json

@@ -0,0 +1,10 @@
+{
+  "name": "communication-example",
+  "version": "1.0.0",
+  "description": "A Tauri example showcasing the JS-Rust communication",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "private": true
+}

+ 11 - 0
tauri/examples/communication/src-tauri/.gitignore

@@ -0,0 +1,11 @@
+# Generated by Cargo
+# will have compiled files and executables
+/target/
+WixTools
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+tauri.js
+config.json
+bundle.json

+ 39 - 0
tauri/examples/communication/src-tauri/Cargo.toml

@@ -0,0 +1,39 @@
+workspace = { }
+
+[package]
+name = "app"
+version = "0.1.0"
+description = "A Tauri App"
+authors = [ "you" ]
+license = ""
+repository = ""
+default-run = "app"
+edition = "2018"
+build = "src/build.rs"
+
+[package.metadata.bundle]
+identifier = "com.tauri.dev"
+icon = [
+  "icons/32x32.png",
+  "icons/128x128.png",
+  "icons/128x128@2x.png",
+  "icons/icon.icns",
+  "icons/icon.ico"
+]
+
+[dependencies]
+serde_json = "1.0"
+serde = { version = "1.0", features = [ "derive" ] }
+tauri = { version = "0.4", features = [ "all-api", "edge" ] }
+
+[target."cfg(windows)".build-dependencies]
+winres = "0.1"
+
+[features]
+dev-server = [ "tauri/dev-server" ]
+embedded-server = [ "tauri/embedded-server" ]
+no-server = [ "tauri/no-server" ]
+
+[[bin]]
+name = "app"
+path = "src/main.rs"

BIN
tauri/examples/communication/src-tauri/icons/128x128.png


BIN
tauri/examples/communication/src-tauri/icons/128x128@2x.png


BIN
tauri/examples/communication/src-tauri/icons/32x32.png


BIN
tauri/examples/communication/src-tauri/icons/Square107x107Logo.png


BIN
tauri/examples/communication/src-tauri/icons/Square142x142Logo.png


BIN
tauri/examples/communication/src-tauri/icons/Square150x150Logo.png


BIN
tauri/examples/communication/src-tauri/icons/Square284x284Logo.png


BIN
tauri/examples/communication/src-tauri/icons/Square30x30Logo.png


BIN
tauri/examples/communication/src-tauri/icons/Square310x310Logo.png


BIN
tauri/examples/communication/src-tauri/icons/Square44x44Logo.png


BIN
tauri/examples/communication/src-tauri/icons/Square71x71Logo.png


BIN
tauri/examples/communication/src-tauri/icons/Square89x89Logo.png


BIN
tauri/examples/communication/src-tauri/icons/StoreLogo.png


BIN
tauri/examples/communication/src-tauri/icons/icon.icns


BIN
tauri/examples/communication/src-tauri/icons/icon.ico


BIN
tauri/examples/communication/src-tauri/icons/icon.png


+ 13 - 0
tauri/examples/communication/src-tauri/rustfmt.toml

@@ -0,0 +1,13 @@
+max_width = 100
+hard_tabs = false
+tab_spaces = 2
+newline_style = "Auto"
+use_small_heuristics = "Default"
+reorder_imports = true
+reorder_modules = true
+remove_nested_parens = true
+edition = "2018"
+merge_derives = true
+use_try_shorthand = false
+use_field_init_shorthand = false
+force_explicit_abi = true

+ 16 - 0
tauri/examples/communication/src-tauri/src/build.rs

@@ -0,0 +1,16 @@
+#[cfg(windows)]
+extern crate winres;
+
+#[cfg(windows)]
+fn main() {
+  if std::path::Path::new("icons/icon.ico").exists() {
+    let mut res = winres::WindowsResource::new();
+    res.set_icon("icons/icon.ico");
+    res.compile().expect("Unable to find visual studio tools");
+  } else {
+    panic!("No Icon.ico found. Please add one or check the path");
+  }
+}
+
+#[cfg(not(windows))]
+fn main() {}

+ 14 - 0
tauri/examples/communication/src-tauri/src/cmd.rs

@@ -0,0 +1,14 @@
+use serde::Deserialize;
+
+#[derive(Debug, Deserialize)]
+pub struct RequestBody {
+  id: i32,
+  name: String
+}
+
+#[derive(Deserialize)]
+#[serde(tag = "cmd", rename_all = "camelCase")]
+pub enum Cmd {
+  LogOperation { event: String, payload: Option<String> },
+  PerformRequest { endpoint: String, body: RequestBody, callback: String, error: String },
+}

+ 64 - 0
tauri/examples/communication/src-tauri/src/main.rs

@@ -0,0 +1,64 @@
+#![cfg_attr(
+  all(not(debug_assertions), target_os = "windows"),
+  windows_subsystem = "windows"
+)]
+
+mod cmd;
+
+use serde::Serialize;
+
+#[derive(Serialize)]
+struct Reply {
+  data: String
+}
+
+fn main() {
+  tauri::AppBuilder::new()
+    .setup(|webview, _source| {
+      let handle = webview.handle();
+      tauri::event::listen(String::from("js-event"), move |msg| {
+        println!("got js-event with message '{}'", msg);
+        let reply = Reply {
+          data: "something else".to_string(),
+        };
+
+        tauri::event::emit(
+          &handle,
+          String::from("rust-event"),
+          serde_json::to_string(&reply).unwrap(),
+        );
+      });
+    })
+    .invoke_handler(|_webview, arg| {
+      use cmd::Cmd::*;
+      match serde_json::from_str(arg) {
+        Err(_) => {}
+        Ok(command) => {
+          match command {
+            LogOperation { event, payload } => {
+              println!("{} {:?}", event, payload);
+            },
+            PerformRequest { endpoint, body, callback, error } => {
+              // tauri::execute_promise is a helper for APIs that uses the tauri.promisified JS function
+              // so you can easily communicate between JS and Rust with promises
+              tauri::execute_promise(
+                _webview,
+                move || {
+                  println!("{} {:?}", endpoint, body);
+                  // perform an async operation here
+                  // if the returned value is Ok, the promise will be resolved with its value
+                  // if the returned value is Err, the promise will be rejected with its value
+                  // the value is a string that will be eval'd
+                  Ok("{ key: 'response', value: [{ id: 3 }] }".to_string())
+                },
+                callback,
+                error
+              )
+            },
+          }
+        }
+      }
+    })
+    .build()
+    .run();
+}

+ 33 - 0
tauri/examples/communication/src-tauri/tauri.conf.json

@@ -0,0 +1,33 @@
+{
+  "build": {
+    "distDir": "../dist",
+    "devPath": "../dist"
+  },
+  "ctx": {},
+  "tauri": {
+    "embeddedServer": {
+      "active": true
+    },
+    "bundle": {
+      "active": true,
+      "icon": [
+        "icons/32x32.png", "icons/128x128.png", "icons/128x128@2x.png", "icons/icon.icns", "icons/icon.ico"
+      ]
+    },
+    "whitelist": {
+      "all": true
+    },
+    "window": {
+      "title": "Tauri App"
+    },
+    "security": {
+      "csp": "default-src blob: data: filesystem: ws: http: https: 'unsafe-eval' 'unsafe-inline'"
+    },
+    "edge": {
+      "active": true
+    },
+    "inliner": {
+      "active": true
+    }
+  }
+}

+ 1 - 0
tauri/src/lib.rs

@@ -18,6 +18,7 @@ mod file_system;
 mod salt;
 #[cfg(feature = "embedded-server")]
 mod tcp;
+mod view;
 
 use std::process::Stdio;
 

+ 1 - 0
tauri/src/view.rs

@@ -0,0 +1 @@
+