Compare commits

..

8 Commits

Author SHA1 Message Date
Lea Anthony
24c7362163 Even more fixes 2019-07-13 22:18:42 +10:00
Lea Anthony
f6ff7d7b16 fix: linting for hound 2019-07-13 22:12:49 +10:00
Lea Anthony
b0a075cdf2 fix: more lint fixes 2019-07-13 22:10:43 +10:00
Lea Anthony
98d4d6b33c config: eslint 2019-07-13 15:42:57 +10:00
Lea Anthony
9ba3e0512b fix: linting 2019-07-13 15:35:50 +10:00
Lea Anthony
eff63175e5 fix: lint 2019-07-13 15:34:00 +10:00
Lea Anthony
75a0b632bc fix: capitalisation and binding fix 2019-07-13 15:30:52 +10:00
Lea Anthony
a2af626477 fix: config errors 2019-07-12 10:22:19 +10:00
21 changed files with 310 additions and 336 deletions

1
.eslintignore Normal file
View File

@@ -0,0 +1 @@
runtime/js/dist/wails.js

View File

@@ -1,4 +1,4 @@
module.exports = {
{
"env": {
"browser": true,
"es6": true
@@ -26,4 +26,4 @@ module.exports = {
"always"
]
}
};
}

6
.hound.yml Normal file
View File

@@ -0,0 +1,6 @@
jshint:
config_file: .jshintrc
eslint:
enabled: true
config_file: .eslintrc
ignore_file: .eslintignore

6
app.go
View File

