[windows-x] Refactor runtime & asset server

This commit is contained in:
Lea Anthony 2021-08-18 22:12:00 +10:00
commit 6923ea301b
16 changed files with 431 additions and 182 deletions

View file

@ -1,78 +0,0 @@
package assetserver
import (
"bytes"
"embed"
"fmt"
"github.com/leaanthony/debme"
"github.com/leaanthony/slicer"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"io/fs"
"path/filepath"
"strings"
)
type AssetServer struct {
assets debme.Debme
indexFile []byte
runtimeJS string
}
func NewAssetServer(assets embed.FS, bindingsJSON string) (*AssetServer, error) {
result := &AssetServer{
runtimeJS: `window.wailsbindings='` + bindingsJSON + `';` + runtime.RuntimeJS,
}
err := result.init(assets)
return result, err
}
func (a *AssetServer) IndexHTML() string {
return string(a.indexFile)
}
func injectScript(input string, script string) ([]byte, error) {
splits := strings.Split(input, "<head>")
if len(splits) != 2 {
return nil, fmt.Errorf("unable to locate a </body> tag in your html")
}
var result bytes.Buffer
result.WriteString(splits[0])
result.WriteString("<head>")
result.WriteString(script)
result.WriteString(splits[1])
return result.Bytes(), nil
}
func processAssets(assets embed.FS) (debme.Debme, error) {
result, err := debme.FS(assets, ".")
if err != nil {
return result, err
}
// Find index.html
stat, err := fs.Stat(assets, "index.html")
if stat != nil {
return debme.FS(assets, ".")
}
var indexFiles slicer.StringSlicer
err = fs.WalkDir(result, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if strings.HasSuffix(path, "index.html") {
indexFiles.Add(path)
}
return nil
})
if err != nil {
return debme.Debme{}, err
}
if indexFiles.Length() > 1 {
return debme.Debme{}, fmt.Errorf("multiple 'index.html' files found in assets")
}
path, _ := filepath.Split(indexFiles.AsSlice()[0])
return debme.FS(assets, path)
}

View file

