5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-04 02:39:30 +08:00

Radical JS runtime overhaul. New @wailsio/runtime package

This commit is contained in:
Lea Anthony 2023-12-28 18:54:30 +11:00
parent d1255d3a9d
commit b08126d745
No known key found for this signature in database
GPG Key ID: 33DAF7BB90A58405
61 changed files with 1809 additions and 4726 deletions

View File

@ -1,3 +1,3 @@
# Runtime
To rebuild the runtime run `task build-runtime` or if you have Wails v3 CLI, you can use `wails task build-runtime`.
To rebuild the runtime run `task build-runtime` or if you have Wails v3 CLI, you can use `wails3 task build-runtime`.

View File

@ -21,82 +21,18 @@ tasks:
build:debug:
internal: true
cmds:
- npx esbuild desktop/main.js --bundle --tree-shaking=true --sourcemap=inline --outfile=runtime_debug_desktop_{{.PLATFORM}}.js --define:DEBUG=true --define:WINDOWS={{.WINDOWS}} --define:DARWIN={{.DARWIN}} --define:LINUX={{.LINUX}} --define:PLATFORM={{.PLATFORM}} --define:INVOKE={{.INVOKE}}
build:debug:windows:
cmds:
- task: build:debug
vars:
WINDOWS: true
DARWIN: false
LINUX: false
PLATFORM: windows
INVOKE: "chrome.webview.postMessage"
build:debug:linux:
cmds:
- task: build:debug
vars:
WINDOWS: false
DARWIN: false
LINUX: true
PLATFORM: linux
INVOKE: "webkit.messageHandlers.external.postMessage"
build:debug:darwin:
cmds:
- task: build:debug
vars:
WINDOWS: false
DARWIN: true
LINUX: false
PLATFORM: darwin
INVOKE: "webkit.messageHandlers.external.postMessage"
- npx esbuild@latest desktop/main.js --bundle --tree-shaking=true --sourcemap=inline --outfile=runtime_debug.js --define:DEBUG=true
build:production:
internal: true
cmds:
- npx esbuild desktop/main.js --bundle --tree-shaking=true --minify --outfile=runtime_production_desktop_{{.PLATFORM}}.js --define:DEBUG=false --define:WINDOWS={{.WINDOWS}} --define:DARWIN={{.DARWIN}} --define:LINUX={{.LINUX}} --define:PLATFORM={{.PLATFORM}} --define:INVOKE={{.INVOKE}}
build:production:windows:
cmds:
- task: build:production
vars:
WINDOWS: true
DARWIN: false
LINUX: false
PLATFORM: windows
INVOKE: "chrome.webview.postMessage"
build:production:linux:
cmds:
- task: build:production
vars:
WINDOWS: false
DARWIN: false
LINUX: true
PLATFORM: linux
INVOKE: "webkit.messageHandlers.external.postMessage"
build:production:darwin:
cmds:
- task: build:production
vars:
WINDOWS: false
DARWIN: true
LINUX: false
PLATFORM: darwin
INVOKE: "webkit.messageHandlers.external.postMessage"
- npx esbuild@latest desktop/main.js --bundle --tree-shaking=true --minify --outfile=runtime.js --drop:console
build:all:
internal: true
deps:
- build:debug:windows
- build:debug:linux
- build:debug:darwin
- build:production:windows
- build:production:linux
- build:production:darwin
- build:debug
- build:production
cmds:
- cmd: echo "Build Complete."

View File

@ -2,6 +2,11 @@
package runtime
import _ "embed"
//go:embed runtime.js
var DesktopRuntime []byte
var RuntimeAssetsBundle = &RuntimeAssets{
runtimeDesktopJS: DesktopRuntime,
}

View File

@ -2,6 +2,11 @@
package runtime
import _ "embed"
//go:embed runtime_debug.js
var DesktopRuntime []byte
var RuntimeAssetsBundle = &RuntimeAssets{
runtimeDesktopJS: DesktopRuntime,
}

View File

@ -0,0 +1,46 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import { newRuntimeCallerWithID, objectNames } from "./runtime";
const call = newRuntimeCallerWithID(objectNames.Application);
const HideMethod = 0;
const ShowMethod = 1;
const QuitMethod = 2;
/**
* Hides a certain method by calling the HideMethod function.
*
* @return {Promise<void>}
*
*/
export function Hide() {
return call(HideMethod);
}
/**
* Calls the ShowMethod and returns the result.
*
* @return {Promise<void>}
*/
export function Show() {
return call(ShowMethod);
}
/**
* Calls the QuitMethod to terminate the program.
*
* @return {Promise<void>}
*/
export function Quit() {
return call(QuitMethod);
}

View File

@ -9,17 +9,16 @@ The electron alternative for Go
*/
/* jshint esversion: 9 */
import {newRuntimeCallerWithID, objectNames} from "./runtime";
let call = newRuntimeCallerWithID(objectNames.Browser);
let BrowserOpenURL = 0;
const call = newRuntimeCallerWithID(objectNames.Browser, '');
const BrowserOpenURL = 0;
/**
* Open a browser window to the given URL
* @param {string} url - The URL to open
* @returns {Promise<string>}
*/
export function OpenURL(url) {
void call(BrowserOpenURL, {url});
return call(BrowserOpenURL, {url});
}

View File

@ -0,0 +1,123 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import { newRuntimeCallerWithID, objectNames } from "./runtime";
import { nanoid } from 'nanoid/non-secure';
const CallBinding = 0;
const call = newRuntimeCallerWithID(objectNames.Call, '');
let callResponses = new Map();
window._wails = window._wails || {};
window._wails.callCallback = resultHandler;
window._wails.callErrorCallback = errorHandler;
function generateID() {
let result;
do {
result = nanoid();
} while (callResponses.has(result));
return result;
}
export function resultHandler(id, data, isJSON) {
const promiseHandler = getAndDeleteResponse(id);
if (promiseHandler) {
promiseHandler.resolve(isJSON ? JSON.parse(data) : data);
}
}
export function errorHandler(id, message) {
const promiseHandler = getAndDeleteResponse(id);
if (promiseHandler) {
promiseHandler.reject(message);
}
}
function getAndDeleteResponse(id) {
const response = callResponses.get(id);
callResponses.delete(id);
return response;
}
function callBinding(type, options = {}) {
return new Promise((resolve, reject) => {
const id = generateID();
options["call-id"] = id;
callResponses.set(id, { resolve, reject });
call(type, options).catch((error) => {
reject(error);
callResponses.delete(id);
});
});
}
/**
* Call method.
*
* @param {Object} options - The options for the method.
* @returns {Object} - The result of the call.
*/
export function Call(options) {
return callBinding(CallBinding, options);
}
/**
* Executes a method by name.
*
* @param {string} name - The name of the method in the format 'package.struct.method'.
* @param {...*} args - The arguments to pass to the method.
* @throws {Error} If the name is not a string or is not in the correct format.
* @returns {*} The result of the method execution.
*/
export function ByName(name, ...args) {
if (typeof name !== "string" || name.split(".").length !== 3) {
throw new Error("CallByName requires a string in the format 'package.struct.method'");
}
let [packageName, structName, methodName] = name.split(".");
return callBinding(CallBinding, {
packageName,
structName,
methodName,
args
});
}
/**
* Calls a method by its ID with the specified arguments.
*
* @param {string} methodID - The ID of the method to call.
* @param {...*} args - The arguments to pass to the method.
* @return {*} - The result of the method call.
*/
export function ByID(methodID, ...args) {
return callBinding(CallBinding, {
methodID,
args
});
}
/**
* Calls a method on a plugin.
*
* @param {string} pluginName - The name of the plugin.
* @param {string} methodName - The name of the method to call.
* @param {...*} args - The arguments to pass to the method.
* @returns {*} - The result of the method call.
*/
export function Plugin(pluginName, methodName, ...args) {
return callBinding(CallBinding, {
packageName: "wails-plugins",
structName: pluginName,
methodName,
args
});
}

View File

@ -0,0 +1,35 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import {newRuntimeCallerWithID, objectNames} from "./runtime";
const call = newRuntimeCallerWithID(objectNames.Clipboard, '');
const ClipboardSetText = 0;
const ClipboardText = 1;
/**
* Sets the text to the Clipboard.
*
* @param {string} text - The text to be set to the Clipboard.
* @return {Promise} - A Promise that resolves when the operation is successful.
*/
export function SetText(text) {
return call(ClipboardSetText, {text});
}
/**
* Get the Clipboard text
* @returns {Promise<string>} A promise that resolves with the text from the Clipboard.
*/
export function Text() {
return call(ClipboardText);
}

View File