@@ -20,7 +20,7 @@ var BuildMode = cmd.BuildModeProd
// App defines the main application struct
type App struct {
config *Config // The Application configuration object
config *AppConfig // The Application configuration object
cli *cmd.Cli // In debug mode, we have a cli
renderer interfaces.Renderer // The renderer is what we will render the app to
logLevel string // The log level of the app
@@ -33,8 +33,8 @@ type App struct {
// CreateApp creates the application window with the given configuration
// If none given, the defaults are used
func CreateApp(optionalConfig ...*Config) *App {
var userConfig *Config
func CreateApp(optionalConfig ...*AppConfig) *App {
var userConfig *AppConfig
if len(optionalConfig) > 0 {
userConfig = optionalConfig[0]
}

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
package cmd
// Version - Wails version
const Version = "v0.17.3-pre"
const Version = "v0.17.4-pre"

View File

@@ -1,14 +1,8 @@
package wails
import (
"strings"
"github.com/dchest/htmlmin"
// "github.com/leaanthony/mewn"
)
// Config is the configuration structure used when creating a Wails App object
type Config struct {
// AppConfig is the configuration structure used when creating a Wails App object
type AppConfig struct {
Width, Height int
Title string
defaultHTML string
@@ -18,87 +12,60 @@ type Config struct {
Colour string
Resizable bool
DisableInspector bool
// isHTMLFragment bool
}
// GetWidth returns the desired width
func (a *Config) GetWidth() int {
func (a *AppConfig) GetWidth() int {
return a.Width
}
// GetHeight returns the desired height
func (a *Config) GetHeight() int {
func (a *AppConfig) GetHeight() int {
return a.Height
}
// GetTitle returns the desired window title
func (a *Config) GetTitle() string {
func (a *AppConfig) GetTitle() string {
return a.Title
}
// GetDefaultHTML returns the desired window title
func (a *Config) GetDefaultHTML() string {
func (a *AppConfig) GetDefaultHTML() string {
return a.defaultHTML
}
// GetResizable returns true if the window should be resizable
func (a *Config) GetResizable() bool {
func (a *AppConfig) GetResizable() bool {
return a.Resizable
}
// GetDisableInspector returns true if the inspector should be disabled
func (a *Config) GetDisableInspector() bool {
func (a *AppConfig) GetDisableInspector() bool {
return a.DisableInspector
}
// GetColour returns the colour
func (a *Config) GetColour() string {
func (a *AppConfig) GetColour() string {
return a.Colour
}
// GetCSS returns the user CSS
func (a *Config) GetCSS() string {
func (a *AppConfig) GetCSS() string {
return a.CSS
}
// GetJS returns the user Javascript
func (a *Config) GetJS() string {
func (a *AppConfig) GetJS() string {
return a.JS
}
func (a *Config) merge(in *Config) error {
func (a *AppConfig) merge(in *AppConfig) error {
if in.CSS != "" {
a.CSS = in.CSS
}
if in.Title != "" {
a.Title = in.Title
}
// if in.HTML != "" {
// minified, err := htmlmin.Minify([]byte(in.HTML), &htmlmin.Options{
// MinifyScripts: true,
// })
// if err != nil {
// return err
// }
// inlineHTML := string(minified)
// inlineHTML = strings.Replace(inlineHTML, "'", "\\'", -1)
// inlineHTML = strings.Replace(inlineHTML, "\n", " ", -1)
// a.HTML = strings.TrimSpace(inlineHTML)
// // Deduce whether this is a full html page or a fragment
// // The document is determined to be a fragment if an HTML
// // tag exists and is located before the first div tag
// HTMLTagIndex := strings.Index(a.HTML, "<html")
// DivTagIndex := strings.Index(a.HTML, "<div")
// if HTMLTagIndex == -1 {
// a.isHTMLFragment = true
// } else {
// if DivTagIndex < HTMLTagIndex {
// a.isHTMLFragment = true
// }
// }
// }
if in.Colour != "" {
a.Colour = in.Colour
@@ -121,14 +88,13 @@ func (a *Config) merge(in *Config) error {
}
// Creates the default configuration
func newConfig(userConfig *Config) (*Config, error) {
result := &Config{
func newConfig(userConfig *AppConfig) (*AppConfig, error) {
result := &AppConfig{
Width: 800,
Height: 600,
Resizable: true,
Title: "My Wails App",
Colour: "#FFF", // White by default
// HTML: mewn.String("./runtime/assets/default.html"),
}
if userConfig != nil {

View File

@@ -86,7 +86,7 @@ func (h *Headless) injectCSS(css string) {
minifiedCSS = strings.Replace(minifiedCSS, "\\", "\\\\", -1)
minifiedCSS = strings.Replace(minifiedCSS, "'", "\\'", -1)
minifiedCSS = strings.Replace(minifiedCSS, "\n", " ", -1)
inject := fmt.Sprintf("wails._.injectCSS('%s')", minifiedCSS)
inject := fmt.Sprintf("wails._.InjectCSS('%s')", minifiedCSS)
h.evalJS(inject, cssMessage)
}
@@ -218,7 +218,7 @@ func (h *Headless) NotifyEvent(event *messages.EventData) error {
}
}
message := fmt.Sprintf("window.wails._.notify('%s','%s')", event.Name, data)
message := fmt.Sprintf("window.wails._.Notify('%s','%s')", event.Name, data)
return h.evalJS(message, notifyMessage)
}

File diff suppressed because one or more lines are too long

View File

@@ -141,7 +141,7 @@ func (w *WebView) evalJSSync(js string) error {
wg.Done()
exit = true
})
command := fmt.Sprintf("wails._.addScript('%s', '%s')", minified, ID)
command := fmt.Sprintf("wails._.AddScript('%s', '%s')", minified, ID)
w.window.Dispatch(func() {
w.window.Eval(command)
})
@@ -226,7 +226,7 @@ func (w *WebView) Run() error {
// NewBinding registers a new binding with the frontend
func (w *WebView) NewBinding(methodName string) error {
objectCode := fmt.Sprintf("window.wails._.newBinding('%s');", methodName)
objectCode := fmt.Sprintf("window.wails._.NewBinding('%s');", methodName)
w.bindingCache = append(w.bindingCache, objectCode)
return nil
}
@@ -288,7 +288,7 @@ func (w *WebView) SelectSaveFile() string {
// Callback sends a callback to the frontend
func (w *WebView) Callback(data string) error {
callbackCMD := fmt.Sprintf("window.wails._.callback('%s');", data)
callbackCMD := fmt.Sprintf("window.wails._.Callback('%s');", data)
return w.evalJS(callbackCMD)
}
@@ -316,7 +316,7 @@ func (w *WebView) NotifyEvent(event *messages.EventData) error {
}
}
message := fmt.Sprintf("wails._.notify('%s','%s')", event.Name, data)
message := fmt.Sprintf("wails._.Notify('%s','%s')", event.Name, data)
return w.evalJS(message)
}

View File

@@ -26,12 +26,12 @@ window.wailsbridge = {
websocket: null,
callback: null,
overlayHTML:
'<div class="wails-reconnect-overlay"><div class="wails-reconnect-overlay-content"><div class="wails-reconnect-overlay-title">Wails Bridge</div><br><div class="wails-reconnect-overlay-loadingspinner"></div><br><div id="wails-reconnect-overlay-message">Waiting for backend</div></div></div>',
'<div class="wails-reconnect-overlay"><div class="wails-reconnect-overlay-content"><div class="wails-reconnect-overlay-title">Wails Bridge</div><br><div class="wails-reconnect-overlay-loadingspinner"></div><br><div id="wails-reconnect-overlay-message">Waiting for backend</div></div></div>',
overlayCSS:
'.wails-reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(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:14em;border-radius:1em;margin:5% auto 0;background-color:#fff;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}.wails-reconnect-overlay-loadingspinner{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#3E67EC #eee #eee;border-radius:50%;animation:loadingspin 1s linear infinite;margin:auto;padding:2.5em}@keyframes loadingspin{100%{transform:rotate(360deg)}}',
'.wails-reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(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:14em;border-radius:1em;margin:5% auto 0;background-color:#fff;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}.wails-reconnect-overlay-loadingspinner{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#3E67EC #eee #eee;border-radius:50%;animation:loadingspin 1s linear infinite;margin:auto;padding:2.5em}@keyframes loadingspin{100%{transform:rotate(360deg)}}',
log: function (message) {
// eslint-disable-next-line
console.log(
console.log(
'%c wails bridge %c ' + message + ' ',
'background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem',
'background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem'
@@ -184,12 +184,12 @@ function startBridge() {
case 'b':
var binding = message.data.slice(1);
//log("Binding: " + binding)
window.wails._.newBinding(binding);
window.wails._.NewBinding(binding);
break;
// Call back
case 'c':
var callbackData = message.data.slice(1);
window.wails._.callback(callbackData);
window.wails._.Callback(callbackData);
break;
default:
window.wails.Log.Error('Unknown message type received: ' + message.data[0]);

View File

@@ -1,4 +1,4 @@
module.exports = {
{
"env": {
"browser": true,
"es6": true
@@ -277,4 +277,4 @@ module.exports = {
"never"
]
}
};
}

View File

@@ -1 +1 @@
!function(n){var e={};function t(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return n[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,r){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:r})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(r,o,function(e){return n[e]}.bind(null,o));return r},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){"use strict";t.r(e);var r={};t.r(r),t.d(r,"Debug",function(){return c}),t.d(r,"Info",function(){return u}),t.d(r,"Warning",function(){return l}),t.d(r,"Error",function(){return f}),t.d(r,"Fatal",function(){return d});var o=window&&window.external&&window.external.invoke?window.external.invoke:console.log;function a(n,e,t){o(JSON.stringify({type:n,callbackID:t,payload:e}))}function i(n,e){a("log",{level:n,message:e})}function c(n){i("debug",n)}function u(n){i("info",n)}function l(n){i("warning",n)}function f(n){i("error",n)}function d(n){i("fatal",n)}var s=function n(e,t){(function(n,e){if(!(n instanceof e))throw new TypeError("Cannot call a class as a function")})(this,n),t=t||-1,this.Callback=function(n){return e.apply(null,n),-1!==t&&0===(t-=1)}},v={};function p(n,e,t){v[n]=v[n]||[];var r=new s(e,t);v[n].push(r)}function w(n){a("event",{name:n,data:JSON.stringify([].slice.apply(arguments).slice(1))})}var y={};var g={};var m=window.crypto?function(){var n=new Uint32Array(1);return window.crypto.getRandomValues(n)[0]}:function(){return 9007199254740991*Math.random()};function b(n,e,t){return(null==t||null==t)&&(t=0),new Promise(function(r,o){var i;do{i=n+"-"+m()}while(g[i]);if(0<t)var c=setTimeout(function(){o(Error("Call to "+n+" timed out. Request ID: "+i))},t);g[i]={timeoutHandle:c,reject:o,resolve:r};try{a("call",{bindingName:n,data:JSON.stringify(e)},i)}catch(n){console.error(n)}})}var h=window.backend;function O(n){try{return new Function("var "+n),!0}catch(n){return!1}}function S(){return(S=Object.assign||function(n){for(var e,t=1;t<arguments.length;t++)for(var r in e=arguments[t])Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}).apply(this,arguments)}window.wails=window.wails||{},window.backend={};var k={NewBinding:function(n){var e=n.split(".").splice(1),t=e.pop(),r=function(n){var e=h;for(var t in n){var r=n[t];if(!O(r))return[null,new Error(r+" is not a valid javascript identifier.")];e[r]||(e[r]={}),e=e[r]}return[e,null]}(e),o=r[0],a=r[1];return null==a?void(o[t]=function(){function e(){var e=[].slice.call(arguments);return b(n,e,t)}var t=0;return e.setTimeout=function(n){t=n},e.getTimeout=function(){return t},e}()):a},Callback:function(n){var e;n=decodeURIComponent(n.replace(/\s+/g,"").replace(/[0-9a-f]{2}/g,"%$&"));try{e=JSON.parse(n)}catch(e){return c("Invalid JSON passed to callback: "+e.message),void c("Message: "+n)}var t=e.callbackid,r=g[t];return r?(clearTimeout(r.timeoutHandle),delete g[t],e.error?r.reject(e.error):r.resolve(e.data)):void console.error("Callback '".concat(t,"' not registed!!!"))},Notify:function(n,e){if(v[n]){for(var t=v[n].slice(),r=0;r<v[n].length;r+=1){var o=v[n][r],a=[];if(e)try{a=JSON.parse(e)}catch(e){f("Invalid JSON data sent to notify. Event name = "+n)}o.Callback(a)&&t.splice(r,1)}v[n]=t}},AddScript:function(n,e){var t=document.createElement("script");t.text=n,document.body.appendChild(t),e&&w(e)},InjectCSS:function(n){var e=document.createElement("style");e.setAttribute("type","text/css"),e.styleSheet?e.styleSheet.cssText=n:e.appendChild(document.createTextNode(n)),(document.head||document.getElementsByTagName("head")[0]).appendChild(e)}},j={Log:r,Event:{On:function(n,e){p(n,e)},Emit:w,Heartbeat:function(n,e,t){var r=null;y[n]=function(){clearInterval(r),t()},r=setInterval(function(){w(n)},e)},Acknowledge:function(n){if(!y[n])throw new f("Cannot acknowledge unknown heartbeat '".concat(n,"'"));y[n]()}},_:k};S(window.wails,j),w("wails:loaded")}]);
!function(n){var e={};function t(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return n[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=n,t.c=e,t.d=function(n,e,r){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:r})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(r,o,function(e){return n[e]}.bind(null,o));return r},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,"a",e),e},t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.p="",t(t.s=0)}([function(n,e,t){"use strict";t.r(e);var r={};function o(n,e,t){!function(n){window&&window.external&&window.external.invoke?window.external.invoke(n):console.log("[No external.invoke] ".concat(n))}(JSON.stringify({type:n,callbackID:t,payload:e}))}function a(n,e){o("log",{level:n,message:e})}function i(n){a("debug",n)}function c(n){a("info",n)}function u(n){a("warning",n)}function l(n){a("error",n)}function f(n){a("fatal",n)}t.r(r),t.d(r,"Debug",function(){return i}),t.d(r,"Info",function(){return c}),t.d(r,"Warning",function(){return u}),t.d(r,"Error",function(){return l}),t.d(r,"Fatal",function(){return f});var d=function n(e,t){(function(n,e){if(!(n instanceof e))throw new TypeError("Cannot call a class as a function")})(this,n),t=t||-1,this.Callback=function(n){return e.apply(null,n),-1!==t&&0===(t-=1)}},s={};function p(n,e,t){s[n]=s[n]||[];var r=new d(e,t);s[n].push(r)}function v(n){o("event",{name:n,data:JSON.stringify([].slice.apply(arguments).slice(1))})}var w={};var y={};var g=window.crypto?function(){var n=new Uint32Array(1);return window.crypto.getRandomValues(n)[0]}:function(){return 9007199254740991*Math.random()};function m(n,e,t){return(null==t||null==t)&&(t=0),new Promise(function(r,a){var i;do{i=n+"-"+g()}while(y[i]);if(0<t)var c=setTimeout(function(){a(Error("Call to "+n+" timed out. Request ID: "+i))},t);y[i]={timeoutHandle:c,reject:a,resolve:r};try{o("call",{bindingName:n,data:JSON.stringify(e)},i)}catch(n){console.error(n)}})}function b(n){try{return new Function("var "+n),!0}catch(n){return!1}}function h(){return(h=Object.assign||function(n){for(var e,t=1;t<arguments.length;t++)for(var r in e=arguments[t])Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}).apply(this,arguments)}window.backend={},window.wails=window.wails||{},window.backend={};var O={NewBinding:function(n){var e=[].concat(n.split(".").splice(1)),t=window.backend;if(1<e.length)for(var r,o=0;o<e.length-1;o+=1){if(!b(r=e[o]))return new Error("".concat(r," is not a valid javascript identifier."));t[r]={},t=t[r]}var a=e.pop();return b(a)?void(t[a]=function(){function e(){var e=[].slice.call(arguments);return m(n,e,t)}var t=0;return e.setTimeout=function(n){t=n},e.getTimeout=function(){return t},e}()):new Error("".concat(a," is not a valid javascript identifier."))},Callback:function(n){var e;n=decodeURIComponent(n.replace(/\s+/g,"").replace(/[0-9a-f]{2}/g,"%$&"));try{e=JSON.parse(n)}catch(e){return i("Invalid JSON passed to callback: "+e.message),void i("Message: "+n)}var t=e.callbackid,r=y[t];return r?(clearTimeout(r.timeoutHandle),delete y[t],e.error?r.reject(e.error):r.resolve(e.data)):void console.error("Callback '".concat(t,"' not registed!!!"))},Notify:function(n,e){if(s[n]){for(var t=s[n].slice(),r=0;r<s[n].length;r+=1){var o=s[n][r],a=[];if(e)try{a=JSON.parse(e)}catch(e){l("Invalid JSON data sent to notify. Event name = "+n)}o.Callback(a)&&t.splice(r,1)}s[n]=t}},AddScript:function(n,e){var t=document.createElement("script");t.text=n,document.body.appendChild(t),e&&v(e)},InjectCSS:function(n){var e=document.createElement("style");e.setAttribute("type","text/css"),e.styleSheet?e.styleSheet.cssText=n:e.appendChild(document.createTextNode(n)),(document.head||document.getElementsByTagName("head")[0]).appendChild(e)}},S={Log:r,Events:{On:function(n,e){p(n,e)},Emit:v,Heartbeat:function(n,e,t){var r=null;w[n]=function(){clearInterval(r),t()},r=setInterval(function(){v(n)},e)},Acknowledge:function(n){if(!w[n])throw new l("Cannot acknowledge unknown heartbeat '".concat(n,"'"));w[n]()}},_:O};h(window.wails,S),v("wails:loaded")}]);

View File

@@ -7,88 +7,74 @@
The lightweight framework for web-like apps
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 6 */
import { Call } from './calls';
var bindingsBasePath = window.backend;
window.backend = {};
// Determines if the given identifier is valid Javascript
function isValidIdentifier(name) {
// Don't xss yourself :-)
try {
new Function('var ' + name);
return true;
} catch (e) {
return false;
}
}
// 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 sectionIndex in pathSections) {
var section = pathSections[sectionIndex];
// 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];
// Don't xss yourself :-)
try {
new Function('var ' + name);
return true;
} catch (e) {
return false;
}
}
// eslint-disable-next-line max-lines-per-function
export function NewBinding(bindingName) {
// Get all the sections of the binding
var bindingSections = bindingName.split('.').splice(1);
// Get all the sections of the binding
var bindingSections = [].concat(bindingName.split('.').splice(1));
var pathToBinding = window.backend;
// Get the actual function/method call name
var callName = bindingSections.pop();
// Check if we have a path (IE Struct)
if (bindingSections.length > 1) {
// Iterate over binding sections, adding them to the window.backend object
for (let index = 0; index < bindingSections.length - 1; index += 1) {
const name = bindingSections[index];
// Is name a valid javascript identifier?
if (!isValidIdentifier(name)) {
return new Error(`${name} is not a valid javascript identifier.`);
}
pathToBinding[name] = {};
pathToBinding = pathToBinding[name];
}
}
// Add path to binding
var bs = addBindingPath(bindingSections);
var pathToBinding = bs[0];
var err = bs[1];
// Get the actual function/method call name
const name = bindingSections.pop();
if (err != null) {
// We need to return an error
return err;
}
// Is name a valid javascript identifier?
if (!isValidIdentifier(name)) {
return new Error(`${name} is not a valid javascript identifier.`);
}
// Add binding call
pathToBinding[callName] = function () {
// Add binding call
pathToBinding[name] = function () {
// No timeout by default
var timeout = 0;
// No timeout by default
var timeout = 0;
// Actual function
function dynamic() {
var args = [].slice.call(arguments);
return Call(bindingName, args, timeout);
}
// 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 setting timeout to function
dynamic.setTimeout = function (newTimeout) {
timeout = newTimeout;
};
// Allow getting timeout to function
dynamic.getTimeout = function () {
return timeout;
};
// Allow getting timeout to function
dynamic.getTimeout = function () {
return timeout;
};
return dynamic;
}();
return dynamic;
}();
}

View File

@@ -7,13 +7,14 @@
The lightweight framework for web-like apps
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 6 */
import { SystemCall } from './calls';
export function OpenURL(url) {
return SystemCall('Browser.OpenURL', url);
return SystemCall('Browser.OpenURL', url);
}
export function OpenFile(filename) {
return SystemCall('Browser.OpenFile', filename);
return SystemCall('Browser.OpenFile', filename);
}

View File

@@ -1,26 +1,36 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The lightweight framework for web-like apps
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 6 */
import { Debug } from './log';
import { SendMessage } from './ipc'
import { SendMessage } from './ipc';
var callbacks = {};
// AwesomeRandom
function cryptoRandom() {
var array = new Uint32Array(1);
return window.crypto.getRandomValues(array)[0];
var array = new Uint32Array(1);
return window.crypto.getRandomValues(array)[0];
}
// LOLRandom
function basicRandom() {
return Math.random() * 9007199254740991;
return Math.random() * 9007199254740991;
}
// Pick one based on browser capability
var randomFunc;
if (window.crypto) {
randomFunc = cryptoRandom;
randomFunc = cryptoRandom;
} else {
randomFunc = basicRandom;
randomFunc = basicRandom;
}
@@ -33,47 +43,47 @@ if (window.crypto) {
export function Call(bindingName, data, timeout) {
// Timeout infinite by default
if (timeout == null || timeout == undefined) {
timeout = 0;
}
// Timeout infinite by default
if (timeout == null || timeout == undefined) {
timeout = 0;
}
// Create a promise
return new Promise(function (resolve, reject) {
// Create a promise
return new Promise(function (resolve, reject) {
// Create a unique callbackID
var callbackID;
do {
callbackID = bindingName + '-' + randomFunc();
} while (callbacks[callbackID]);
// 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);
}
// 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
};
// Store callback
callbacks[callbackID] = {
timeoutHandle: timeoutHandle,
reject: reject,
resolve: resolve
};
try {
const payload = {
bindingName: bindingName,
data: JSON.stringify(data),
}
try {
const payload = {
bindingName: bindingName,
data: JSON.stringify(data),
};
// Make the call
SendMessage('call', payload, callbackID)
} catch (e) {
// eslint-disable-next-line
console.error(e);
}
});
// Make the call
SendMessage('call', payload, callbackID);
} catch (e) {
// eslint-disable-next-line
console.error(e);
}
});
}
@@ -81,36 +91,36 @@ export function Call(bindingName, data, timeout) {
// binding invocation
export function Callback(incomingMessage) {
// Decode the message - Credit: https://stackoverflow.com/a/13865680
incomingMessage = decodeURIComponent(incomingMessage.replace(/\s+/g, '').replace(/[0-9a-f]{2}/g, '%$&'));
// Decode the message - Credit: https://stackoverflow.com/a/13865680
incomingMessage = decodeURIComponent(incomingMessage.replace(/\s+/g, '').replace(/[0-9a-f]{2}/g, '%$&'));
// Parse the message
var message;
try {
message = JSON.parse(incomingMessage);
} catch (e) {
Debug('Invalid JSON passed to callback: ' + e.message);
Debug('Message: ' + incomingMessage);
return;
}
var callbackID = message.callbackid;
var callbackData = callbacks[callbackID];
if (!callbackData) {
// eslint-disable-next-line
console.error(`Callback '${callbackID}' not registed!!!`);
return;
}
clearTimeout(callbackData.timeoutHandle);
// Parse the message
var message;
try {
message = JSON.parse(incomingMessage);
} catch (e) {
const error = `Invalid JSON passed to callback: ${e.message}. Message: ${incomingMessage}`;
Debug(error);
throw new Error(error);
}
var callbackID = message.callbackid;
var callbackData = callbacks[callbackID];
if (!callbackData) {
const error = `Callback '${callbackID}' not registed!!!`;
console.error(error); // eslint-disable-line
throw new Error(error);
}
clearTimeout(callbackData.timeoutHandle);
delete callbacks[callbackID];
delete callbacks[callbackID];
if (message.error) {
return callbackData.reject(message.error);
}
return callbackData.resolve(message.data);
if (message.error) {
return callbackData.reject(message.error);
}
return callbackData.resolve(message.data);
}
// systemCall is used to call wails methods from the frontend
export function SystemCall(method, data) {
return Call('.wails.' + method, data);
return Call('.wails.' + method, data);
}

View File

@@ -7,98 +7,99 @@
The lightweight framework for web-like apps
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 6 */
import { Error } from './log';
import { SendMessage } from './ipc';
// Defines a single listener with a maximum number of times to callback
class Listener {
constructor(callback, maxCallbacks) {
// Default of -1 means infinite
maxCallbacks = maxCallbacks || -1;
// Callback invokes the callback with the given data
// Returns true if this listener should be destroyed
this.Callback = (data) => {
callback.apply(null, data);
// If maxCallbacks is infinite, return false (do not destroy)
if (maxCallbacks === -1) {
return false;
}
// Decrement maxCallbacks. Return true if now 0, otherwise false
maxCallbacks -= 1;
return maxCallbacks === 0;
};
}
constructor(callback, maxCallbacks) {
// Default of -1 means infinite
maxCallbacks = maxCallbacks || -1;
// Callback invokes the callback with the given data
// Returns true if this listener should be destroyed
this.Callback = (data) => {
callback.apply(null, data);
// If maxCallbacks is infinite, return false (do not destroy)
if (maxCallbacks === -1) {
return false;
}
// Decrement maxCallbacks. Return true if now 0, otherwise false
maxCallbacks -= 1;
return maxCallbacks === 0;
};
}
}
var eventListeners = {};
// Registers an event listener that will be invoked `maxCallbacks` times before being destroyed
export function OnMultiple(eventName, callback, maxCallbacks) {
eventListeners[eventName] = eventListeners[eventName] || [];
const thisListener = new Listener(callback, maxCallbacks);
eventListeners[eventName].push(thisListener);
eventListeners[eventName] = eventListeners[eventName] || [];
const thisListener = new Listener(callback, maxCallbacks);
eventListeners[eventName].push(thisListener);
}
// Registers an event listener that will be invoked every time the event is emitted
export function On(eventName, callback) {
OnMultiple(eventName, callback);
OnMultiple(eventName, callback);
}
// Registers an event listener that will be invoked once then destroyed
export function Once(eventName, callback) {
OnMultiple(eventName, callback, 1);
OnMultiple(eventName, callback, 1);
}
// Notify informs frontend listeners that an event was emitted with the given data
export function Notify(eventName, data) {
// Check if we have any listeners for this event
if (eventListeners[eventName]) {
// Check if we have any listeners for this event
if (eventListeners[eventName]) {
// Keep a list of listener indexes to destroy
const newEventListenerList = eventListeners[eventName].slice();
// Keep a list of listener indexes to destroy
const newEventListenerList = eventListeners[eventName].slice();
// Iterate listeners
for (let count = 0; count < eventListeners[eventName].length; count += 1) {
// Iterate listeners
for (let count = 0; count < eventListeners[eventName].length; count += 1) {
// Get next listener
const listener = eventListeners[eventName][count];
// Get next listener
const listener = eventListeners[eventName][count];
// Parse data if we have it
var parsedData = [];
if (data) {
try {
parsedData = JSON.parse(data);
} catch (e) {
Error('Invalid JSON data sent to notify. Event name = ' + eventName);
}
}
// Do the callback
const destroy = listener.Callback(parsedData);
if (destroy) {
// if the listener indicated to destroy itself, add it to the destroy list
newEventListenerList.splice(count, 1);
}
}
// Parse data if we have it
var parsedData = [];
if (data) {
try {
parsedData = JSON.parse(data);
} catch (e) {
Error('Invalid JSON data sent to notify. Event name = ' + eventName);
}
}
// Do the callback
const destroy = listener.Callback(parsedData);
if (destroy) {
// if the listener indicated to destroy itself, add it to the destroy list
newEventListenerList.splice(count, 1);
}
}
// Update callbacks with new list of listners
eventListeners[eventName] = newEventListenerList;
}
// Update callbacks with new list of listners
eventListeners[eventName] = newEventListenerList;
}
}
// Emit an event with the given name and data
export function Emit(eventName) {
// Calculate the data
var data = JSON.stringify([].slice.apply(arguments).slice(1));
// Calculate the data
var data = JSON.stringify([].slice.apply(arguments).slice(1));
// Notify backend
const payload = {
name: eventName,
data: data,
}
SendMessage('event', payload)
// Notify backend
const payload = {
name: eventName,
data: data,
};
SendMessage('event', payload);
}
const heartbeatCallbacks = {};
@@ -107,32 +108,32 @@ const heartbeatCallbacks = {};
// the event is acknowledged via `Event.Acknowledge`. Once this happens, `callback` is invoked ONCE
export function Heartbeat(eventName, timeInMilliseconds, callback) {
// Declare interval variable
let interval = null;
// Declare interval variable
let interval = null;
// Setup callback
function dynamicCallback() {
// Kill interval
clearInterval(interval);
// Callback
callback();
}
// Setup callback
function dynamicCallback() {
// Kill interval
clearInterval(interval);
// Callback
callback();
}
// Register callback
heartbeatCallbacks[eventName] = dynamicCallback;
// Register callback
heartbeatCallbacks[eventName] = dynamicCallback;
// Start emitting the event
interval = setInterval(function () {
Emit(eventName);
}, timeInMilliseconds);
// Start emitting the event
interval = setInterval(function () {
Emit(eventName);
}, timeInMilliseconds);
}
export function Acknowledge(eventName) {
// If we are waiting for acknowledgement for this event type
if (heartbeatCallbacks[eventName]) {
// Acknowledge!
heartbeatCallbacks[eventName]();
} else {
throw new Error(`Cannot acknowledge unknown heartbeat '${eventName}'`);
}
// If we are waiting for acknowledgement for this event type
if (heartbeatCallbacks[eventName]) {
// Acknowledge!
heartbeatCallbacks[eventName]();
} else {
throw new Error(`Cannot acknowledge unknown heartbeat '${eventName}'`);
}
}

View File

@@ -7,22 +7,22 @@
The lightweight framework for web-like apps
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 6 */
// var Invoke = window.external.invoke;
var Invoke;
if (window && window.external && window.external.invoke) {
Invoke = window.external.invoke;
} else {
Invoke = console.log;
function Invoke(message) {
if (window && window.external && window.external.invoke) {
window.external.invoke(message);
} else {
console.log(`[No external.invoke] ${message}`); // eslint-disable-line
}
}
export function SendMessage(type, payload, callbackID) {
const message = {
type,
callbackID,
payload
};
Invoke(JSON.stringify(message));
const message = {
type,
callbackID,
payload
};
Invoke(JSON.stringify(message));
}

View File

@@ -7,6 +7,7 @@
The lightweight framework for web-like apps
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 6 */
import { SendMessage } from './ipc';
@@ -14,31 +15,31 @@ import { SendMessage } from './ipc';
// level + message
function sendLogMessage(level, message) {
// Log Message
const payload = {
level: level,
message: message,
}
SendMessage('log', payload)
// Log Message
const payload = {
level: level,
message: message,
};
SendMessage('log', payload);
}
export function Debug(message) {
sendLogMessage('debug', message);
sendLogMessage('debug', message);
}
export function Info(message) {
sendLogMessage('info', message);
sendLogMessage('info', message);
}
export function Warning(message) {
sendLogMessage('warning', message);
sendLogMessage('warning', message);
}
export function Error(message) {
sendLogMessage('error', message);
sendLogMessage('error', message);
}
export function Fatal(message) {
sendLogMessage('fatal', message);
sendLogMessage('fatal', message);
}

View File

@@ -7,6 +7,7 @@
The lightweight framework for web-like apps
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 6 */
import * as Log from './log';
import { On, Emit, Notify, Heartbeat, Acknowledge } from './events';
import { NewBinding } from './bindings';
@@ -19,24 +20,24 @@ window.backend = {};
// Setup internal calls
var internal = {
NewBinding,
Callback,
Notify,
AddScript,
InjectCSS
}
NewBinding,
Callback,
Notify,
AddScript,
InjectCSS
};
// Setup runtime structure
var runtime = {
Log,
Event: {
On,
Emit,
Heartbeat,
Acknowledge,
},
_: internal,
}
Log,
Events: {
On,
Emit,
Heartbeat,
Acknowledge,
},
_: internal,
};
// Augment global
Object.assign(window.wails, runtime);

View File

@@ -7,27 +7,28 @@
The lightweight framework for web-like apps
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 6 */
import { Emit } from './events';
export function AddScript(js, callbackID) {
var script = document.createElement('script');
script.text = js;
document.body.appendChild(script);
if (callbackID) {
Emit(callbackID);
}
var script = document.createElement('script');
script.text = js;
document.body.appendChild(script);
if (callbackID) {
Emit(callbackID);
}
}
// Adapted from webview - thanks zserge!
export 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);
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);
}