@ -1,12 +1,89 @@
//go:build desktop
// +build desktop
package assetserver
import (
"bytes"
"embed"
"fmt"
"github.com/leaanthony/debme"
"github.com/leaanthony/slicer"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"io/fs"
"net/http"
"path/filepath"
"strings"
)
type AssetServer struct {
assets debme.Debme
indexFile []byte
runtimeJS []byte
}
func NewAssetServer(assets embed.FS, bindingsJSON string) (*AssetServer, error) {
result := &AssetServer{}
var buffer bytes.Buffer
buffer.Write(runtime.IPCJS)
buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
buffer.Write(runtime.RuntimeJS)
result.runtimeJS = buffer.Bytes()
err := result.init(assets)
return result, err
}
func (a *AssetServer) IndexHTML() string {
return string(a.indexFile)
}
func injectScript(input string, script string) ([]byte, error) {
splits := strings.Split(input, "<head>")
if len(splits) != 2 {
return nil, fmt.Errorf("unable to locate a </body> tag in your html")
}
var result bytes.Buffer
result.WriteString(splits[0])
result.WriteString("<head>")
result.WriteString(script)
result.WriteString(splits[1])
return result.Bytes(), nil
}
func processAssets(assets embed.FS) (debme.Debme, error) {
result, err := debme.FS(assets, ".")
if err != nil {
return result, err
}
// Find index.html
stat, err := fs.Stat(assets, "index.html")
if stat != nil {
return debme.FS(assets, ".")
}
var indexFiles slicer.StringSlicer
err = fs.WalkDir(result, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if strings.HasSuffix(path, "index.html") {
indexFiles.Add(path)
}
return nil
})
if err != nil {
return debme.Debme{}, err
}
if indexFiles.Length() > 1 {
return debme.Debme{}, fmt.Errorf("multiple 'index.html' files found in assets")
}
path, _ := filepath.Split(indexFiles.AsSlice()[0])
return debme.FS(assets, path)
}
func (a *AssetServer) init(assets embed.FS) error {
var err error
@ -18,7 +95,7 @@ func (a *AssetServer) init(assets embed.FS) error {
if err != nil {
return err
}
a.indexFile, err = injectScript(string(indexHTML), "<script>"+a.runtimeJS+"</script>")
a.indexFile, err = injectScript(string(indexHTML), `<script src="/wails/runtime.js"></script>`)
if err != nil {
return err
}
@ -31,6 +108,10 @@ func (a *AssetServer) Load(filename string) ([]byte, string, error) {
switch filename {
case "/":
content = a.indexFile
case "/wails/runtime.js":
content = a.runtimeJS
case "/wails/ipc.js":
content = runtime.IPCJS
default:
content, err = a.assets.ReadFile(filename)
}

View file

@ -1,48 +0,0 @@
// +build desktop
package assetserver
import (
"embed"
"github.com/matryer/is"
"github.com/wailsapp/wails/v2/internal/frontend/assetserver/testdata"
"strconv"
"testing"
)
var runtimeInjection = `<script defer src="/wails/runtime.js"></script>`
var expected = `<html><head><link rel="stylesheet" href="/main.css"></head><body data-wails-drag><div id="logo"></div>` + runtimeInjection + `</body></html>`
//go:embed testdata/subdir
var subdir embed.FS
//go:embed testdata
var multiple embed.FS
func TestAssetServer_Init(t *testing.T) {
is2 := is.New(t)
tests := []struct {
assets embed.FS
want string
wantErr bool
}{
{testdata.TopLevelFS, expected, false},
{subdir, expected, false},
{multiple, expected, true},
}
for idx, tt := range tests {
t.Run(strconv.Itoa(idx), func(t *testing.T) {
server, err := NewAssetServer(tt.assets)
if tt.wantErr {
is2.True(err != nil)
} else {
is2.NoErr(err)
is2.Equal(string(server.indexFile), tt.want)
}
})
}
}

File diff suppressed because one or more lines are too long

View file

@ -9,8 +9,6 @@ The lightweight framework for web-like apps
*/
/* jshint esversion: 6 */
import {SendMessage} from './ipc';
var callbacks = {};
/**
@ -95,7 +93,7 @@ export function Call(name, args, timeout) {
};
// Make the call
SendMessage('C' + JSON.stringify(payload));
window.WailsInvoke('C' + JSON.stringify(payload));
} catch (e) {
// eslint-disable-next-line
console.error(e);

View file

@ -9,8 +9,6 @@ The lightweight framework for web-like apps
*/
/* jshint esversion: 6 */
import {SendMessage} from './ipc';
// Defines a single listener with a maximum number of times to callback
/**
@ -152,7 +150,7 @@ export function EventsEmit(eventName) {
notifyListeners(payload);
// Notify Go listeners
SendMessage('EE' + JSON.stringify(payload));
window.WailsInvoke('EE' + JSON.stringify(payload));
}
export function EventsOff(eventName) {
@ -160,5 +158,5 @@ export function EventsOff(eventName) {
eventListeners.delete(eventName);
// Notify Go listeners
SendMessage('EX' + eventName);
window.WailsInvoke('EX' + eventName);
}

View file

@ -9,23 +9,12 @@ The lightweight framework for web-like apps
*/
/* jshint esversion: 6 */
// IPC Listeners
const listeners = [];
/**
* Adds a listener to IPC messages
* @param {function} callback
*/
export function AddIPCListener(callback) {
listeners.push(callback);
}
/**
* SendMessage sends the given message to the backend
*
* @param {string} message
*/
export function SendMessage(message) {
window.WailsInvoke = function (message) {
// Call Platform specific invoke method
if (PLATFORM === "windows") {
@ -35,11 +24,4 @@ export function SendMessage(message) {
} else {
console.error("Unsupported Platform");
}
// Also send to listeners
if (listeners.length > 0) {
for (let i = 0; i < listeners.length; i++) {
listeners[i](message);
}
}
}
};

View file

@ -10,8 +10,6 @@ The lightweight framework for web-like apps
/* jshint esversion: 6 */
import {SendMessage} from './ipc';
/**
* Sends a log message to the backend with the given level + message
*
@ -22,7 +20,7 @@ function sendLogMessage(level, message) {
// Log Message format:
// l[type][message]
SendMessage('L' + level + message);
window.WailsInvoke('L' + level + message);
}
/**

View file

@ -12,8 +12,6 @@ import * as Log from './log';
import {EventsEmit, EventsNotify, EventsOff, EventsOn, EventsOnce, EventsOnMultiple} from './events';
import {Callback} from './calls';
import {SetBindings} from "./bindings";
// import {AddScript, DisableDefaultContextMenu, InjectCSS} from './utils';
import {SendMessage} from './ipc';
// Backend is where the Go struct wrappers get bound to
window.backend = {};
@ -35,8 +33,8 @@ window.wails = {
};
window.wails.SetBindings(window.wailsbindings);
delete window.wails['SetBindings'];
delete window['wailsbindings'];
delete window.wails.SetBindings;
delete window.wailsbindings;
// Setup drag handler
// Based on code from: https://github.com/patr0nus/DeskGap
@ -46,7 +44,7 @@ window.addEventListener('mousedown', (e) => {
if (currentElement.hasAttribute('data-wails-no-drag')) {
break;
} else if (currentElement.hasAttribute('data-wails-drag')) {
SendMessage("drag");
window.WailsInvoke("drag");
break;
}
currentElement = currentElement.parentElement;

View file

@ -0,0 +1,8 @@
//go:build dev
package runtime
import _ "embed"
//go:embed ipc_dev.js
var IPCJS []byte

View file

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

View file

@ -5,8 +5,10 @@
"main": "index.js",
"scripts": {
"build": "run-p build:*",
"build:windows": "esbuild desktop/main.js --bundle --minify --outfile=runtime_production_windows.js --define:PLATFORM='windows'",
"build:windows-dev": "esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_debug_windows.js --define:PLATFORM='windows'",
"build:ipc-windows": "esbuild desktop/ipc.js --bundle --minify --outfile=ipc_windows.js --define:PLATFORM='windows'",
"build:ipc-dev": "esbuild desktop/ipc.js --bundle --minify --outfile=ipc_dev.js",
"build:runtime-desktop-prod": "esbuild desktop/main.js --bundle --minify --outfile=runtime_prod_desktop.js",
"build:runtime-desktop-debug": "esbuild desktop/main.js --bundle --sourcemap=inline --outfile=runtime_debug_desktop.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Lea Anthony <lea.anthony@gmail.com>",

View file

@ -0,0 +1,8 @@
//go:build debug && desktop
package runtime
import _ "embed"
//go:embed runtime_debug_desktop.js
var RuntimeJS []byte

View file

@ -1,9 +0,0 @@
//+build debug
//+build windows
package runtime
import _ "embed"
//go:embed runtime_debug_windows.js
var RuntimeJS string

View file

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

View file

@ -1,9 +0,0 @@
//+build !debug
//+build windows
package runtime
import _ "embed"
//go:embed runtime_production_windows.js
var RuntimeJS string