mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 02:31:58 +08:00
commit
ab6e7531b4
File diff suppressed because one or more lines are too long
1
assets/default/default.html
Normal file
1
assets/default/default.html
Normal file
@ -0,0 +1 @@
|
||||
<div id="app"></div>
|
2
assets/default/jquery.3.3.1.min.js
vendored
Normal file
2
assets/default/jquery.3.3.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
337
assets/default/wails.js
Normal file
337
assets/default/wails.js
Normal file
@ -0,0 +1,337 @@
|
||||
// Wails runtime JS
|
||||
|
||||
(function () {
|
||||
window.wails = window.wails || {
|
||||
$: {}
|
||||
};
|
||||
|
||||
/****************** Utility Functions ************************/
|
||||
|
||||
// -------------- Random --------------
|
||||
// AwesomeRandom
|
||||
function cryptoRandom() {
|
||||
var array = new Uint32Array(1);
|
||||
return window.crypto.getRandomValues(array)[0];
|
||||
}
|
||||
|
||||
// LOLRandom
|
||||
function basicRandom() {
|
||||
return Math.random() * 9007199254740991;
|
||||
}
|
||||
|
||||
// Pick one based on browser capability
|
||||
var randomFunc;
|
||||
if (window.crypto) {
|
||||
randomFunc = cryptoRandom;
|
||||
} else {
|
||||
randomFunc = basicRandom;
|
||||
}
|
||||
|
||||
// -------------- Identifiers ---------------
|
||||
|
||||
function isValidIdentifier(name) {
|
||||
// Don't xss yourself :-)
|
||||
try {
|
||||
new Function("var " + name);
|
||||
return true
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// -------------- JS ----------------
|
||||
function addScript(js, callbackID) {
|
||||
console.log("Adding script: " + js)
|
||||
var script = document.createElement("script");
|
||||
script.text = js;
|
||||
document.body.appendChild(script);
|
||||
console.log("Calling back with:" + callbackID);
|
||||
window.wails.events.emit(callbackID);
|
||||
}
|
||||
|
||||
// -------------- CSS ---------------
|
||||
// Adapted from webview - thanks zserge!
|
||||
function injectCSS(css) {
|
||||
var elem = document.createElement('style');
|
||||
elem.setAttribute('type', 'text/css');
|
||||
if (elem.styleSheet) {
|
||||
elem.styleSheet.cssText = css;
|
||||
} else {
|
||||
elem.appendChild(document.createTextNode(css));
|
||||
}
|
||||
var head = document.head || document.getElementsByTagName('head')[0];
|
||||
head.appendChild(elem)
|
||||
}
|
||||
|
||||
/************************* Bindings *************************/
|
||||
|
||||
var bindingsBasePath = window.wails.$;
|
||||
|
||||
// Creates the path given in the bindings path
|
||||
function addBindingPath(pathSections) {
|
||||
// Start at the base path
|
||||
var currentPath = bindingsBasePath
|
||||
// for each section of the given path
|
||||
for (var section of pathSections) {
|
||||
|
||||
// Is section a valid javascript identifier?
|
||||
if (!isValidIdentifier(section)) {
|
||||
var errMessage = section + " is not a valid javascript identifier."
|
||||
var err = new Error(errMessage)
|
||||
return [null, err]
|
||||
}
|
||||
|
||||
// Add if doesn't exist
|
||||
if (!currentPath[section]) {
|
||||
currentPath[section] = {}
|
||||
}
|
||||
// update current path to new path
|
||||
currentPath = currentPath[section]
|
||||
}
|
||||
return [currentPath, null]
|
||||
}
|
||||
|
||||
function newBinding(bindingName) {
|
||||
|
||||
// Get all the sections of the binding
|
||||
var bindingSections = bindingName.split('.');
|
||||
|
||||
// Get the actual function/method call name
|
||||
var callName = bindingSections.pop();
|
||||
|
||||
// Add path to binding
|
||||
[pathToBinding, err] = addBindingPath(bindingSections)
|
||||
|
||||
if (err != null) {
|
||||
// We need to return an error
|
||||
return err
|
||||
}
|
||||
|
||||
// Add binding call
|
||||
pathToBinding[callName] = function () {
|
||||
|
||||
// No timeout by default
|
||||
var timeout = 0;
|
||||
|
||||
// Actual function
|
||||
function dynamic() {
|
||||
var args = [].slice.call(arguments)
|
||||
return call(bindingName, args, timeout);
|
||||
}
|
||||
|
||||
// Allow setting timeout to function
|
||||
dynamic.setTimeout = function (newTimeout) {
|
||||
timeout = newTimeout;
|
||||
}
|
||||
|
||||
// Allow getting timeout to function
|
||||
dynamic.getTimeout = function () {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
return dynamic;
|
||||
}();
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
|
||||
/*************************** Calls **************************/
|
||||
|
||||
var callbacks = {};
|
||||
|
||||
// Call sends a message to the backend to call the binding with the
|
||||
// given data. A promise is returned and will be completed when the
|
||||
// backend responds. This will be resolved when the call was successful
|
||||
// or rejected if an error is passed back.
|
||||
// There is a timeout mechanism. If the call doesn't respond in the given
|
||||
// time (in milliseconds) then the promise is rejected.
|
||||
|
||||
function call(bindingName, data, timeout) {
|
||||
|
||||
// Timeout infinite by default
|
||||
if (timeout == null || timeout == undefined) {
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
// Create a promise
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
||||
// Create a unique callbackID
|
||||
var callbackID;
|
||||
do {
|
||||
callbackID = bindingName + "-" + randomFunc();
|
||||
} while (callbacks[callbackID])
|
||||
|
||||
// Set timeout
|
||||
if (timeout > 0) {
|
||||
var timeoutHandle = setTimeout(function () {
|
||||
reject(Error("Call to " + bindingName + " timed out. Request ID: " + callbackID))
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
// Store callback
|
||||
callbacks[callbackID] = {
|
||||
timeoutHandle: timeoutHandle,
|
||||
reject: reject,
|
||||
resolve: resolve
|
||||
}
|
||||
try {
|
||||
var payloaddata = JSON.stringify(data)
|
||||
// Create the message
|
||||
message = {
|
||||
type: "call",
|
||||
callbackid: callbackID,
|
||||
payload: {
|
||||
bindingName: bindingName,
|
||||
data: payloaddata,
|
||||
}
|
||||
}
|
||||
|
||||
// Make the call
|
||||
var payload = JSON.stringify(message)
|
||||
external.invoke(payload);
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Called by the backend to return data to a previously called
|
||||
// binding invocation
|
||||
function callback(incomingMessage) {
|
||||
// Parse the message
|
||||
var message
|
||||
try {
|
||||
message = JSON.parse(incomingMessage)
|
||||
} catch (e) {
|
||||
wails.log.debug("Invalid JSON passed to callback: " + e.message)
|
||||
wails.log.debug("Message: " + incomingMessage)
|
||||
return
|
||||
}
|
||||
callbackID = message.callbackid
|
||||
callbackData = callbacks[callbackID]
|
||||
if (!callbackData) {
|
||||
console.error("Callback '" + callbackID + "' not registed!!!")
|
||||
return
|
||||
}
|
||||
clearTimeout(callbackData.timeoutHandle)
|
||||
delete callbacks[callbackID]
|
||||
if (message.error) {
|
||||
return callbackData.reject(message.error)
|
||||
}
|
||||
return callbackData.resolve(message.data)
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
|
||||
|
||||
/************************** Events **************************/
|
||||
|
||||
var eventListeners = {};
|
||||
|
||||
// Registers event listeners
|
||||
function on(eventName, callback) {
|
||||
eventListeners[eventName] = eventListeners[eventName] || [];
|
||||
eventListeners[eventName].push(callback);
|
||||
}
|
||||
|
||||
// notify informs frontend listeners that an event was emitted with the given data
|
||||
function notify(eventName, data) {
|
||||
if (eventListeners[eventName]) {
|
||||
eventListeners[eventName].forEach(element => {
|
||||
var parsedData = []
|
||||
// Parse data if we have it
|
||||
if (data) {
|
||||
try {
|
||||
parsedData = JSON.parse(data);
|
||||
} catch (e) {
|
||||
wails.log.error("Invalid JSON data sent to notify. Event name = " + eventName)
|
||||
}
|
||||
}
|
||||
element.apply(null, parsedData);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// emit an event with the given name and data
|
||||
function emit(eventName) {
|
||||
|
||||
// Calculate the data
|
||||
var data = JSON.stringify([].slice.apply(arguments).slice(1));
|
||||
|
||||
// Notify backend
|
||||
message = {
|
||||
type: "event",
|
||||
payload: {
|
||||
name: eventName,
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
external.invoke(JSON.stringify(message));
|
||||
}
|
||||
|
||||
// Events calls
|
||||
window.wails.events = { emit: emit, on: on };
|
||||
|
||||
/************************************************************/
|
||||
|
||||
/************************* Logging **************************/
|
||||
|
||||
// Sends a log message to the backend with the given
|
||||
// level + message
|
||||
function sendLogMessage(level, message) {
|
||||
|
||||
// Log Message
|
||||
message = {
|
||||
type: "log",
|
||||
payload: {
|
||||
level: level,
|
||||
message: message,
|
||||
}
|
||||
}
|
||||
external.invoke(JSON.stringify(message));
|
||||
}
|
||||
|
||||
function logDebug(message) {
|
||||
sendLogMessage("debug", message);
|
||||
}
|
||||
function logInfo(message) {
|
||||
sendLogMessage("info", message);
|
||||
}
|
||||
function logWarning(message) {
|
||||
sendLogMessage("warning", message);
|
||||
}
|
||||
function logError(message) {
|
||||
sendLogMessage("error", message);
|
||||
}
|
||||
function logFatal(message) {
|
||||
sendLogMessage("fatal", message);
|
||||
}
|
||||
|
||||
window.wails.log = {
|
||||
debug: logDebug,
|
||||
info: logInfo,
|
||||
warning: logWarning,
|
||||
error: logError,
|
||||
fatal: logFatal,
|
||||
};
|
||||
|
||||
/************************** Exports *************************/
|
||||
|
||||
window.wails._ = {
|
||||
newBinding: newBinding,
|
||||
callback: callback,
|
||||
notify: notify,
|
||||
sendLogMessage: sendLogMessage,
|
||||
callbacks: callbacks,
|
||||
injectCSS: injectCSS,
|
||||
addScript: addScript,
|
||||
}
|
||||
|
||||
/************************************************************/
|
||||
|
||||
// Notify backend that the runtime has finished loading
|
||||
window.wails.events.emit("wails:loaded");
|
||||
|
||||
})()
|
179
assets/headless/index.html
Normal file
179
assets/headless/index.html
Normal file
@ -0,0 +1,179 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Wails Headless</title>
|
||||
<style>
|
||||
.wails-reconnect-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
font-family: sans-serif;
|
||||
display: none;
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
.wails-reconnect-overlay-content {
|
||||
padding: 20px 30px;
|
||||
text-align: center;
|
||||
width: 20em;
|
||||
position: relative;
|
||||
height: 17em;
|
||||
border-radius: 1em;
|
||||
margin: 5% auto 0;
|
||||
background-color: white;
|
||||
box-shadow: 1px 1px 20px 3px;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAqFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAEBAQAAAAAAAAAAAAEBAQEBAQDAwMBAQEAAAABAQEAAAAAAAAAAAABAQEAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWKCj6oAAAAN3RSTlMALiIqDhkGBAswJjP0GxP6NR4W9/ztjRDMhWU50G9g5eHXvbZ9XEI9xZTcqZl2aldKo55QwoCvZUgzhAAAAs9JREFUSMeNleeWqjAUhU0BCaH3Itiw9zKT93+zG02QK1hm/5HF+jzZJ6fQe6cyXE+jg9X7o9wxuylIIf4Tv2V3+bOrEXnf8dwQ/KQIGDN2/S+4OmVCVXL/ScBnfibxURqIByP/hONE8r8T+bDMlQ98KSl7Y8hzjpS8v1qtDh8u5f8KQpGpfnPPhqG8JeogN37Hq9eaN2xRhIwAaGnvws8F1ShxqK5ob2twYi1FAMD4rXsYtnC/JEiRbl4cUrCWhnMCLRFemXezXbb59QK4WASOsm6n2W1+4CBT2JmtzQ6fsrbGubR/NFbd2g5Y179+5w/GEHaKsHjYCet7CgrXU3txarNC7YxOVJtIj4/ERzMdZfzc31hp+8cD6eGILgarZY9uZ12hAs03vfBD9C171gS5Omz7OcvxALQIn4u8RRBBBcsi9WW2woO9ipLgfzpYlggg3ZRdROUC8KT7QLqq3W9KB5BbdFVg4929kdwp6+qaZnMCCNBdj+NyN1W885Ry/AL3D4AQbsVV4noCiM/C83kyYq80XlDAYQtralOiDzoRAHlotWl8q2tjvYlOgcg1A8jEApZa+C06TBdAz2Qv0wu11I/zZOyJQ6EwGez2P2b8PIQr1hwwnAZsAxwA4UAYOyXUxM/xp6tHAn4GUmPGM9R28oVxgC0e/zQJJI6DyhyZ1r7uzRQhpcW7x7vTaWSzKSG6aep77kroTEl3U81uSVaUTtgEINfC8epx+Q4F9SpplHG84Ek6m4RAq9/TLkOBrxyeuddZhHvGIp1XXfFy3Z3vtwNblKGiDn+J+92vwwABHghj7HnzlS1H5kB49AZvdGCFgiBPq69qfXPr3y++yilF0ON4R8eR7spAsLpZ95NqAW5tab1c4vkZm6aleajchMwYTdILQQTwE2OV411ZM9WztDjPql12caBi6gDpUKmDd4U1XNdQxZ4LIXQ5/Tr4P7I9tYcFrDK3AAAAAElFTkSuQmCC");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.wails-reconnect-overlay-title {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.wails-reconnect-overlay-message {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
/* https://codepen.io/EastingAndNorthing/pen/aNWrZz - Cheers Mark! */
|
||||
|
||||
.wails-reconnect-overlay-loadingspinner {
|
||||
pointer-events: none;
|
||||
width: 2.5em;
|
||||
height: 2.5em;
|
||||
border: 0.4em solid transparent;
|
||||
border-color: #eee;
|
||||
border-top-color: #3E67EC;
|
||||
border-radius: 50%;
|
||||
animation: loadingspin 1s linear infinite;
|
||||
margin: auto;
|
||||
padding: 2.5em;
|
||||
}
|
||||
|
||||
@keyframes loadingspin {
|
||||
100% {
|
||||
transform: rotate(360deg)
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wails-reconnect-overlay">
|
||||
<div class="wails-reconnect-overlay-content">
|
||||
<div class="wails-reconnect-overlay-title">Disconnected</div><br>
|
||||
<div class="wails-reconnect-overlay-loadingspinner"></div><br>
|
||||
<div class="wails-reconnect-overlay-message">Waiting for backend</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="app"></div>
|
||||
|
||||
<script id="wails-headless-runtime">
|
||||
(function () {
|
||||
|
||||
var websocket = null;
|
||||
var connectTimer = null;
|
||||
var reconnectOverlay = document.querySelector(".wails-reconnect-overlay");
|
||||
var connectionState = "disconnected";
|
||||
|
||||
function showReconnectOverlay() {
|
||||
reconnectOverlay.style.display = 'block';
|
||||
}
|
||||
|
||||
function hideReconnectOverlay() {
|
||||
reconnectOverlay.style.display = 'none';
|
||||
}
|
||||
|
||||
window.external = {
|
||||
invoke: function (msg) {
|
||||
websocket.send(msg);
|
||||
}
|
||||
};
|
||||
|
||||
function addScript(script, id) {
|
||||
var s = document.createElement("script")
|
||||
if (id) {
|
||||
s.id = id;
|
||||
}
|
||||
s.textContent = script;
|
||||
document.head.appendChild(s)
|
||||
}
|
||||
|
||||
function handleConnect() {
|
||||
console.log("[Wails] Connected to backend");
|
||||
addKeyListener();
|
||||
hideReconnectOverlay();
|
||||
clearInterval(connectTimer);
|
||||
websocket.onclose = handleDisconnect;
|
||||
websocket.onmessage = handleMessage;
|
||||
connectionState = "connected";
|
||||
// websocket.onerror = function () { }
|
||||
}
|
||||
|
||||
function handleDisconnect() {
|
||||
console.log("[Wails] Disconnected from backend");
|
||||
websocket = null;
|
||||
removeKeyListener();
|
||||
connectionState = "disconnected";
|
||||
showReconnectOverlay();
|
||||
connect();
|
||||
}
|
||||
|
||||
function connect() {
|
||||
connectTimer = setInterval(function () {
|
||||
if (websocket == null) {
|
||||
websocket = new WebSocket("ws://localhost:34115/ws")
|
||||
websocket.onopen = handleConnect;
|
||||
websocket.onerror = function (e) {
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
websocket = null;
|
||||
return false
|
||||
}
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function handleMessage(e) {
|
||||
addScript(e.data);
|
||||
}
|
||||
|
||||
// Key listener
|
||||
var delta = 300;
|
||||
var lastKeypressTime = 0;
|
||||
function KeyHandler(event) {
|
||||
if (event.key === "`") {
|
||||
var thisKeypressTime = new Date();
|
||||
if (thisKeypressTime - lastKeypressTime <= delta) {
|
||||
console.log("Double tap!")
|
||||
// optional - if we'd rather not detect a triple-press
|
||||
// as a second double-press, reset the timestamp
|
||||
thisKeypressTime = 0;
|
||||
}
|
||||
lastKeypressTime = thisKeypressTime;
|
||||
}
|
||||
}
|
||||
|
||||
function addKeyListener() {
|
||||
document.body.addEventListener('keydown', KeyHandler);
|
||||
}
|
||||
|
||||
function removeKeyListener() {
|
||||
document.body.removeEventListener('keydown', KeyHandler);
|
||||
}
|
||||
|
||||
connect();
|
||||
|
||||
|
||||
}());
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user