mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 01:13:03 +08:00
[windows-x] Support embed.fs assets, log runtime
This commit is contained in:
parent
1a69d93d32
commit
244b3dc2b4
@ -13,6 +13,7 @@ require (
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/jackmordaunt/icns v1.0.0
|
||||
github.com/jchv/go-webview2 v0.0.0-20210720204005-cbb937ae0f7f
|
||||
github.com/klauspost/compress v1.11.3 // indirect
|
||||
github.com/leaanthony/clir v1.0.4
|
||||
github.com/leaanthony/debme v1.2.1
|
||||
@ -45,5 +46,6 @@ require (
|
||||
nhooyr.io/websocket v1.8.6
|
||||
)
|
||||
|
||||
replace github.com/tadvi/winc v0.0.0-20190405175627-5454f291903d => C:\Users\leaan\GolandProjects\winc
|
||||
replace github.com/tadvi/winc v0.0.0-20190405175627-5454f291903d => C:\Users\leaan\GolandProjects\winc
|
||||
|
||||
replace github.com/jchv/go-webview2 v0.0.0-20210720204005-cbb937ae0f7f => C:\Users\leaan\GolandProjects\go-webview2
|
||||
|
@ -72,6 +72,8 @@ github.com/jackmordaunt/icns v1.0.0 h1:RYSxplerf/l/DUd09AHtITwckkv/mqjVv4DjYdPmA
|
||||
github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5 h1:pdFFlHXY9tZXmJz+tRSm1DzYEH4ebha7cffmm607bMU=
|
||||
github.com/jchv/go-winloader v0.0.0-20200815041850-dec1ee9a7fd5/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
@ -111,8 +113,6 @@ github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k=
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
@ -145,8 +145,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tadvi/winc v0.0.0-20190405175627-5454f291903d h1:IMe61i0F1F/AugXLCNYqi8NSqRm6ybWloiU/lQRnk+I=
|
||||
github.com/tadvi/winc v0.0.0-20190405175627-5454f291903d/go.mod h1:tNBZi4sduF/C3bQE2wGTIccmErQ4A9M9QkPsICVg+oE=
|
||||
github.com/tdewolff/minify v2.3.6+incompatible h1:2hw5/9ZvxhWLvBUnHE06gElGYz+Jv9R4Eys0XUzItYo=
|
||||
github.com/tdewolff/minify v2.3.6+incompatible/go.mod h1:9Ov578KJUmAWpS6NeZwRZyT56Uf6o3Mcz9CEsg8USYs=
|
||||
github.com/tdewolff/parse v2.3.4+incompatible h1:x05/cnGwIMf4ceLuDMBOdQ1qGniMoxpP46ghf0Qzh38=
|
||||
@ -205,8 +203,9 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/dispatcher"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||
"github.com/wailsapp/wails/v2/internal/signal"
|
||||
@ -22,9 +23,6 @@ type App struct {
|
||||
// Indicates if the app is in debug mode
|
||||
debug bool
|
||||
|
||||
// This is our binding DB
|
||||
bindings *binding.Bindings
|
||||
|
||||
// Startup/Shutdown
|
||||
startupCallback func(ctx context.Context)
|
||||
shutdownCallback func()
|
||||
@ -131,12 +129,13 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
||||
bindingExemptions := []interface{}{appoptions.Startup, appoptions.Shutdown}
|
||||
appBindings := binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions)
|
||||
|
||||
appFrontend := NewFrontend(appoptions, myLogger, appBindings)
|
||||
messageDispatcher := dispatcher.NewDispatcher(myLogger, appBindings)
|
||||
|
||||
appFrontend := NewFrontend(appoptions, myLogger, appBindings, messageDispatcher)
|
||||
|
||||
result := &App{
|
||||
frontend: appFrontend,
|
||||
logger: myLogger,
|
||||
bindings: appBindings,
|
||||
menuManager: menuManager,
|
||||
startupCallback: appoptions.Startup,
|
||||
shutdownCallback: appoptions.Shutdown,
|
||||
|
@ -8,6 +8,6 @@ import (
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
)
|
||||
|
||||
func NewFrontend(appoptions *options.App, myLogger *logger.Logger, bindings *binding.Bindings) frontend.Frontend {
|
||||
return windows.NewFrontend(appoptions, myLogger, bindings)
|
||||
func NewFrontend(appoptions *options.App, myLogger *logger.Logger, bindings *binding.Bindings, dispatcher frontend.Dispatcher) frontend.Frontend {
|
||||
return windows.NewFrontend(appoptions, myLogger, bindings, dispatcher)
|
||||
}
|
||||
|
74
v2/internal/frontend/assetserver/assetserver.go
Normal file
74
v2/internal/frontend/assetserver/assetserver.go
Normal file
@ -0,0 +1,74 @@
|
||||
package assetserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"fmt"
|
||||
"github.com/leaanthony/debme"
|
||||
"github.com/leaanthony/slicer"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AssetServer struct {
|
||||
assets debme.Debme
|
||||
indexFile []byte
|
||||
}
|
||||
|
||||
func (a *AssetServer) IndexHTML() string {
|
||||
return string(a.indexFile)
|
||||
}
|
||||
|
||||
func NewAssetServer(assets embed.FS) (*AssetServer, error) {
|
||||
result := &AssetServer{}
|
||||
err := result.init(assets)
|
||||
return result, err
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
43
v2/internal/frontend/assetserver/assetserver_desktop.go
Normal file
43
v2/internal/frontend/assetserver/assetserver_desktop.go
Normal file
@ -0,0 +1,43 @@
|
||||
// +build desktop
|
||||
|
||||
package assetserver
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (a *AssetServer) init(assets embed.FS) error {
|
||||
|
||||
var err error
|
||||
a.assets, err = processAssets(assets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
indexHTML, err := a.assets.ReadFile("index.html")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.indexFile, err = injectScript(string(indexHTML), "<script>"+runtime.RuntimeJS+"</script>")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AssetServer) Load(filename string) ([]byte, string, error) {
|
||||
var content []byte
|
||||
var err error
|
||||
switch filename {
|
||||
case "/":
|
||||
content = a.indexFile
|
||||
default:
|
||||
content, err = a.assets.ReadFile(filename)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
mimeType := http.DetectContentType(content)
|
||||
return content, mimeType, nil
|
||||
}
|
48
v2/internal/frontend/assetserver/assetserver_desktop_test.go
Normal file
48
v2/internal/frontend/assetserver/assetserver_desktop_test.go
Normal file
@ -0,0 +1,48 @@
|
||||
// +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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
8
v2/internal/frontend/assetserver/testdata/index.html
vendored
Normal file
8
v2/internal/frontend/assetserver/testdata/index.html
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<link href="/main.css" rel="stylesheet">
|
||||
</head>
|
||||
<body data-wails-drag>
|
||||
<div id="logo"></div>
|
||||
</body>
|
||||
</html>
|
39
v2/internal/frontend/assetserver/testdata/main.css
vendored
Normal file
39
v2/internal/frontend/assetserver/testdata/main.css
vendored
Normal file
File diff suppressed because one or more lines are too long
20
v2/internal/frontend/assetserver/testdata/main.js
vendored
Normal file
20
v2/internal/frontend/assetserver/testdata/main.js
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
import {ready} from '@wails/runtime';
|
||||
|
||||
ready(() => {
|
||||
// Get input + focus
|
||||
let nameElement = document.getElementById("name");
|
||||
nameElement.focus();
|
||||
|
||||
// Setup the greet function
|
||||
window.greet = function () {
|
||||
|
||||
// Get name
|
||||
let name = nameElement.value;
|
||||
|
||||
// Call App.Greet(name)
|
||||
window.backend.main.App.Greet(name).then((result) => {
|
||||
// Update result with data back from App.Greet()
|
||||
document.getElementById("result").innerText = result;
|
||||
});
|
||||
};
|
||||
});
|
8
v2/internal/frontend/assetserver/testdata/subdir/index.html
vendored
Normal file
8
v2/internal/frontend/assetserver/testdata/subdir/index.html
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<link href="/main.css" rel="stylesheet">
|
||||
</head>
|
||||
<body data-wails-drag>
|
||||
<div id="logo"></div>
|
||||
</body>
|
||||
</html>
|
39
v2/internal/frontend/assetserver/testdata/subdir/main.css
vendored
Normal file
39
v2/internal/frontend/assetserver/testdata/subdir/main.css
vendored
Normal file
File diff suppressed because one or more lines are too long
20
v2/internal/frontend/assetserver/testdata/subdir/main.js
vendored
Normal file
20
v2/internal/frontend/assetserver/testdata/subdir/main.js
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
import {ready} from '@wails/runtime';
|
||||
|
||||
ready(() => {
|
||||
// Get input + focus
|
||||
let nameElement = document.getElementById("name");
|
||||
nameElement.focus();
|
||||
|
||||
// Setup the greet function
|
||||
window.greet = function () {
|
||||
|
||||
// Get name
|
||||
let name = nameElement.value;
|
||||
|
||||
// Call App.Greet(name)
|
||||
window.backend.main.App.Greet(name).then((result) => {
|
||||
// Update result with data back from App.Greet()
|
||||
document.getElementById("result").innerText = result;
|
||||
});
|
||||
};
|
||||
});
|
6
v2/internal/frontend/assetserver/testdata/testdata.go
vendored
Normal file
6
v2/internal/frontend/assetserver/testdata/testdata.go
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
package testdata
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed index.html main.css main.js
|
||||
var TopLevelFS embed.FS
|
5
v2/internal/frontend/dispatcher.go
Normal file
5
v2/internal/frontend/dispatcher.go
Normal file
@ -0,0 +1,5 @@
|
||||
package frontend
|
||||
|
||||
type Dispatcher interface {
|
||||
ProcessMessage(message string) error
|
||||
}
|
45
v2/internal/frontend/runtime/desktop/ipc.js
Normal file
45
v2/internal/frontend/runtime/desktop/ipc.js
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* 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) {
|
||||
|
||||
// Call Platform specific invoke method
|
||||
if (PLATFORM === "windows") {
|
||||
window.chrome.webview.postMessage(message);
|
||||
} else if (PLATFORM === "darwin") {
|
||||
window.blah();
|
||||
} else {
|
||||
console.error("Unsupported Platform");
|
||||
}
|
||||
|
||||
// Also send to listeners
|
||||
if (listeners.length > 0) {
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
listeners[i](message);
|
||||
}
|
||||
}
|
||||
}
|
115
v2/internal/frontend/runtime/desktop/log.js
Normal file
115
v2/internal/frontend/runtime/desktop/log.js
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
import {SendMessage} from './ipc';
|
||||
|
||||
/**
|
||||
* Sends a log message to the backend with the given level + message
|
||||
*
|
||||
* @param {string} level
|
||||
* @param {string} message
|
||||
*/
|
||||
function sendLogMessage(level, message) {
|
||||
|
||||
// Log Message format:
|
||||
// l[type][message]
|
||||
SendMessage('L' + level + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given trace message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Trace(message) {
|
||||
sendLogMessage('T', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Print(message) {
|
||||
sendLogMessage('P', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given debug message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Debug(message) {
|
||||
sendLogMessage('D', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given info message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Info(message) {
|
||||
sendLogMessage('I', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given warning message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Warning(message) {
|
||||
sendLogMessage('W', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given error message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Error(message) {
|
||||
sendLogMessage('E', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given fatal message with the backend
|
||||
*
|
||||
* @export
|
||||
* @param {string} message
|
||||
*/
|
||||
export function Fatal(message) {
|
||||
sendLogMessage('F', message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Log level to the given log level
|
||||
*
|
||||
* @export
|
||||
* @param {number} loglevel
|
||||
*/
|
||||
export function SetLogLevel(loglevel) {
|
||||
sendLogMessage('S', loglevel);
|
||||
}
|
||||
|
||||
// Log levels
|
||||
export const Level = {
|
||||
TRACE: 1,
|
||||
DEBUG: 2,
|
||||
INFO: 3,
|
||||
WARNING: 4,
|
||||
ERROR: 5,
|
||||
};
|
6
v2/internal/frontend/runtime/runtime_windows.go
Normal file
6
v2/internal/frontend/runtime/runtime_windows.go
Normal file
@ -0,0 +1,6 @@
|
||||
package runtime
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed runtime_windows.js
|
||||
var RuntimeJS string
|
@ -2,21 +2,32 @@ package windows
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/jchv/go-webview2/pkg/edge"
|
||||
"github.com/tadvi/winc"
|
||||
"github.com/tadvi/winc/w32"
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"log"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Frontend struct {
|
||||
frontendOptions *options.App
|
||||
logger *logger.Logger
|
||||
chromium *edge.Chromium
|
||||
|
||||
// Assets
|
||||
assets *assetserver.AssetServer
|
||||
|
||||
// main window handle
|
||||
mainWindow *Window
|
||||
minWidth, minHeight, maxWidth, maxHeight int
|
||||
bindings *binding.Bindings
|
||||
dispatcher frontend.Dispatcher
|
||||
}
|
||||
|
||||
func (f *Frontend) Run() error {
|
||||
@ -30,6 +41,12 @@ func (f *Frontend) Run() error {
|
||||
mainWindow.Show()
|
||||
}
|
||||
|
||||
f.setupChromium()
|
||||
|
||||
mainWindow.OnSize().Bind(func(arg *winc.Event) {
|
||||
f.chromium.Resize()
|
||||
})
|
||||
|
||||
mainWindow.OnClose().Bind(func(arg *winc.Event) {
|
||||
if f.frontendOptions.HideWindowOnClose {
|
||||
f.WindowHide()
|
||||
@ -131,11 +148,77 @@ func (f *Frontend) Quit() {
|
||||
winc.Exit()
|
||||
}
|
||||
|
||||
func NewFrontend(appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings) *Frontend {
|
||||
func (f *Frontend) setupChromium() {
|
||||
chromium := edge.NewChromium()
|
||||
chromium.MessageCallback = f.processMessage
|
||||
chromium.WebResourceRequestedCallback = f.processRequest
|
||||
chromium.Embed(f.mainWindow.Handle())
|
||||
chromium.Resize()
|
||||
chromium.AddWebResourceRequestedFilter("*", edge.COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL)
|
||||
chromium.Navigate("file://index.html")
|
||||
f.chromium = chromium
|
||||
}
|
||||
|
||||
return &Frontend{
|
||||
func (f *Frontend) processRequest(sender *edge.ICoreWebView2, args *edge.ICoreWebView2WebResourceRequestedEventArgs) uintptr {
|
||||
// Get the request
|
||||
requestObject, _ := args.GetRequest()
|
||||
uri, _ := requestObject.GetURI()
|
||||
|
||||
// Translate URI
|
||||
uri = strings.TrimPrefix(uri, "file://index.html")
|
||||
if !strings.HasPrefix(uri, "/") {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Load file from asset store
|
||||
content, mimeType, err := f.assets.Load(uri)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Create stream for response
|
||||
stream, err := w32.SHCreateMemStream(content)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
env := f.chromium.Environment()
|
||||
var response *edge.ICoreWebView2WebResourceResponse
|
||||
err = env.CreateWebResourceResponse(stream, 200, "OK", "Content-Type: "+mimeType, &response)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
// Send response back
|
||||
err = args.PutResponse(response)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (f *Frontend) processMessage(message string) {
|
||||
err := f.dispatcher.ProcessMessage(message)
|
||||
if err != nil {
|
||||
// TODO: Work out what this means
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func NewFrontend(appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
|
||||
|
||||
result := &Frontend{
|
||||
frontendOptions: appoptions,
|
||||
logger: myLogger,
|
||||
bindings: appBindings,
|
||||
dispatcher: dispatcher,
|
||||
}
|
||||
|
||||
if appoptions.Windows.Assets != nil {
|
||||
assets, err := assetserver.NewAssetServer(*appoptions.Windows.Assets)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
result.assets = assets
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
@ -19,31 +19,31 @@ func (l *DefaultLogger) Print(message string) {
|
||||
|
||||
// Trace level logging. Works like Sprintf.
|
||||
func (l *DefaultLogger) Trace(message string) {
|
||||
println("TRACE | " + message)
|
||||
println("TRA | " + message)
|
||||
}
|
||||
|
||||
// Debug level logging. Works like Sprintf.
|
||||
func (l *DefaultLogger) Debug(message string) {
|
||||
println("DEBUG | " + message)
|
||||
println("DEB | " + message)
|
||||
}
|
||||
|
||||
// Info level logging. Works like Sprintf.
|
||||
func (l *DefaultLogger) Info(message string) {
|
||||
println("INFO | " + message)
|
||||
println("INF | " + message)
|
||||
}
|
||||
|
||||
// Warning level logging. Works like Sprintf.
|
||||
func (l *DefaultLogger) Warning(message string) {
|
||||
println("WARN | " + message)
|
||||
println("WAR | " + message)
|
||||
}
|
||||
|
||||
// Error level logging. Works like Sprintf.
|
||||
func (l *DefaultLogger) Error(message string) {
|
||||
println("ERROR | " + message)
|
||||
println("ERR | " + message)
|
||||
}
|
||||
|
||||
// Fatal level logging. Works like Sprintf.
|
||||
func (l *DefaultLogger) Fatal(message string) {
|
||||
println("FATAL | " + message)
|
||||
println("FAT | " + message)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package windows
|
||||
|
||||
import "github.com/wailsapp/wails/v2/pkg/menu"
|
||||
import (
|
||||
"embed"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
)
|
||||
|
||||
// Options are options specific to Windows
|
||||
type Options struct {
|
||||
@ -8,4 +11,5 @@ type Options struct {
|
||||
WindowBackgroundIsTranslucent bool
|
||||
DisableWindowIcon bool
|
||||
Menu *menu.Menu
|
||||
Assets *embed.FS
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user