mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 22:55:48 +01:00
[windows-x] Refactor runtime & asset server
This commit is contained in:
parent
ec8d8e4587
commit
6923ea301b
16 changed files with 431 additions and 182 deletions
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
304
v2/internal/frontend/devserver/runtime_debug_windows.js
Normal file
304
v2/internal/frontend/devserver/runtime_debug_windows.js
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
8
v2/internal/frontend/runtime/ipc_dev.go
Normal file
8
v2/internal/frontend/runtime/ipc_dev.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//go:build dev
|
||||
|
||||
package runtime
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed ipc_dev.js
|
||||
var IPCJS []byte
|
||||
8
v2/internal/frontend/runtime/ipc_windows.go
Normal file
8
v2/internal/frontend/runtime/ipc_windows.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//go:build desktop && windows
|
||||
|
||||
package runtime
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed ipc_windows.js
|
||||
var IPCJS []byte
|
||||
|
|
@ -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>",
|
||||
|
|
|
|||
8
v2/internal/frontend/runtime/runtime_debug_desktop.go
Normal file
8
v2/internal/frontend/runtime/runtime_debug_desktop.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//go:build debug && desktop
|
||||
|
||||
package runtime
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed runtime_debug_desktop.js
|
||||
var RuntimeJS []byte
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
//+build debug
|
||||
//+build windows
|
||||
|
||||
package runtime
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed runtime_debug_windows.js
|
||||
var RuntimeJS string
|
||||
8
v2/internal/frontend/runtime/runtime_prod_desktop.go
Normal file
8
v2/internal/frontend/runtime/runtime_prod_desktop.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//go:build production && desktop
|
||||
|
||||
package runtime
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed runtime_prod_desktop.js
|
||||
var RuntimeJS []byte
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
//+build !debug
|
||||
//+build windows
|
||||
|
||||
package runtime
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed runtime_production_windows.js
|
||||
var RuntimeJS string
|
||||
Loading…
Add table
Add a link
Reference in a new issue