@ -1,8 +1,19 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import {newRuntimeCallerWithID, objectNames} from "./runtime";
let call = newRuntimeCallerWithID(objectNames.ContextMenu);
let ContextMenuOpen = 0;
const call = newRuntimeCallerWithID(objectNames.ContextMenu, '');
const ContextMenuOpen = 0;
function openContextMenu(id, x, y, data) {
void call(ContextMenuOpen, {id, x, y, data});

View File

@ -0,0 +1,138 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* @typedef {import("./types").MessageDialogOptions} MessageDialogOptions
* @typedef {import("./types").OpenDialogOptions} OpenDialogOptions
* @typedef {import("./types").SaveDialogOptions} SaveDialogOptions
*/
import {newRuntimeCallerWithID, objectNames} from "./runtime";
import { nanoid } from 'nanoid/non-secure';
// Define constants from the `methods` object in Title Case
const DialogInfo = 0;
const DialogWarning = 1;
const DialogError = 2;
const DialogQuestion = 3;
const DialogOpenFile = 4;
const DialogSaveFile = 5;
const call = newRuntimeCallerWithID(objectNames.Dialog, '');
const dialogResponses = new Map();
/**
* Generates a unique id that is not present in dialogResponses.
* @returns {string} unique id
*/
function generateID() {
let result;
do {
result = nanoid();
} while (dialogResponses.has(result));
return result;
}
/**
* Shows a dialog of specified type with the given options.
* @param {number} type - type of dialog
* @param {object} options - options for the dialog
* @returns {Promise} promise that resolves with result of dialog
*/
function dialog(type, options = {}) {
const id = generateID();
options["dialog-id"] = id;
return new Promise((resolve, reject) => {
dialogResponses.set(id, {resolve, reject});
call(type, options).catch((error) => {
reject(error);
dialogResponses.delete(id);
});
});
}
/**
* Handles the callback from a dialog.
*
* @param {string} id - The ID of the dialog response.
* @param {string} data - The data received from the dialog.
* @param {boolean} isJSON - Flag indicating whether the data is in JSON format.
*
* @return {undefined}
*/
export function dialogCallback(id, data, isJSON) {
let p = dialogResponses.get(id);
if (p) {
if (isJSON) {
p.resolve(JSON.parse(data));
} else {
p.resolve(data);
}
dialogResponses.delete(id);
}
}
/**
* Callback function for handling errors in dialog.
*
* @param {string} id - The id of the dialog response.
* @param {string} message - The error message.
*
* @return {void}
*/
export function dialogErrorCallback(id, message) {
let p = dialogResponses.get(id);
if (p) {
p.reject(message);
dialogResponses.delete(id);
}
}
// Replace `methods` with constants in Title Case
/**
* @param {MessageDialogOptions} options - Dialog options
* @returns {Promise<string>} - The label of the button pressed
*/
export const Info = (options) => dialog(DialogInfo, options);
/**
* @param {MessageDialogOptions} options - Dialog options
* @returns {Promise<string>} - The label of the button pressed
*/
export const Warning = (options) => dialog(DialogWarning, options);
/**
* @param {MessageDialogOptions} options - Dialog options
* @returns {Promise<string>} - The label of the button pressed
*/
export const Error = (options) => dialog(DialogError, options);
/**
* @param {MessageDialogOptions} options - Dialog options
* @returns {Promise<string>} - The label of the button pressed
*/
export const Question = (options) => dialog(DialogQuestion, options);
/**
* @param {OpenDialogOptions} options - Dialog options
* @returns {Promise<string[]|string>} Returns selected file or list of files. Returns blank string if no file is selected.
*/
export const OpenFile = (options) => dialog(DialogOpenFile, options);
/**
* @param {SaveDialogOptions} options - Dialog options
* @returns {Promise<string>} Returns the selected file. Returns blank string if no file is selected.
*/
export const SaveFile = (options) => dialog(DialogSaveFile, options);

View File

@ -10,26 +10,22 @@ The electron alternative for Go
/* jshint esversion: 9 */
import {invoke} from "./invoke";
import {invoke, IsWindows} from "./system";
import {GetFlag} from "./flags";
let shouldDrag = false;
let resizeEdge = null;
let resizable = false;
let defaultCursor = "auto";
window._wails = window._wails || {};
window._wails.setResizable = setResizable;
window._wails.endDrag = endDrag;
export function dragTest(e) {
let val = window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");
if (val) {
val = val.trim();
}
if (val !== "drag") {
if (val && val.trim() !== "drag" || e.buttons !== 1) {
return false;
}
// Only process the primary button
if (e.buttons !== 1) {
return false;
}
return e.detail === 1;
}
@ -39,38 +35,32 @@ export function setupDrag() {
window.addEventListener('mouseup', onMouseUp);
}
let resizeEdge = null;
let resizable = false;
export function setResizable(value) {
resizable = value;
}
function testResize(e) {
export function endDrag() {
document.body.style.cursor = 'default';
shouldDrag = false;
}
function testResize() {
if( resizeEdge ) {
invoke("resize:" + resizeEdge);
invoke(`resize:${resizeEdge}`);
return true
}
return false;
}
function onMouseDown(e) {
if(IsWindows() && testResize() || dragTest(e)) {
shouldDrag = !!isValidDrag(e);
}
}
// Check for resizing on Windows
if( WINDOWS ) {
if (testResize()) {
return;
}
}
if (dragTest(e)) {
// Ignore drag on scrollbars
if (e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight) {
return;
}
shouldDrag = true;
} else {
shouldDrag = false;
}
function isValidDrag(e) {
// Ignore drag on scrollbars
return !(e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight);
}
function onMouseUp(e) {
@ -80,34 +70,26 @@ function onMouseUp(e) {
}
}
export function endDrag() {
document.body.style.cursor = 'default';
shouldDrag = false;
}
function setResize(cursor) {
document.documentElement.style.cursor = cursor || defaultCursor;
function setResize(cursor = defaultCursor) {
document.documentElement.style.cursor = cursor;
resizeEdge = cursor;
}
function onMouseMove(e) {
if (shouldDrag) {
shouldDrag = false;
let mousePressed = e.buttons !== undefined ? e.buttons : e.which;
if (mousePressed > 0) {
invoke("drag");
}
return;
}
if (WINDOWS) {
if (resizable) {
handleResize(e);
}
shouldDrag = checkDrag(e);
if (IsWindows() && resizable) {
handleResize(e);
}
}
let defaultCursor = "auto";
function checkDrag(e) {
let mousePressed = e.buttons !== undefined ? e.buttons : e.which;
if(shouldDrag && mousePressed > 0) {
invoke("drag");
return false;
}
return shouldDrag;
}
function handleResize(e) {
let resizeHandleHeight = GetFlag("system.resizeHandleHeight") || 5;

View File

@ -0,0 +1,134 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* @typedef {import("./types").WailsEvent} WailsEvent
*/
import {newRuntimeCallerWithID, objectNames} from "./runtime";
const call = newRuntimeCallerWithID(objectNames.Events, '');
const EmitMethod = 0;
const eventListeners = new Map();
class Listener {
constructor(eventName, callback, maxCallbacks) {
this.eventName = eventName;
this.maxCallbacks = maxCallbacks || -1;
this.Callback = (data) => {
callback(data);
if (this.maxCallbacks === -1) return false;
this.maxCallbacks -= 1;
return this.maxCallbacks === 0;
};
}
}
export class WailsEvent {
constructor(name, data = null) {
this.name = name;
this.data = data;
}
}
window._wails = window._wails || {};
window._wails.dispatchWailsEvent = dispatchWailsEvent;
export function dispatchWailsEvent(event) {
let listeners = eventListeners.get(event.name);
if (listeners) {
let toRemove = listeners.filter(listener => {
let remove = listener.Callback(event);
if (remove) return true;
});
if (toRemove.length > 0) {
listeners = listeners.filter(l => !toRemove.includes(l));
if (listeners.length === 0) eventListeners.delete(event.name);
else eventListeners.set(event.name, listeners);
}
}
}
/**
* Register a callback function to be called multiple times for a specific event.
*
* @param {string} eventName - The name of the event to register the callback for.
* @param {function} callback - The callback function to be called when the event is triggered.
* @param {number} maxCallbacks - The maximum number of times the callback can be called for the event. Once the maximum number is reached, the callback will no longer be called.
*
@return {function} - A function that, when called, will unregister the callback from the event.
*/
export function OnMultiple(eventName, callback, maxCallbacks) {
let listeners = eventListeners.get(eventName) || [];
const thisListener = new Listener(eventName, callback, maxCallbacks);
listeners.push(thisListener);
eventListeners.set(eventName, listeners);
return () => listenerOff(thisListener);
}
/**
* Registers a callback function to be executed when the specified event occurs.
*
* @param {string} eventName - The name of the event.
* @param {function} callback - The callback function to be executed. It takes no parameters.
* @return {function} - A function that, when called, will unregister the callback from the event. */
export function On(eventName, callback) { return OnMultiple(eventName, callback, -1); }
/**
* Registers a callback function to be executed only once for the specified event.
*
* @param {string} eventName - The name of the event.
* @param {function} callback - The function to be executed when the event occurs.
* @return {void@return {function} - A function that, when called, will unregister the callback from the event.
*/
export function Once(eventName, callback) { return OnMultiple(eventName, callback, 1); }
/**
* Removes the specified listener from the event listeners collection.
* If all listeners for the event are removed, the event key is deleted from the collection.
*
* @param {Object} listener - The listener to be removed.
*/
function listenerOff(listener) {
const eventName = listener.eventName;
let listeners = eventListeners.get(eventName).filter(l => l !== listener);
if (listeners.length === 0) eventListeners.delete(eventName);
else eventListeners.set(eventName, listeners);
}
/**
* Removes event listeners for the specified event names.
*
* @param {string} eventName - The name of the event to remove listeners for.
* @param {...string} additionalEventNames - Additional event names to remove listeners for.
* @return {undefined}
*/
export function Off(eventName, ...additionalEventNames) {
let eventsToRemove = [eventName, ...additionalEventNames];
eventsToRemove.forEach(eventName => eventListeners.delete(eventName));
}
/**
* Removes all event listeners.
*
* @function OffAll
* @returns {void}
*/
export function OffAll() { eventListeners.clear(); }
/**
* Emits an event using the given event name.
*
* @param {WailsEvent} event - The name of the event to emit.
* @returns {any} - The result of the emitted event.
*/
export function Emit(event) { return call(EmitMethod, event); }

View File

@ -1,4 +1,6 @@
import { On, Off, OffAll, OnMultiple, WailsEvent, dispatchWailsEvent, eventListeners, Once } from './events';
import { expect, describe, it, vi, afterEach, beforeEach } from 'vitest';
afterEach(() => {

View File

@ -52,6 +52,12 @@ function getValueFromMap(keyString) {
return value;
}
/**
* Retrieves the value associated with the specified key from the flag map.
*
* @param {string} keyString - The key to retrieve the value for.
* @return {*} - The value associated with the specified key.
*/
export function GetFlag(keyString) {
return getValueFromMap(keyString);
}

View File

@ -0,0 +1,56 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
import {setupContextMenus} from "./contextmenu";
import {setupDrag} from "./drag";
import {reloadWML} from "./wml";
import {Emit, Off, OffAll, On, Once, OnMultiple, WailsEvent} from './events';
import {ByID, ByName, Plugin} from "./calls";
import {Error, Info, OpenFile, Question, SaveFile, Warning} from "./dialogs";
export * as Application from "./application";
export * as Browser from "./browser";
export * as Clipboard from "./clipboard";
export * as ContextMenu from "./contextmenu";
export * as Flags from "./flags";
export * as Runtime from "./runtime";
export * as Screens from "./screens";
export * as System from "./system";
export * as Window from "./window";
export const Events = {
On,
Off,
OnMultiple,
WailsEvent,
OffAll,
Emit,
Once
}
export const Call = {
Plugin,
ByID,
ByName
}
export const Dialogs = {
Info,
Error,
OpenFile, Question, Warning, SaveFile
}
setupContextMenus();
setupDrag();
document.addEventListener("DOMContentLoaded", function () {
reloadWML();
});

View File

@ -1,7 +1,7 @@
{
"name": "@wailsapp/api",
"name": "@wailsio/runtime",
"version": "3.0.0-alpha.4",
"description": "Wails Runtime API",
"description": "Wails Runtime",
"main": "index.js",
"repository": {
"type": "git",

View File

@ -12,6 +12,7 @@ The electron alternative for Go
import { nanoid } from 'nanoid/non-secure';
const runtimeURL = window.location.origin + "/wails/runtime";
// Object Names
export const objectNames = {
Call: 0,
@ -27,6 +28,33 @@ export const objectNames = {
}
export let clientId = nanoid();
/**
* Creates a runtime caller function that invokes a specified method on a given object within a specified window context.
*
* @param {Object} object - The object on which the method is to be invoked.
* @param {string} windowName - The name of the window context in which the method should be called.
* @returns {Function} A runtime caller function that takes the method name and optionally arguments and invokes the method within the specified window context.
*/
export function newRuntimeCaller(object, windowName) {
return function (method, args=null) {
return runtimeCall(object + "." + method, windowName, args);
};
}
/**
* Creates a new runtime caller with specified ID.
*
* @param {object} object - The object to invoke the method on.
* @param {string} windowName - The name of the window.
* @return {Function} - The new runtime caller function.
*/
export function newRuntimeCallerWithID(object, windowName) {
return function (method, args=null) {
return runtimeCallWithID(object, method, windowName, args);
};
}
function runtimeCall(method, windowName, args) {
let url = new URL(runtimeURL);
if( method ) {
@ -61,12 +89,6 @@ function runtimeCall(method, windowName, args) {
});
}
export function newRuntimeCaller(object, windowName) {
return function (method, args=null) {
return runtimeCall(object + "." + method, windowName, args);
};
}
function runtimeCallWithID(objectID, method, windowName, args) {
let url = new URL(runtimeURL);
url.searchParams.append("object", objectID);
@ -98,9 +120,3 @@ function runtimeCallWithID(objectID, method, windowName, args) {
.catch(error => reject(error));
});
}
export function newRuntimeCallerWithID(object, windowName) {
return function (method, args=null) {
return runtimeCallWithID(object, method, windowName, args);
};
}

View File

@ -15,34 +15,31 @@ The electron alternative for Go
*/
import {newRuntimeCallerWithID, objectNames} from "./runtime";
const call = newRuntimeCallerWithID(objectNames.Screens, '');
let call = newRuntimeCallerWithID(objectNames.Screens);
let ScreensGetAll = 0;
let ScreensGetPrimary = 1;
let ScreensGetCurrent = 2;
const getAll = 0;
const getPrimary = 1;
const getCurrent = 2;
/**
* Gets all screens.
* @returns {Promise<Screen[]>}
* @returns {Promise<Screen[]>} A promise that resolves to an array of Screen objects.
*/
export function GetAll() {
return call(ScreensGetAll);
return call(getAll);
}
/**
* Gets the primary screen.
* @returns {Promise<Screen>}
* @returns {Promise<Screen>} A promise that resolves to the primary screen.
*/
export function GetPrimary() {
return call(ScreensGetPrimary);
return call(getPrimary);
}
/**
* Gets the current active screen.
* @returns {Promise<Screen>}
* @constructor
*
* @returns {Promise<Screen>} A promise that resolves with the current active screen.
*/
export function GetCurrent() {
return call(ScreensGetCurrent);
return call(getCurrent);
}

View File

@ -0,0 +1,118 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import {newRuntimeCallerWithID, objectNames} from "./runtime";
let call = newRuntimeCallerWithID(objectNames.System, '');
const systemIsDarkMode = 0;
const environment = 1;
/**
* @function
* Retrieves the system dark mode status.
* @returns {Promise<boolean>} - A promise that resolves to a boolean value indicating if the system is in dark mode.
*/
export function IsDarkMode() {
return call(systemIsDarkMode);
}
/**
* Fetches the capabilities of the application from the server.
*
* @async
* @function Capabilities
* @returns {Promise<Object>} A promise that resolves to an object containing the capabilities.
*/
export async function Capabilities() {
let response = fetch("/wails/capabilities");
return response.json();
}
/**
* @typedef {object} EnvironmentInfo
* @property {string} OS - The operating system in use.
* @property {string} Arch - The architecture of the system.
*/
/**
* @function
* Retrieves environment details.
* @returns {Promise<EnvironmentInfo>} - A promise that resolves to an object containing OS and system architecture.
*/
export function Environment() {
return call(environment);
}
export let invoke = null;
let environmentCache = null;
Environment()
.then(result => {
environmentCache = result;
invoke = IsWindows() ? window.chrome.webview.postMessage : window.webkit.messageHandlers.external.postMessage;
})
.catch(error => {
console.error(`Error getting Environment: ${error}`);
});
/**
* Checks if the current operating system is Windows.
*
* @return {boolean} True if the operating system is Windows, otherwise false.
*/
export function IsWindows() {
return environmentCache.OS === "windows";
}
/**
* Checks if the current operating system is Linux.
*
* @returns {boolean} Returns true if the current operating system is Linux, false otherwise.
*/
export function IsLinux() {
return environmentCache.OS === "linux";
}
/**
* Checks if the current environment is a macOS operating system.
*
* @returns {boolean} True if the environment is macOS, false otherwise.
*/
export function IsMac() {
return environmentCache.OS === "darwin";
}
/**
* Checks if the current environment architecture is AMD64.
* @returns {boolean} True if the current environment architecture is AMD64, false otherwise.
*/
export function IsAMD64() {
return environmentCache.Arch === "amd64";
}
/**
* Checks if the current architecture is ARM.
*
* @returns {boolean} True if the current architecture is ARM, false otherwise.
*/
export function IsARM() {
return environmentCache.Arch === "arm";
}
/**
* Checks if the current environment is ARM64 architecture.
*
* @returns {boolean} - Returns true if the environment is ARM64 architecture, otherwise returns false.
*/
export function IsARM64() {
return environmentCache.Arch === "arm64";
}

View File

@ -0,0 +1,122 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* @typedef {import("../api/types").Size} Size
* @typedef {import("../api/types").Position} Position
* @typedef {import("../api/types").Screen} Screen
*/
import {newRuntimeCallerWithID, objectNames} from "./runtime";
const center = 0;
const setTitle = 1;
const fullscreen = 2;
const unFullscreen = 3;
const setSize = 4;
const size = 5;
const setMaxSize = 6;
const setMinSize = 7;
const setAlwaysOnTop = 8;
const setRelativePosition = 9;
const relativePosition = 10;
const screen = 11;
const hide = 12;
const maximise = 13;
const unMaximise = 14;
const toggleMaximise = 15;
const minimise = 16;
const unMinimise = 17;
const restore = 18;
const show = 19;
const close = 20;
const setBackgroundColour = 21;
const setResizable = 22;
const width = 23;
const height = 24;
const zoomIn = 25;
const zoomOut = 26;
const zoomReset = 27;
const getZoomLevel = 28;
const setZoomLevel = 29;
const thisWindow = newRuntimeCallerWithID(objectNames.Window, '');
function createWindow(call) {
return {
Get: (windowName) => createWindow(newRuntimeCallerWithID(objectNames.Window, windowName)),
Center: () => call(center),
SetTitle: (title) => call(setTitle, {title}),
Fullscreen: () => call(fullscreen),
UnFullscreen: () => call(unFullscreen),
SetSize: (width, height) => call(setSize, {width, height}),
Size: () => call(size),
SetMaxSize: (width, height) => call(setMaxSize, {width, height}),
SetMinSize: (width, height) => call(setMinSize, {width, height}),
SetAlwaysOnTop: (onTop) => call(setAlwaysOnTop, {alwaysOnTop: onTop}),
SetRelativePosition: (x, y) => call(setRelativePosition, {x, y}),
RelativePosition: () => call(relativePosition),
Screen: () => call(screen),
Hide: () => call(hide),
Maximise: () => call(maximise),
UnMaximise: () => call(unMaximise),
ToggleMaximise: () => call(toggleMaximise),
Minimise: () => call(minimise),
UnMinimise: () => call(unMinimise),
Restore: () => call(restore),
Show: () => call(show),
Close: () => call(close),
SetBackgroundColour: (r, g, b, a) => call(setBackgroundColour, {r, g, b, a}),
SetResizable: (resizable) => call(setResizable, {resizable}),
Width: () => call(width),
Height: () => call(height),
ZoomIn: () => call(zoomIn),
ZoomOut: () => call(zoomOut),
ZoomReset: () => call(zoomReset),
GetZoomLevel: () => call(getZoomLevel),
SetZoomLevel: (zoomLevel) => call(setZoomLevel, {zoomLevel}),
};
}
/**
* Gets the specified window.
*
* @param {string} windowName - The name of the window to get.
* @return {Object} - The specified window object.
*/
export function Get(windowName) {
return createWindow(newRuntimeCallerWithID(objectNames.Window, windowName));
}
/**
* Returns a map of all methods in the current window.
* @returns {Map} - A map of window methods.
*/
export function WindowMethods(targetWindow) {
// Create a new map to store methods
let result = new Map();
// Iterate over all properties of the window object
for (let method in targetWindow) {
// Check if the property is indeed a method (function)
if(typeof targetWindow[method] === 'function') {
// Add the method to the map
result.set(method, targetWindow[method]);
}
}
// Return the map of window methods
return result;
}
export default {
...Get('')
}

View File

@ -1,12 +1,26 @@
import {Emit, WailsEvent} from "./events";
import {Question} from "./dialogs";
import {WindowMethods, Get} from "./window";
/**
* Sends an event with the given name and optional data.
*
* @param {string} eventName - The name of the event to send.
* @param {any} [data=null] - Optional data to send along with the event.
*
* @return {void}
*/
function sendEvent(eventName, data=null) {
let event = new WailsEvent(eventName, data);
Emit(event);
}
/**
* Adds event listeners to elements with `wml-event` attribute.
*
* @return {void}
*/
function addWMLEventListeners() {
const elements = document.querySelectorAll('[wml-event]');
elements.forEach(function (element) {
@ -25,8 +39,8 @@ function addWMLEventListeners() {
}
sendEvent(eventType);
};
// Remove existing listeners
// Remove existing listeners
element.removeEventListener(trigger, callback);
// Add new listener
@ -34,13 +48,30 @@ function addWMLEventListeners() {
});
}
/**
* Calls a method on the window object.
*
* @param {string} method - The name of the method to call on the window object.
*
* @return {void}
*/
function callWindowMethod(method) {
if (wails.Window[method] === undefined) {
// TODO: Make this a parameter!
let windowName = '';
let targetWindow = Get('');
let methodMap = WindowMethods(targetWindow);
if (!methodMap.has(method)) {
console.log("Window method " + method + " not found");
}
wails.Window[method]();
methodMap.get(method)();
}
/**
* Adds window listeners for elements with the 'wml-window' attribute.
* Removes any existing listeners before adding new ones.
*
* @return {void}
*/
function addWMLWindowListeners() {
const elements = document.querySelectorAll('[wml-window]');
elements.forEach(function (element) {
@ -68,6 +99,15 @@ function addWMLWindowListeners() {
});
}
/**
* Adds a listener to elements with the 'wml-openurl' attribute.
* When the specified trigger event is fired on any of these elements,
* the listener will open the URL specified by the 'wml-openurl' attribute.
* If a 'wml-confirm' attribute is provided, a confirmation dialog will be displayed,
* and the URL will only be opened if the user confirms.
*
* @return {void}
*/
function addWMLOpenBrowserListener() {
const elements = document.querySelectorAll('[wml-openurl]');
elements.forEach(function (element) {
@ -95,7 +135,13 @@ function addWMLOpenBrowserListener() {
});
}
/**
* Reloads the WML page by adding necessary event listeners and browser listeners.
*
* @return {void}
*/
export function reloadWML() {
console.log("Reloading WML");
addWMLEventListeners();
addWMLWindowListeners();
addWMLOpenBrowserListener();

View File

@ -1,3 +1,8 @@
# README
After updating any files in this directory, you must run `wails task build:runtime` to regenerate the compiled JS.
The `main.js` file in this directory is the entrypoint for the `runtime.js` file that may be
loaded at runtime. This will add `window.wails` and `window._wails` to the global scope.
NOTE: It is preferable to use the `@wailsio/runtime` package to use the runtime.
After updating any files in this directory, you must run `wails3 task build:runtime` to regenerate the compiled JS.

View File

@ -1,363 +0,0 @@
# Wails API
This package provides a typed Javascript API for Wails applications.
It provides methods for the following components:
- [Dialog](#dialog)
- [Events](#events)
- [Window](#window)
- [Plugin](#plugin)
- [Screens](#screens)
- [Application](#application)
## Installation
In your Wails application, run the following command in the frontend project directory:
```bash
npm install -D @wailsapp/api
```
## Usage
Import the API into your application:
```javascript
import * as Wails from "@wailsapp/api";
```
Then use the API components:
```javascript
function showDialog() {
Wails.Dialog.Info({
Title: "Hello",
}).then((result) => {
console.log("Result: " + result);
});
}
```
Individual components of the API can also be imported directly.
## API
### Dialog
The Dialog API provides access to the native system dialogs.
```javascript
import { Dialog } from "@wailsapp/api";
function example() {
Dialog.Info({
Title: "Hello",
}).then((result) => {
console.log("Result: " + result);
});
}
```
#### Message Dialogs
Message dialogs are used to display a message to the user.
They can be used to display information, errors, warnings and questions.
Each method returns the button that was pressed by the user.
- `Info(options: MessageDialogOptions): Promise<string>`
- `Error(options: MessageDialogOptions): Promise<string>`
- `Warning(options: MessageDialogOptions): Promise<string>`
- `Question(options: MessageDialogOptions): Promise<string>`
#### Open Dialog
The Open Dialog is used to open a file or directory. It returns the path of the selected file or directory.
If the `AllowsMultipleFiles` option is set, multiple files or directories can be selected and are returned
as an array of file paths.
- `Open(options: OpenDialogOptions): Promise<string[]|string>`
#### Save Dialog
The Save Dialog is used to save a file. It returns the path of the selected file.
- `Save(options: SaveDialogOptions): Promise<string>`
### Events
The Events API provides access to the Wails event system. This is a global event system
that can be used to send events between the Go and Javascript.
Events are available to every window in a multi-window application.
These API methods are specific to the window in which they are called in.
```javascript
import { Events } from "@wailsapp/api";
function example() {
// Emit an event
Events.Emit("myevent", { message: "Hello" });
// Subscribe to an event
let unsub = Events.On("otherEvent", (data) => {
console.log("Received event: " + data);
});
// Unsubscribe from the event
unsub();
}
```
#### Emit
Emit an event with optional data.
- `Emit(eventName: string, data?: any): void`
#### Subscribe
Three methods are provided to subscribe to an event:
- `On(eventName: string, callback: (data: any) => void): () => void` - Subscribe to all events of the given name
- `Once(eventName: string, callback: (data: any) => void): () => void` - Subscribe to one event of the given name
- `OnMultiple(eventName: string, callback: (data: any) => void, count: number): () => void` - Subscribe to multiple events of the given name
The callback will be called when the event is emitted.
The returned function can be called to unsubscribe from the event.
#### Unsubscribe
As well as unsubscribing from a single event, you can unsubscribe from events of a given name or all events.
- `Off(eventName: string, additionalEventNames: ...string): void` - Unsubscribe from all events of the given name(s)
- `OffAll(): void` - Unsubscribe all events
### Window
The Window API provides a number of methods that interact with the window in which the API is called.
- `Center: (void) => void` - Center the window
- `SetTitle: (title) => void` - Set the window title
- `Fullscreen: () => void` - Set the window to fullscreen
- `UnFullscreen: () => void` - Restore a fullscreen window
- `SetSize: (width: number, height: number) => void` - Set the window size
- `Size: () => Size` - Get the window size
- `SetMaxSize: (width, height) => void` - Set the window maximum size
- `SetMinSize: (width, height) => void` - Set the window minimum size
- `SetAlwaysOnTop: (onTop) => void` - Set window to be always on top
- `SetPosition: (x, y) => void` - Set the window position
- `Position: () => Position` - Get the window position
- `SetResizable: (resizable) => void` - Set whether the window is resizable
- `Screen: () => Screen` - Get information about the screen the window is on
- `Hide: () => void` - Hide the window
- `Show: () => void` - Show the window
- `Maximise: () => void` - Maximise the window
- `Close: () => void` - Close the window
- `ToggleMaximise: () => void` - Toggle the window maximise state
- `UnMaximise: () => void` - UnMaximise the window
- `Minimise: () => void` - Minimise the window
- `UnMinimise: () => void` - UnMinimise the window
- `SetBackgroundColour: (r, g, b, a) => void` - Set the background colour of the window
### Plugin
The Plugin API provides access to the Wails plugin system.
This method provides the ability to call a plugin method from the frontend.
```javascript
import { Plugin } from "@wailsapp/api";
function example() {
// Call a plugin method
Plugin.Call("myplugin", "MyMethod", { message: "Hello" }).then((result) => {
console.log("Result: " + result);
});
}
```
### Screens
The Screens API provides access to the Wails screen system.
```javascript
import { Screens } from "@wailsapp/api";
function example() {
// Get all attatched screens
Screens.GetAll().then((screens) => {
console.log("Screens: " + screens);
});
// Get the primary screen
Screens.GetPrimary().then((screen) => {
console.log("Primary screen: " + screen);
});
// Get the screen the window is on
Screens.GetCurrent().then((screen) => {
console.log("Window screen: " + screen);
});
}
```
- `GetAll: () => Promise<Screen[]>` - Get all screens
- `GetPrimary: () => Promise<Screen>` - Get the primary screen
- `GetCurrent: () => Promise<Screen>` - Get the screen the window is on
### Application
The Application API provides access to the Wails application system.
```javascript
import { Application } from "@wailsapp/api";
function example() {
// Hide the application
Application.Hide();
// Shopw the application
Application.Show();
// Quit the application
Application.Quit();
}
```
- `Hide: () => void` - Hide the application
- `Show: () => void` - Show the application
- `Quit: () => void` - Quit the application
## Types
This is a comprehensive list of types used by the Wails API.
```typescript
export interface Button {
// The label of the button
Label?: string;
// True if this button is the cancel button (selected when pressing escape)
IsCancel?: boolean;
// True if this button is the default button (selected when pressing enter)
IsDefault?: boolean;
}
interface MessageDialogOptions {
// The title for the dialog
Title?: string;
// The message to display
Message?: string;
// The buttons to use on the dialog
Buttons?: Button[];
}
export interface OpenFileDialogOptions {
// Allows the user to be able to select directories
CanChooseDirectories?: boolean;
// Allows the user to be able to select files
CanChooseFiles?: boolean;
// Provide an option to create directories in the dialog
CanCreateDirectories?: boolean;
// Makes the dialog show hidden files
ShowHiddenFiles?: boolean;
// Whether the dialog should follow filesystem aliases
ResolvesAliases?: boolean;
// Allow the user to select multiple files or directories
AllowsMultipleSelection?: boolean;
// Hide the extension when showing the filename
HideExtension?: boolean;
// Allow the user to select files where the system hides their extensions
CanSelectHiddenExtension?: boolean;
// Treats file packages as directories, e.g. .app on macOS
TreatsFilePackagesAsDirectories?: boolean;
// Allows selection of filetypes not specified in the filters
AllowsOtherFiletypes?: boolean;
// The file filters to use in the dialog
Filters?: FileFilter[];
// The title of the dialog
Title?: string;
// The message to display
Message?: string;
// The label for the select button
ButtonText?: string;
// The default directory to open the dialog in
Directory?: string;
}
export interface FileFilter {
// The display name for the filter, e.g. "Text Files"
DisplayName?: string;
// The pattern to use for the filter, e.g. "*.txt;*.md"
Pattern?: string;
}
export interface SaveFileDialogOptions {
// Provide an option to create directories in the dialog
CanCreateDirectories?: boolean;
// Makes the dialog show hidden files
ShowHiddenFiles?: boolean;
// Allow the user to select files where the system hides their extensions
CanSelectHiddenExtension?: boolean;
// Allows selection of filetypes not specified in the filters
AllowOtherFiletypes?: boolean;
// Hide the extension when showing the filename
HideExtension?: boolean;
// Treats file packages as directories, e.g. .app on macOS
TreatsFilePackagesAsDirectories?: boolean;
// The message to show in the dialog
Message?: string;
// The default directory to open the dialog in
Directory?: string;
// The default filename to use in the dialog
Filename?: string;
// The label for the select button
ButtonText?: string;
}
export interface Screen {
// The screen ID
Id: string;
// The screen name
Name: string;
// The screen scale. 1 = standard resolution, 2: 2x retina, etc.
Scale: number;
// The X position of the screen
X: number;
// The Y position of the screen
Y: number;
// The width and height of the screen
Size: Size;
// The bounds of the screen
Bounds: Rect;
// The work area of the screen
WorkArea: Rect;
// True if this is the primary screen
IsPrimary: boolean;
// The rotation of the screen
Rotation: number;
}
export interface Rect {
X: number;
Y: number;
Width: number;
Height: number;
}
export interface WailsEvent {
// The name of the event
Name: string;
// The data associated with the event
Data?: any;
}
export interface Size {
Width: number;
Height: number;
}
export interface Position {
X: number;
Y: number;
}
```

View File

@ -1,35 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* The Application API provides methods to interact with the application.
*/
export const Application = {
/**
* Hides the application
*/
Hide: () => {
return wails.Application.Hide();
},
/**
* Shows the application
*/
Show: () => {
return wails.Application.Show();
},
/**
* Quits the application
*/
Quit: () => {
return wails.Application.Quit();
},
};

View File

@ -1,24 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* The Browser API provides methods to interact with the system browser.
*/
export const Browser = {
/**
* Opens a browser window to the given URL
* @returns {Promise<string>}
*/
OpenURL: (url) => {
return wails.Browser.OpenURL(url);
},
};

View File

@ -1,31 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* The Clipboard API provides methods to interact with the system clipboard.
*/
export const Clipboard = {
/**
* Gets the text from the clipboard
* @returns {Promise<string>}
*/
Text: () => {
return wails.Clipboard.Text();
},
/**
* Sets the text on the clipboard
* @param {string} text - text to set in the clipboard
*/
SetText: (text) => {
return wails.Clipboard.SetText(text);
},
};

View File

@ -1,75 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* @typedef {import("./types").MessageDialogOptions} MessageDialogOptions
* @typedef {import("./types").OpenDialogOptions} OpenDialogOptions
* @typedef {import("./types").SaveDialogOptions} SaveDialogOptions
*/
/**
* The Dialog API provides methods to interact with system dialogs.
*/
export const Dialog = {
/**
* Shows an info dialog
* @param {MessageDialogOptions} options - options for the dialog
* @returns {Promise<string>}
*/
Info: (options) => {
return wails.Dialog.Info(options);
},
/**
* Shows a warning dialog
* @param {MessageDialogOptions} options - options for the dialog
* @returns {Promise<string>}
*/
Warning: (options) => {
return wails.Dialog.Warning(options);
},
/**
* Shows an error dialog
* @param {MessageDialogOptions} options - options for the dialog
* @returns {Promise<string>}
*/
Error: (options) => {
return wails.Dialog.Error(options);
},
/**
* Shows a question dialog
* @param {MessageDialogOptions} options - options for the dialog
* @returns {Promise<string>}
*/
Question: (options) => {
return wails.Dialog.Question(options);
},
/**
* Shows a file open dialog and returns the files selected by the user.
* A blank string indicates that the dialog was cancelled.
* @param {OpenDialogOptions} options - options for the dialog
* @returns {Promise<string[]>|Promise<string>}
*/
OpenFile: (options) => {
return wails.Dialog.OpenFile(options);
},
/**
* Shows a file save dialog and returns the filename given by the user.
* A blank string indicates that the dialog was cancelled.
* @param {SaveDialogOptions} options - options for the dialog
* @returns {Promise<string>}
*/
SaveFile: (options) => {
return wails.Dialog.SaveFile(options);
},
};

View File

@ -1,178 +0,0 @@
export const EventTypes = {
Windows: {
SystemThemeChanged: "windows:SystemThemeChanged",
APMPowerStatusChange: "windows:APMPowerStatusChange",
APMSuspend: "windows:APMSuspend",
APMResumeAutomatic: "windows:APMResumeAutomatic",
APMResumeSuspend: "windows:APMResumeSuspend",
APMPowerSettingChange: "windows:APMPowerSettingChange",
ApplicationStarted: "windows:ApplicationStarted",
WebViewNavigationCompleted: "windows:WebViewNavigationCompleted",
WindowInactive: "windows:WindowInactive",
WindowActive: "windows:WindowActive",
WindowClickActive: "windows:WindowClickActive",
WindowMaximise: "windows:WindowMaximise",
WindowUnMaximise: "windows:WindowUnMaximise",
WindowFullscreen: "windows:WindowFullscreen",
WindowUnFullscreen: "windows:WindowUnFullscreen",
WindowRestore: "windows:WindowRestore",
WindowMinimise: "windows:WindowMinimise",
WindowUnMinimise: "windows:WindowUnMinimise",
WindowClose: "windows:WindowClose",
WindowSetFocus: "windows:WindowSetFocus",
WindowKillFocus: "windows:WindowKillFocus",
WindowDragDrop: "windows:WindowDragDrop",
WindowDragEnter: "windows:WindowDragEnter",
WindowDragLeave: "windows:WindowDragLeave",
WindowDragOver: "windows:WindowDragOver",
},
Mac: {
ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive",
ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties",
ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance",
ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon",
ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState",
ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters",
ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame",
ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation",
ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching",
ApplicationDidHide: "mac:ApplicationDidHide",
ApplicationDidResignActiveNotification: "mac:ApplicationDidResignActiveNotification",
ApplicationDidUnhide: "mac:ApplicationDidUnhide",
ApplicationDidUpdate: "mac:ApplicationDidUpdate",
ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive",
ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching",
ApplicationWillHide: "mac:ApplicationWillHide",
ApplicationWillResignActive: "mac:ApplicationWillResignActive",
ApplicationWillTerminate: "mac:ApplicationWillTerminate",
ApplicationWillUnhide: "mac:ApplicationWillUnhide",
ApplicationWillUpdate: "mac:ApplicationWillUpdate",
ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme!",
ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen!",
WindowDidBecomeKey: "mac:WindowDidBecomeKey",
WindowDidBecomeMain: "mac:WindowDidBecomeMain",
WindowDidBeginSheet: "mac:WindowDidBeginSheet",
WindowDidChangeAlpha: "mac:WindowDidChangeAlpha",
WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation",
WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties",
WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior",
WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance",
WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState",
WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode",
WindowDidChangeScreen: "mac:WindowDidChangeScreen",
WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters",
WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile",
WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace",
WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties",
WindowDidChangeSharingType: "mac:WindowDidChangeSharingType",
WindowDidChangeSpace: "mac:WindowDidChangeSpace",
WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode",
WindowDidChangeTitle: "mac:WindowDidChangeTitle",
WindowDidChangeToolbar: "mac:WindowDidChangeToolbar",
WindowDidChangeVisibility: "mac:WindowDidChangeVisibility",
WindowDidDeminiaturize: "mac:WindowDidDeminiaturize",
WindowDidEndSheet: "mac:WindowDidEndSheet",
WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen",
WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser",
WindowDidExitFullScreen: "mac:WindowDidExitFullScreen",
WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser",
WindowDidExpose: "mac:WindowDidExpose",
WindowDidFocus: "mac:WindowDidFocus",
WindowDidMiniaturize: "mac:WindowDidMiniaturize",
WindowDidMove: "mac:WindowDidMove",
WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen",
WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen",
WindowDidResignKey: "mac:WindowDidResignKey",
WindowDidResignMain: "mac:WindowDidResignMain",
WindowDidResize: "mac:WindowDidResize",
WindowDidUpdate: "mac:WindowDidUpdate",
WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha",
WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior",
WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties",
WindowDidUpdateShadow: "mac:WindowDidUpdateShadow",
WindowDidUpdateTitle: "mac:WindowDidUpdateTitle",
WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar",
WindowDidUpdateVisibility: "mac:WindowDidUpdateVisibility",
WindowShouldClose: "mac:WindowShouldClose!",
WindowWillBecomeKey: "mac:WindowWillBecomeKey",
WindowWillBecomeMain: "mac:WindowWillBecomeMain",
WindowWillBeginSheet: "mac:WindowWillBeginSheet",
WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode",
WindowWillClose: "mac:WindowWillClose",
WindowWillDeminiaturize: "mac:WindowWillDeminiaturize",
WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen",
WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser",
WindowWillExitFullScreen: "mac:WindowWillExitFullScreen",
WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser",
WindowWillFocus: "mac:WindowWillFocus",
WindowWillMiniaturize: "mac:WindowWillMiniaturize",
WindowWillMove: "mac:WindowWillMove",
WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen",
WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen",
WindowWillResignMain: "mac:WindowWillResignMain",
WindowWillResize: "mac:WindowWillResize",
WindowWillUnfocus: "mac:WindowWillUnfocus",
WindowWillUpdate: "mac:WindowWillUpdate",
WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha",
WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior",
WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties",
WindowWillUpdateShadow: "mac:WindowWillUpdateShadow",
WindowWillUpdateTitle: "mac:WindowWillUpdateTitle",
WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar",
WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility",
WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame",
MenuWillOpen: "mac:MenuWillOpen",
MenuDidOpen: "mac:MenuDidOpen",
MenuDidClose: "mac:MenuDidClose",
MenuWillSendAction: "mac:MenuWillSendAction",
MenuDidSendAction: "mac:MenuDidSendAction",
MenuWillHighlightItem: "mac:MenuWillHighlightItem",
MenuDidHighlightItem: "mac:MenuDidHighlightItem",
MenuWillDisplayItem: "mac:MenuWillDisplayItem",
MenuDidDisplayItem: "mac:MenuDidDisplayItem",
MenuWillAddItem: "mac:MenuWillAddItem",
MenuDidAddItem: "mac:MenuDidAddItem",
MenuWillRemoveItem: "mac:MenuWillRemoveItem",
MenuDidRemoveItem: "mac:MenuDidRemoveItem",
MenuWillBeginTracking: "mac:MenuWillBeginTracking",
MenuDidBeginTracking: "mac:MenuDidBeginTracking",
MenuWillEndTracking: "mac:MenuWillEndTracking",
MenuDidEndTracking: "mac:MenuDidEndTracking",
MenuWillUpdate: "mac:MenuWillUpdate",
MenuDidUpdate: "mac:MenuDidUpdate",
MenuWillPopUp: "mac:MenuWillPopUp",
MenuDidPopUp: "mac:MenuDidPopUp",
MenuWillSendActionToItem: "mac:MenuWillSendActionToItem",
MenuDidSendActionToItem: "mac:MenuDidSendActionToItem",
WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation",
WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",
WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation",
WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation",
WindowFileDraggingEntered: "mac:WindowFileDraggingEntered",
WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed",
WindowFileDraggingExited: "mac:WindowFileDraggingExited",
},
Common: {
ApplicationStarted: "common:ApplicationStarted",
WindowMaximise: "common:WindowMaximise",
WindowUnMaximise: "common:WindowUnMaximise",
WindowFullscreen: "common:WindowFullscreen",
WindowUnFullscreen: "common:WindowUnFullscreen",
WindowRestore: "common:WindowRestore",
WindowMinimise: "common:WindowMinimise",
WindowUnMinimise: "common:WindowUnMinimise",
WindowClosing: "common:WindowClosing",
WindowZoom: "common:WindowZoom",
WindowZoomIn: "common:WindowZoomIn",
WindowZoomOut: "common:WindowZoomOut",
WindowZoomReset: "common:WindowZoomReset",
WindowFocus: "common:WindowFocus",
WindowLostFocus: "common:WindowLostFocus",
WindowShow: "common:WindowShow",
WindowHide: "common:WindowHide",
WindowDPIChanged: "common:WindowDPIChanged",
WindowFilesDropped: "common:WindowFilesDropped",
ThemeChanged: "common:ThemeChanged",
},
};

View File

@ -1,74 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import {EventTypes} from './event_types';
/**
* The Events API provides methods to interact with the event system.
*/
export const Events = {
/**
* Emit an event
* @param {string} name
* @param {any=} data
*/
Emit: (name, data) => {
return wails.Events.Emit(name, data);
},
/**
* Subscribe to an event
* @param {string} name - name of the event
* @param {(any) => void} callback - callback to call when the event is emitted
@returns {function()} unsubscribeMethod - method to unsubscribe from the event
*/
On: (name, callback) => {
return wails.Events.On(name, callback);
},
/**
* Subscribe to an event once
* @param {string} name - name of the event
* @param {(any) => void} callback - callback to call when the event is emitted
* @returns {function()} unsubscribeMethod - method to unsubscribe from the event
*/
Once: (name, callback) => {
return wails.Events.Once(name, callback);
},
/**
* Subscribe to an event multiple times
* @param {string} name - name of the event
* @param {(any) => void} callback - callback to call when the event is emitted
* @param {number} count - number of times to call the callback
* @returns {Promise<void>} unsubscribeMethod - method to unsubscribe from the event
*/
OnMultiple: (name, callback, count) => {
return wails.Events.OnMultiple(name, callback, count);
},
/**
* Unsubscribe from an event
* @param {string} name - name of the event to unsubscribe from
* @param {...string} additionalNames - additional names of events to unsubscribe from
*/
Off: (name, ...additionalNames) => {
wails.Events.Off(name, additionalNames);
},
/**
* Unsubscribe all listeners from all events
*/
OffAll: () => {
wails.Events.OffAll();
},
Windows: EventTypes.Windows,
Mac: EventTypes.Mac,
Common: EventTypes.Common,
};

View File

@ -1,32 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import * as Clipboard from "./clipboard";
import * as Application from "./application";
import * as Screens from "./screens";
import * as Dialogs from "./dialogs";
import * as Events from "./events";
import * as Window from "./window";
export { Clipboard, Application, Screens, Dialogs, Events, Window };
/**
* Call a plugin method
* @param {string} pluginName - name of the plugin
* @param {string} methodName - name of the method
* @param {...any} args - arguments to pass to the method
* @returns {Promise<any>} - promise that resolves with the result
*/
export const Plugin = (pluginName, methodName, ...args) => {
return wails.Plugin(pluginName, methodName, ...args);
};

View File

@ -1,38 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* The Screens API provides methods to interact with the system screens/monitors.
*/
export const Screens = {
/**
* Get the primary screen
* @returns {Promise<Screen>}
*/
GetPrimary: () => {
return wails.Screens.GetPrimary();
},
/**
* Get all screens
* @returns {Promise<Screen[]>}
*/
GetAll: () => {
return wails.Screens.GetAll();
},
/**
* Get the current screen
* @returns {Promise<Screen>}
*/
GetCurrent: () => {
return wails.Screens.GetCurrent();
},
};

View File

@ -1,159 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* The Window API provides methods to interact with the window.
*/
export const Window = {
/**
* Center the window.
*/
Center: () => void wails.Window.Center(),
/**
* Set the window title.
* @param title
*/
SetTitle: (title) => void wails.Window.SetTitle(title),
/**
* Makes the window fullscreen.
*/
Fullscreen: () => void wails.Window.Fullscreen(),
/**
* Unfullscreen the window.
*/
UnFullscreen: () => void wails.Window.UnFullscreen(),
/**
* Set the window size.
* @param {number} width The window width
* @param {number} height The window height
*/
SetSize: (width, height) => void wails.Window.SetSize(width, height),
/**
* Get the window size.
* @returns {Promise<Size>} The window size
*/
Size: () => {
return wails.Window.Size();
},
/**
* Set the window maximum size.
* @param {number} width
* @param {number} height
*/
SetMaxSize: (width, height) => void wails.Window.SetMaxSize(width, height),
/**
* Set the window minimum size.
* @param {number} width
* @param {number} height
*/
SetMinSize: (width, height) => void wails.Window.SetMinSize(width, height),
/**
* Set window to be always on top.
* @param {boolean} onTop Whether the window should be always on top
*/
SetAlwaysOnTop: (onTop) => void wails.Window.SetAlwaysOnTop(onTop),
/**
* Set the window position relative to the current monitor.
* @param {number} x
* @param {number} y
*/
SetRelativePosition: (x, y) => void wails.Window.SetRelativePosition(x, y),
/**
* Get the window position relative to the current monitor.
* @returns {Promise<Position>} The window position
*/
RelativePosition: () => {
return wails.Window.RelativePosition();
},
/**
* Set the absolute window position.
* @param {number} x
* @param {number} y
*/
SetAbsolutePosition: (x, y) => void wails.Window.SetAbsolutePosition(x, y),
/**
* Get the absolute window position.
* @returns {Promise<Position>} The window position
*/
AbsolutePosition: () => {
return wails.Window.AbsolutePosition();
},
/**
* Get the screen the window is on.
* @returns {Promise<Screen>}
*/
Screen: () => {
return wails.Window.Screen();
},
/**
* Hide the window
*/
Hide: () => void wails.Window.Hide(),
/**
* Maximise the window
*/
Maximise: () => void wails.Window.Maximise(),
/**
* Show the window
*/
Show: () => void wails.Window.Show(),
/**
* Close the window
*/
Close: () => void wails.Window.Close(),
/**
* Toggle the window maximise state
*/
ToggleMaximise: () => void wails.Window.ToggleMaximise(),
/**
* Unmaximise the window
*/
UnMaximise: () => void wails.Window.UnMaximise(),
/**
* Minimise the window
*/
Minimise: () => void wails.Window.Minimise(),
/**
* Unminimise the window
*/
UnMinimise: () => void wails.Window.UnMinimise(),
/**
* Set the background colour of the window.
* @param {number} r - The red value between 0 and 255
* @param {number} g - The green value between 0 and 255
* @param {number} b - The blue value between 0 and 255
* @param {number} a - The alpha value between 0 and 255
*/
SetBackgroundColour: (r, g, b, a) => void wails.Window.SetBackgroundColour(r, g, b, a),
};

View File

@ -1,43 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import {newRuntimeCallerWithID, objectNames} from "./runtime";
let call = newRuntimeCallerWithID(objectNames.Application);
let methods = {
Hide: 0,
Show: 1,
Quit: 2,
}
/**
* Hide the application
*/
export function Hide() {
void call(methods.Hide);
}
/**
* Show the application
*/
export function Show() {
void call(methods.Show);
}
/**
* Quit the application
*/
export function Quit() {
void call(methods.Quit);
}

View File

@ -1,107 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import {newRuntimeCallerWithID, objectNames} from "./runtime";
import { nanoid } from 'nanoid/non-secure';
let call = newRuntimeCallerWithID(objectNames.Call);
let CallBinding = 0;
let callResponses = new Map();
function generateID() {
let result;
do {
result = nanoid();
} while (callResponses.has(result));
return result;
}
export function callCallback(id, data, isJSON) {
let p = callResponses.get(id);
if (p) {
if (isJSON) {
p.resolve(JSON.parse(data));
} else {
p.resolve(data);
}
callResponses.delete(id);
}
}
export function callErrorCallback(id, message) {
let p = callResponses.get(id);
if (p) {
p.reject(message);
callResponses.delete(id);
}
}
function callBinding(type, options) {
return new Promise((resolve, reject) => {
let id = generateID();
options = options || {};
options["call-id"] = id;
callResponses.set(id, {resolve, reject});
call(type, options).catch((error) => {
reject(error);
callResponses.delete(id);
});
});
}
export function Call(options) {
return callBinding(CallBinding, options);
}
export function CallByName(name, ...args) {
// Ensure first argument is a string and has 2 dots
if (typeof name !== "string" || name.split(".").length !== 3) {
throw new Error("CallByName requires a string in the format 'package.struct.method'");
}
// Split inputs
let parts = name.split(".");
return callBinding(CallBinding, {
packageName: parts[0],
structName: parts[1],
methodName: parts[2],
args: args,
});
}
export function CallByID(methodID, ...args) {
return callBinding(CallBinding, {
methodID: methodID,
args: args,
});
}
/**
* Call a plugin method
* @param {string} pluginName - name of the plugin
* @param {string} methodName - name of the method
* @param {...any} args - arguments to pass to the method
* @returns {Promise<any>} - promise that resolves with the result
*/
export function Plugin(pluginName, methodName, ...args) {
return callBinding(CallBinding, {
packageName: "wails-plugins",
structName: pluginName,
methodName: methodName,
args: args,
});
}

View File

@ -1,33 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import {newRuntimeCallerWithID, objectNames} from "./runtime";
let call = newRuntimeCallerWithID(objectNames.Clipboard);
let ClipboardSetText = 0;
let ClipboardText = 1;
/**
* Set the Clipboard text
*/
export function SetText(text) {
void call(ClipboardSetText, {text});
}
/**
* Get the Clipboard text
* @returns {Promise<string>}
*/
export function Text() {
return call(ClipboardText);
}

View File

@ -1,129 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* @typedef {import("./api/types").MessageDialogOptions} MessageDialogOptions
* @typedef {import("./api/types").OpenDialogOptions} OpenDialogOptions
* @typedef {import("./api/types").SaveDialogOptions} SaveDialogOptions
*/
import {newRuntimeCallerWithID, objectNames} from "./runtime";
import { nanoid } from 'nanoid/non-secure';
let call = newRuntimeCallerWithID(objectNames.Dialog);
let DialogInfo = 0;
let DialogWarning = 1;
let DialogError = 2;
let DialogQuestion = 3;
let DialogOpenFile = 4;
let DialogSaveFile = 5;
let dialogResponses = new Map();
function generateID() {
let result;
do {
result = nanoid();
} while (dialogResponses.has(result));
return result;
}
export function dialogCallback(id, data, isJSON) {
let p = dialogResponses.get(id);
if (p) {
if (isJSON) {
p.resolve(JSON.parse(data));
} else {
p.resolve(data);
}
dialogResponses.delete(id);
}
}
export function dialogErrorCallback(id, message) {
let p = dialogResponses.get(id);
if (p) {
p.reject(message);
dialogResponses.delete(id);
}
}
function dialog(type, options) {
return new Promise((resolve, reject) => {
let id = generateID();
options = options || {};
options["dialog-id"] = id;
dialogResponses.set(id, {resolve, reject});
call(type, options).catch((error) => {
reject(error);
dialogResponses.delete(id);
});
});
}
/**
* Shows an Info dialog with the given options.
* @param {MessageDialogOptions} options
* @returns {Promise<string>} The label of the button pressed
*/
export function Info(options) {
return dialog(DialogInfo, options);
}
/**
* Shows a Warning dialog with the given options.
* @param {MessageDialogOptions} options
* @returns {Promise<string>} The label of the button pressed
*/
export function Warning(options) {
return dialog(DialogWarning, options);
}
/**
* Shows an Error dialog with the given options.
* @param {MessageDialogOptions} options
* @returns {Promise<string>} The label of the button pressed
*/
export function Error(options) {
return dialog(DialogError, options);
}
/**
* Shows a Question dialog with the given options.
* @param {MessageDialogOptions} options
* @returns {Promise<string>} The label of the button pressed
*/
export function Question(options) {
return dialog(DialogQuestion, options);
}
/**
* Shows an Open dialog with the given options.
* @param {OpenDialogOptions} options
* @returns {Promise<string[]|string>} Returns the selected file or an array of selected files if AllowsMultipleSelection is true. A blank string is returned if no file was selected.
*/
export function OpenFile(options) {
return dialog(DialogOpenFile, options);
}
/**
* Shows a Save dialog with the given options.
* @param {SaveDialogOptions} options
* @returns {Promise<string>} Returns the selected file. A blank string is returned if no file was selected.
*/
export function SaveFile(options) {
return dialog(DialogSaveFile, options);
}

View File

@ -1,194 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* @typedef {import("./api/types").WailsEvent} WailsEvent
*/
import {newRuntimeCallerWithID, objectNames} from "./runtime";
let call = newRuntimeCallerWithID(objectNames.Events);
let EventEmit = 0;
/**
* The Listener class defines a listener! :-)
*
* @class Listener
*/
class Listener {
/**
* Creates an instance of Listener.
* @param {string} eventName
* @param {function} callback
* @param {number} maxCallbacks
* @memberof Listener
*/
constructor(eventName, callback, maxCallbacks) {
this.eventName = eventName;
// Default of -1 means infinite
this.maxCallbacks = maxCallbacks || -1;
// Callback invokes the callback with the given data
// Returns true if this listener should be destroyed
this.Callback = (data) => {
callback(data);
// If maxCallbacks is infinite, return false (do not destroy)
if (this.maxCallbacks === -1) {
return false;
}
// Decrement maxCallbacks. Return true if now 0, otherwise false
this.maxCallbacks -= 1;
return this.maxCallbacks === 0;
};
}
}
/**
* WailsEvent defines a custom event. It is passed to event listeners.
*
* @class WailsEvent
* @property {string} name - Name of the event
* @property {any} data - Data associated with the event
*/
export class WailsEvent {
/**
* Creates an instance of WailsEvent.
* @param {string} name - Name of the event
* @param {any=null} data - Data associated with the event
* @memberof WailsEvent
*/
constructor(name, data = null) {
this.name = name;
this.data = data;
}
}
export const eventListeners = new Map();
/**
* Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
*
* @export
* @param {string} eventName
* @param {function(WailsEvent): void} callback
* @param {number} maxCallbacks
* @returns {function} A function to cancel the listener
*/
export function OnMultiple(eventName, callback, maxCallbacks) {
let listeners = eventListeners.get(eventName) || [];
const thisListener = new Listener(eventName, callback, maxCallbacks);
listeners.push(thisListener);
eventListeners.set(eventName, listeners);
return () => listenerOff(thisListener);
}
/**
* Registers an event listener that will be invoked every time the event is emitted
*
* @export
* @param {string} eventName
* @param {function(WailsEvent): void} callback
* @returns {function} A function to cancel the listener
*/
export function On(eventName, callback) {
return OnMultiple(eventName, callback, -1);
}
/**
* Registers an event listener that will be invoked once then destroyed
*
* @export
* @param {string} eventName
* @param {function(WailsEvent): void} callback
@returns {function} A function to cancel the listener
*/
export function Once(eventName, callback) {
return OnMultiple(eventName, callback, 1);
}
/**
* listenerOff unregisters a listener previously registered with On
*
* @param {Listener} listener
*/
function listenerOff(listener) {
const eventName = listener.eventName;
// Remove local listener
let listeners = eventListeners.get(eventName).filter(l => l !== listener);
if (listeners.length === 0) {
eventListeners.delete(eventName);
} else {
eventListeners.set(eventName, listeners);
}
}
/**
* dispatches an event to all listeners
*
* @export
* @param {WailsEvent} event
*/
export function dispatchWailsEvent(event) {
let listeners = eventListeners.get(event.name);
if (listeners) {
// iterate listeners and call callback. If callback returns true, remove listener
let toRemove = [];
listeners.forEach(listener => {
let remove = listener.Callback(event);
if (remove) {
toRemove.push(listener);
}
});
// remove listeners
if (toRemove.length > 0) {
listeners = listeners.filter(l => !toRemove.includes(l));
if (listeners.length === 0) {
eventListeners.delete(event.name);
} else {
eventListeners.set(event.name, listeners);
}
}
}
}
/**
* Off unregisters a listener previously registered with On,
* optionally multiple listeners can be unregistered via `additionalEventNames`
*
[v3 CHANGE] Off only unregisters listeners within the current window
*
* @param {string} eventName
* @param {...string} additionalEventNames
*/
export function Off(eventName, ...additionalEventNames) {
let eventsToRemove = [eventName, ...additionalEventNames];
eventsToRemove.forEach(eventName => {
eventListeners.delete(eventName);
});
}
/**
* OffAll unregisters all listeners
* [v3 CHANGE] OffAll only unregisters listeners within the current window
*
*/
export function OffAll() {
eventListeners.clear();
}
/**
* Emit an event
* @param {WailsEvent} event The event to emit
*/
export function Emit(event) {
void call(EventEmit, event);
}

View File

@ -1,20 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
// defined in the Taskfile
export let invoke = function(input) {
if(WINDOWS) {
chrome.webview.postMessage(input);
} else {
webkit.messageHandlers.external.postMessage(input);
}
}

View File

@ -10,39 +10,32 @@ The electron alternative for Go
/* jshint esversion: 9 */
import * as Clipboard from './clipboard';
import * as Application from './application';
import * as Screens from './screens';
import * as System from './system';
import * as Browser from './browser';
import {Plugin, Call, callErrorCallback, callCallback, CallByID, CallByName} from "./calls";
import {clientId} from './runtime';
import {newWindow} from "./window";
import {dispatchWailsEvent, Emit, Off, OffAll, On, Once, OnMultiple} from "./events";
import {dialogCallback, dialogErrorCallback, Error, Info, OpenFile, Question, SaveFile, Warning,} from "./dialogs";
import {setupContextMenus} from "./contextmenu";
import {reloadWML} from "./wml";
import {setupDrag, endDrag, setResizable} from "./drag";
import * as Clipboard from './@wailsio/runtime/clipboard';
import * as Application from './@wailsio/runtime/application';
import * as Screens from './@wailsio/runtime/screens';
import * as System from './@wailsio/runtime/system';
import * as Browser from './@wailsio/runtime/browser';
import * as Window from './@wailsio/runtime/window';
import {Plugin, Call, errorHandler as callErrorHandler, resultHandler as callResultHandler, ByID, ByName} from "./@wailsio/runtime/calls";
import {clientId} from './@wailsio/runtime/runtime';
import {dispatchWailsEvent, Emit, Off, OffAll, On, Once, OnMultiple} from "./@wailsio/runtime/events";
import {dialogCallback, dialogErrorCallback, Error, Info, OpenFile, Question, SaveFile, Warning} from "./@wailsio/runtime/dialogs";
import {setupContextMenus} from './@wailsio/runtime/contextmenu';
import {reloadWML} from './@wailsio/runtime/wml';
import {setupDrag, endDrag, setResizable} from './@wailsio/runtime/drag';
window.wails = {
...newRuntime(null),
Capabilities: {},
clientId: clientId,
};
fetch("/wails/capabilities").then((response) => {
response.json().then((data) => {
window.wails.Capabilities = data;
});
});
// Internal wails endpoints
window._wails = {
dialogCallback,
dialogErrorCallback,
dispatchWailsEvent,
callCallback,
callErrorCallback,
callErrorHandler,
callResultHandler,
endDrag,
setResizable,
};
@ -54,17 +47,16 @@ export function newRuntime(windowName) {
},
Application: {
...Application,
GetWindowByName(windowName) {
return newRuntime(windowName);
}
},
System,
Screens,
Browser,
Call,
CallByID,
CallByName,
Plugin,
Call: {
Call,
ByID,
ByName,
Plugin,
},
WML: {
Reload: reloadWML,
},
@ -84,14 +76,12 @@ export function newRuntime(windowName) {
Off,
OffAll,
},
Window: newWindow(windowName),
Window: {
...Window.Get('')
},
};
}
if (DEBUG) {
console.log("Wails v3.0.0 Debug Mode Enabled");
}
setupContextMenus();
setupDrag();

View File

@ -1,25 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import {newRuntimeCallerWithID, objectNames} from "./runtime";
let call = newRuntimeCallerWithID(objectNames.System);
let SystemIsDarkMode = 0;
/**
* Determines if the system is currently using dark mode
* @returns {Promise<boolean>}
*/
export function IsDarkMode() {
return call(SystemIsDarkMode);
}

View File

@ -1,228 +0,0 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
/**
* @typedef {import("../api/types").Size} Size
* @typedef {import("../api/types").Position} Position
* @typedef {import("../api/types").Screen} Screen
*/
import {newRuntimeCallerWithID, objectNames} from "./runtime";
let WindowCenter = 0;
let WindowSetTitle = 1;
let WindowFullscreen = 2;
let WindowUnFullscreen = 3;
let WindowSetSize = 4;
let WindowSize = 5;
let WindowSetMaxSize = 6;
let WindowSetMinSize = 7;
let WindowSetAlwaysOnTop = 8;
let WindowSetRelativePosition = 9;
let WindowRelativePosition = 10;
let WindowScreen = 11;
let WindowHide = 12;
let WindowMaximise = 13;
let WindowUnMaximise = 14;
let WindowToggleMaximise = 15;
let WindowMinimise = 16;
let WindowUnMinimise = 17;
let WindowRestore = 18;
let WindowShow = 19;
let WindowClose = 20;
let WindowSetBackgroundColour = 21;
let WindowSetResizable = 22;
let WindowWidth = 23;
let WindowHeight = 24;
let WindowZoomIn = 25;
let WindowZoomOut = 26;
let WindowZoomReset = 27;
let WindowGetZoomLevel = 28;
let WindowSetZoomLevel = 29;
export function newWindow(windowName) {
let call = newRuntimeCallerWithID(objectNames.Window, windowName);
return {
/**
* Centers the window.
*/
Center: () => void call(WindowCenter),
/**
* Set the window title.
* @param title
*/
SetTitle: (title) => void call(WindowSetTitle, {title}),
/**
* Makes the window fullscreen.
*/
Fullscreen: () => void call(WindowFullscreen),
/**
* Unfullscreen the window.
*/
UnFullscreen: () => void call(WindowUnFullscreen),
/**
* Set the window size.
* @param {number} width The window width
* @param {number} height The window height
*/
SetSize: (width, height) => call(WindowSetSize, {width,height}),
/**
* Get the window size.
* @returns {Promise<Size>} The window size
*/
Size: () => { return call(WindowSize); },
/**
* Set the window maximum size.
* @param {number} width
* @param {number} height
*/
SetMaxSize: (width, height) => void call(WindowSetMaxSize, {width,height}),
/**
* Set the window minimum size.
* @param {number} width
* @param {number} height
*/
SetMinSize: (width, height) => void call(WindowSetMinSize, {width,height}),
/**
* Set window to be always on top.
* @param {boolean} onTop Whether the window should be always on top
*/
SetAlwaysOnTop: (onTop) => void call(WindowSetAlwaysOnTop, {alwaysOnTop:onTop}),
/**
* Set the window relative position.
* @param {number} x
* @param {number} y
*/
SetRelativePosition: (x, y) => call(WindowSetRelativePosition, {x,y}),
/**
* Get the window position.
* @returns {Promise<Position>} The window position
*/
RelativePosition: () => { return call(WindowRelativePosition); },
/**
* Get the screen the window is on.
* @returns {Promise<Screen>}
*/
Screen: () => { return call(WindowScreen); },
/**
* Hide the window
*/
Hide: () => void call(WindowHide),
/**
* Maximise the window
*/
Maximise: () => void call(WindowMaximise),
/**
* Show the window
*/
Show: () => void call(WindowShow),
/**
* Close the window
*/
Close: () => void call(WindowClose),
/**
* Toggle the window maximise state
*/
ToggleMaximise: () => void call(WindowToggleMaximise),
/**
* Unmaximise the window
*/
UnMaximise: () => void call(WindowUnMaximise),
/**
* Minimise the window
*/
Minimise: () => void call(WindowMinimise),
/**
* Unminimise the window
*/
UnMinimise: () => void call(WindowUnMinimise),
/**
* Restore the window
*/
Restore: () => void call(WindowRestore),
/**
* Set the background colour of the window.
* @param {number} r - A value between 0 and 255
* @param {number} g - A value between 0 and 255
* @param {number} b - A value between 0 and 255
* @param {number} a - A value between 0 and 255
*/
SetBackgroundColour: (r, g, b, a) => void call(WindowSetBackgroundColour, {r, g, b, a}),
/**
* Set whether the window can be resized or not
* @param {boolean} resizable
*/
SetResizable: (resizable) => void call(WindowSetResizable, {resizable}),
/**
* Get the window width
* @returns {Promise<number>}
*/
Width: () => { return call(WindowWidth); },
/**
* Get the window height
* @returns {Promise<number>}
*/
Height: () => { return call(WindowHeight); },
/**
* Zoom in the window
*/
ZoomIn: () => void call(WindowZoomIn),
/**
* Zoom out the window
*/
ZoomOut: () => void call(WindowZoomOut),
/**
* Reset the window zoom
*/
ZoomReset: () => void call(WindowZoomReset),
/**
* Get the window zoom
* @returns {Promise<number>}
*/
GetZoomLevel: () => { return call(WindowGetZoomLevel); },
/**
* Set the window zoom level
* @param {number} zoomLevel
*/
SetZoomLevel: (zoomLevel) => void call(WindowSetZoomLevel, {zoomLevel}),
};
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,8 +0,0 @@
//go:build darwin && !production
package runtime
import _ "embed"
//go:embed runtime_debug_desktop_darwin.js
var DesktopRuntime []byte

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,8 +0,0 @@
//go:build linux && !production
package runtime
import _ "embed"
//go:embed runtime_debug_desktop_linux.js
var DesktopRuntime []byte

View File

@ -1,8 +0,0 @@
//go:build windows && !production
package runtime
import _ "embed"
//go:embed runtime_debug_desktop_windows.js
var DesktopRuntime []byte

View File

@ -1,8 +0,0 @@
//go:build darwin && production
package runtime
import _ "embed"
//go:embed runtime_production_desktop_darwin.js
var DesktopRuntime []byte

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,8 +0,0 @@
//go:build linux && production
package runtime
import _ "embed"
//go:embed runtime_production_desktop_linux.js
var DesktopRuntime []byte

View File

@ -1,8 +0,0 @@
//go:build windows && production
package runtime
import _ "embed"
//go:embed runtime_production_desktop_windows.js
var DesktopRuntime []byte

View File

@ -825,3 +825,10 @@ func (a *App) BrowserOpenURL(url string) error {
func (a *App) BrowserOpenFile(path string) error {
return browser.OpenFile(path)
}
func (a *App) Environment() EnvironmentInfo {
return EnvironmentInfo{
OS: runtime.GOOS,
Arch: runtime.GOARCH,
}
}

View File

@ -0,0 +1,6 @@
package application
type EnvironmentInfo struct {
OS string
Arch string
}

View File

@ -41,26 +41,26 @@ func (m *MessageProcessor) httpError(rw http.ResponseWriter, message string, arg
rw.Write([]byte(fmt.Sprintf(message, args...)))
}
func (m *MessageProcessor) getTargetWindow(r *http.Request) Window {
func (m *MessageProcessor) getTargetWindow(r *http.Request) (Window, string) {
windowName := r.Header.Get(webViewRequestHeaderWindowName)
if windowName != "" {
return globalApplication.GetWindowByName(windowName)
return globalApplication.GetWindowByName(windowName), windowName
}
windowID := r.Header.Get(webViewRequestHeaderWindowId)
if windowID == "" {
return nil
return nil, windowID
}
wID, err := strconv.ParseUint(windowID, 10, 64)
if err != nil {
m.Error("Window ID '%s' not parsable: %s", windowID, err)
return nil
return nil, windowID
}
targetWindow := globalApplication.getWindowForID(uint(wID))
if targetWindow == nil {
m.Error("Window ID %d not found", wID)
return nil
return nil, windowID
}
return targetWindow
return targetWindow, windowID
}
func (m *MessageProcessor) HandleRuntimeCall(rw http.ResponseWriter, r *http.Request) {
@ -115,9 +115,9 @@ func (m *MessageProcessor) HandleRuntimeCallWithIDs(rw http.ResponseWriter, r *h
}
params := QueryParams(r.URL.Query())
targetWindow := m.getTargetWindow(r)
targetWindow, nameOrID := m.getTargetWindow(r)
if targetWindow == nil {
m.httpError(rw, "No valid window found")
m.httpError(rw, fmt.Sprintf("Window '%s' not found", nameOrID))
return
}

View File

@ -6,6 +6,7 @@ import (
const (
SystemIsDarkMode = 0
Environment = 1
)
var systemMethodNames = map[int]string{
@ -17,6 +18,8 @@ func (m *MessageProcessor) processSystemMethod(method int, rw http.ResponseWrite
switch method {
case SystemIsDarkMode:
m.json(rw, globalApplication.IsDarkMode())
case Environment:
m.json(rw, globalApplication.Environment())
default:
m.httpError(rw, "Unknown system method: %d", method)
}

View File

@ -239,13 +239,13 @@ func (w *WebviewWindow) formatJS(f string, callID string, data string) string {
func (w *WebviewWindow) CallError(callID string, result string) {
if w.impl != nil {
w.impl.execJS(w.formatJS("_wails.callErrorCallback('%s', %s);", callID, result))
w.impl.execJS(w.formatJS("_wails.callErrorHandler('%s', %s);", callID, result))
}
}
func (w *WebviewWindow) CallResponse(callID string, result string) {
if w.impl != nil {
w.impl.execJS(w.formatJS("_wails.callCallback('%s', %s, true);", callID, result))
w.impl.execJS(w.formatJS("_wails.callResultHandler('%s', %s, true);", callID, result))
}
}