Skip to content

Commit

Permalink
feat(core): allow defining a custom invoke system (#2899)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasfernog committed Nov 16, 2021
1 parent dd1d2b6 commit 15164d9
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 181 deletions.
5 changes: 5 additions & 0 deletions .changes/custom-invoke-system.md
@@ -0,0 +1,5 @@
---
"tauri": patch
---

Added an API to use a custom invoke system to receive and respond to commands (`Builder#invoke_system`).
2 changes: 1 addition & 1 deletion core/tauri/scripts/bundle.js

Large diffs are not rendered by default.

127 changes: 29 additions & 98 deletions core/tauri/scripts/core.js
Expand Up @@ -2,7 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

;(function () {
;
(function () {
function uid() {
const length = new Int8Array(1)
window.crypto.getRandomValues(length)
Expand All @@ -11,58 +12,6 @@
return array.join('')
}

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
}

if (!window.__TAURI__) {
window.__TAURI__ = {}
}
Expand Down Expand Up @@ -103,30 +52,24 @@
return reject(new Error('Invalid argument type.'))
}

if (window.rpc) {
window.rpc.notify(
cmd,
_objectSpread(
{
callback: callback,
error: error,
__invokeKey: key || __TAURI_INVOKE_KEY__
},
args
)
if (window.__TAURI_POST_MESSAGE__) {
window.__TAURI_POST_MESSAGE__(
cmd, {
...args,
callback: callback,
error: error,
__invokeKey: key || __TAURI_INVOKE_KEY__
}
)
} else {
window.addEventListener('DOMContentLoaded', function () {
window.rpc.notify(
cmd,
_objectSpread(
{
callback: callback,
error: error,
__invokeKey: key || __TAURI_INVOKE_KEY__
},
args
)
window.__TAURI_POST_MESSAGE__(
cmd, {
...args,
callback: callback,
error: error,
__invokeKey: key || __TAURI_INVOKE_KEY__
}
)
})
}
Expand All @@ -147,8 +90,7 @@
target.target === '_blank'
) {
window.__TAURI_INVOKE__(
'tauri',
{
'tauri', {
__tauriModule: 'Shell',
message: {
cmd: 'open',
Expand Down Expand Up @@ -188,8 +130,7 @@
if (e.target.hasAttribute('data-tauri-drag-region') && e.buttons === 1) {
// start dragging if the element has a `tauri-drag-region` data attribute and maximize on double-clicking it
window.__TAURI_INVOKE__(
'tauri',
{
'tauri', {
__tauriModule: 'Window',
message: {
cmd: 'manage',
Expand All @@ -206,8 +147,7 @@
})

window.__TAURI_INVOKE__(
'tauri',
{
'tauri', {
__tauriModule: 'Event',
message: {
cmd: 'listen',
Expand All @@ -233,8 +173,7 @@
return Promise.resolve(window.Notification.permission === 'granted')
}
return window.__TAURI_INVOKE__(
'tauri',
{
'tauri', {
__tauriModule: 'Notification',
message: {
cmd: 'isNotificationPermissionGranted'
Expand All @@ -253,8 +192,7 @@
function requestPermission() {
return window
.__TAURI_INVOKE__(
'tauri',
{
'tauri', {
__tauriModule: 'Notification',
message: {
cmd: 'requestNotificationPermission'
Expand All @@ -276,17 +214,13 @@
isPermissionGranted().then(function (permission) {
if (permission) {
return window.__TAURI_INVOKE__(
'tauri',
{
'tauri', {
__tauriModule: 'Notification',
message: {
cmd: 'notification',
options:
typeof options === 'string'
? {
title: options
}
: options
options: typeof options === 'string' ? {
title: options
} : options
}
},
_KEY_VALUE_
Expand Down Expand Up @@ -329,8 +263,7 @@

window.alert = function (message) {
window.__TAURI_INVOKE__(
'tauri',
{
'tauri', {
__tauriModule: 'Dialog',
message: {
cmd: 'messageDialog',
Expand All @@ -343,8 +276,7 @@

window.confirm = function (message) {
return window.__TAURI_INVOKE__(
'tauri',
{
'tauri', {
__tauriModule: 'Dialog',
message: {
cmd: 'confirmDialog',
Expand All @@ -359,8 +291,7 @@
if (navigator.userAgent.includes('Mac')) {
window.print = function () {
return window.__TAURI_INVOKE__(
'tauri',
{
'tauri', {
__tauriModule: 'Window',
message: {
cmd: 'manage',
Expand Down
31 changes: 29 additions & 2 deletions core/tauri/src/app.rs
Expand Up @@ -7,7 +7,9 @@ pub(crate) mod tray;

use crate::{
command::{CommandArg, CommandItem},
hooks::{InvokeHandler, OnPageLoad, PageLoadPayload, SetupHook},
hooks::{
window_invoke_responder, InvokeHandler, InvokeResponder, OnPageLoad, PageLoadPayload, SetupHook,
},
manager::{Asset, CustomProtocol, WindowManager},
plugin::{Plugin, PluginStore},
runtime::{
Expand All @@ -19,7 +21,7 @@ use crate::{
sealed::{ManagerBase, RuntimeOrDispatch},
utils::assets::Assets,
utils::config::{Config, WindowUrl},
Context, Invoke, InvokeError, Manager, StateManager, Window,
Context, Invoke, InvokeError, InvokeResponse, Manager, StateManager, Window,
};

use tauri_macros::default_runtime;
Expand Down Expand Up @@ -582,6 +584,12 @@ pub struct Builder<R: Runtime> {
/// The JS message handler.
invoke_handler: Box<InvokeHandler<R>>,

/// The JS message responder.
invoke_responder: Arc<InvokeResponder<R>>,

/// The script that initializes the `window.__TAURI_POST_MESSAGE__` function.
invoke_initialization_script: String,

/// The setup hook.
setup: SetupHook<R>,

Expand Down Expand Up @@ -624,6 +632,9 @@ impl<R: Runtime> Builder<R> {
Self {
setup: Box::new(|_| Ok(())),
invoke_handler: Box::new(|_| ()),
invoke_responder: Arc::new(window_invoke_responder),
invoke_initialization_script:
"Object.defineProperty(window, '__TAURI_POST_MESSAGE__', { value: (cmd, args) => window.rpc.notify(cmd, args) })".into(),
on_page_load: Box::new(|_, _| ()),
pending_windows: Default::default(),
plugins: PluginStore::default(),
Expand All @@ -648,6 +659,21 @@ impl<R: Runtime> Builder<R> {
self
}

/// Defines a custom JS message system.
///
/// The `responder` is a function that will be called when a command has been executed and must send a response to the JS layer.
///
/// The `initialization_script` is a script that initializes `window.__TAURI_POST_MESSAGE__`.
/// That function must take the `command: string` and `args: object` types and send a message to the backend.
pub fn invoke_system<F>(mut self, initialization_script: String, responder: F) -> Self
where
F: Fn(Window<R>, InvokeResponse, String, String) + Send + Sync + 'static,
{
self.invoke_initialization_script = initialization_script;
self.invoke_responder = Arc::new(responder);
self
}

/// Defines the setup hook.
pub fn setup<F>(mut self, setup: F) -> Self
where
Expand Down Expand Up @@ -905,6 +931,7 @@ impl<R: Runtime> Builder<R> {
self.state,
self.window_event_listeners,
(self.menu, self.menu_event_listeners),
(self.invoke_responder, self.invoke_initialization_script),
);

// set up all the windows defined in the config
Expand Down

0 comments on commit 15164d9

Please sign in to comment.