mirror of
https://github.com/wavetermdev/wails.git
synced 2026-08-05 13:53:43 -07:00
[assetserver] Introduce middleware and extract options (#2016)
* [assetserver] Add support for HTTP Middlewares * [dev] Disable frontend DevServer if no Assets has been defined and inform user * [dev] Consistent WebSocket behaviour in dev and prod mode for assets handler and middleware In prod mode we can't support WebSockets so make sure the assets handler and middleware never see WebSockets in dev mode. * [templates] Migrate to new AssetServer option * [docs] Add assetserver.Options to the reference
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||||
)
|
||||
@@ -36,7 +37,9 @@ func main() {
|
||||
StartHidden: false,
|
||||
HideWindowOnClose: false,
|
||||
BackgroundColour: &options.RGBA{R: 255, G: 255, B: 255, A: 255},
|
||||
Assets: assets,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
Menu: nil,
|
||||
Logger: nil,
|
||||
LogLevel: logger.DEBUG,
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||||
)
|
||||
|
||||
@@ -37,7 +38,9 @@ func main() {
|
||||
StartHidden: false,
|
||||
HideWindowOnClose: false,
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
Assets: assets,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
Menu: nil,
|
||||
Logger: nil,
|
||||
LogLevel: logger.DEBUG,
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
@@ -16,10 +17,12 @@ func main() {
|
||||
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "{{.ProjectName}}",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
Assets: assets,
|
||||
Title: "{{.ProjectName}}",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
OnStartup: app.startup,
|
||||
Bind: []interface{}{
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/assetserver"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/devserver"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/dispatcher"
|
||||
@@ -90,6 +91,14 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
||||
}
|
||||
}
|
||||
|
||||
assetConfig := assetserver.BuildAssetServerConfig(appoptions)
|
||||
|
||||
if assetConfig.Assets == nil && frontendDevServerURL != "" {
|
||||
myLogger.Warning("No AssetServer.Assets has been defined but a frontend DevServer, the frontend DevServer will not be used.")
|
||||
frontendDevServerURL = ""
|
||||
assetdir = ""
|
||||
}
|
||||
|
||||
if frontendDevServerURL != "" {
|
||||
if devServer == "" {
|
||||
return nil, fmt.Errorf("Unable to use FrontendDevServerUrl without a DevServer address")
|
||||
@@ -107,7 +116,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
||||
} else {
|
||||
if assetdir == "" {
|
||||
// If no assetdir has been defined, let's try to infer it from the project root and the asset FS.
|
||||
assetdir, err = tryInferAssetDirFromFS(appoptions.Assets)
|
||||
assetdir, err = tryInferAssetDirFromFS(assetConfig.Assets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -121,12 +130,17 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
||||
}
|
||||
|
||||
myLogger.Info("Serving assets from disk: %s", absdir)
|
||||
appoptions.Assets = os.DirFS(absdir)
|
||||
assetConfig.Assets = os.DirFS(absdir)
|
||||
|
||||
ctx = context.WithValue(ctx, "assetdir", assetdir)
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate deprecated options to the new AssetServer option
|
||||
appoptions.Assets = nil
|
||||
appoptions.AssetsHandler = nil
|
||||
appoptions.AssetServer = &assetConfig
|
||||
|
||||
if devServer != "" {
|
||||
ctx = context.WithValue(ctx, "devserver", devServer)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/fs"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
//go:embed defaultindex.html
|
||||
@@ -32,7 +33,13 @@ type assetHandler struct {
|
||||
retryMissingFiles bool
|
||||
}
|
||||
|
||||
func NewAssetHandler(ctx context.Context, vfs iofs.FS, assetsHandler http.Handler) (http.Handler, error) {
|
||||
func NewAssetHandler(ctx context.Context, options assetserver.Options) (http.Handler, error) {
|
||||
var log *logger.Logger
|
||||
if _logger := ctx.Value("logger"); _logger != nil {
|
||||
log = _logger.(*logger.Logger)
|
||||
}
|
||||
|
||||
vfs := options.Assets
|
||||
if vfs != nil {
|
||||
if _, err := vfs.Open("."); err != nil {
|
||||
return nil, err
|
||||
@@ -49,13 +56,14 @@ func NewAssetHandler(ctx context.Context, vfs iofs.FS, assetsHandler http.Handle
|
||||
}
|
||||
}
|
||||
|
||||
result := &assetHandler{
|
||||
var result http.Handler = &assetHandler{
|
||||
fs: vfs,
|
||||
handler: assetsHandler,
|
||||
handler: options.Handler,
|
||||
logger: log,
|
||||
}
|
||||
|
||||
if _logger := ctx.Value("logger"); _logger != nil {
|
||||
result.logger = _logger.(*logger.Logger)
|
||||
if middleware := options.Middleware; middleware != nil {
|
||||
result = middleware(result)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
||||
@@ -4,15 +4,16 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
iofs "io/fs"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -22,6 +23,7 @@ const (
|
||||
|
||||
type AssetServer struct {
|
||||
handler http.Handler
|
||||
wsHandler http.Handler
|
||||
runtimeJS []byte
|
||||
ipcJS func(*http.Request) []byte
|
||||
|
||||
@@ -31,8 +33,12 @@ type AssetServer struct {
|
||||
appendSpinnerToBody bool
|
||||
}
|
||||
|
||||
func NewAssetServer(ctx context.Context, vfs iofs.FS, assetsHandler http.Handler, bindingsJSON string) (*AssetServer, error) {
|
||||
handler, err := NewAssetHandler(ctx, vfs, assetsHandler)
|
||||
func NewAssetServerMainPage(ctx context.Context, bindingsJSON string, options *options.App) (*AssetServer, error) {
|
||||
return NewAssetServer(ctx, bindingsJSON, BuildAssetServerConfig(options))
|
||||
}
|
||||
|
||||
func NewAssetServer(ctx context.Context, bindingsJSON string, options assetserver.Options) (*AssetServer, error) {
|
||||
handler, err := NewAssetHandler(ctx, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -66,17 +72,21 @@ func NewAssetServerWithHandler(ctx context.Context, handler http.Handler, bindin
|
||||
}
|
||||
|
||||
func (d *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
if isWebSocket(req) {
|
||||
// Forward WebSockets to the distinct websocket handler if it exists
|
||||
if wsHandler := d.wsHandler; wsHandler != nil {
|
||||
wsHandler.ServeHTTP(rw, req)
|
||||
} else {
|
||||
rw.WriteHeader(http.StatusNotImplemented)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
header := rw.Header()
|
||||
if d.servingFromDisk {
|
||||
header.Add(HeaderCacheControl, "no-cache")
|
||||
}
|
||||
|
||||
if isWebSocket(req) {
|
||||
// WebSockets can always directly be forwarded to the handler
|
||||
d.handler.ServeHTTP(rw, req)
|
||||
return
|
||||
}
|
||||
|
||||
path := req.URL.Path
|
||||
switch path {
|
||||
case "", "/", "/index.html":
|
||||
|
||||
+5
-3
@@ -12,15 +12,17 @@ import (
|
||||
)
|
||||
|
||||
/*
|
||||
The assetserver for dev serves assets from disk.
|
||||
It injects a websocket based IPC script into `index.html`.
|
||||
The assetserver for the dev mode.
|
||||
Depending on the UserAgent it injects a websocket based IPC script into `index.html` or the default desktop IPC. The
|
||||
default desktop IPC is injected when the webview accesses the devserver.
|
||||
*/
|
||||
func NewBrowserAssetServer(ctx context.Context, handler http.Handler, bindingsJSON string) (*AssetServer, error) {
|
||||
func NewDevAssetServer(ctx context.Context, handler http.Handler, wsHandler http.Handler, bindingsJSON string) (*AssetServer, error) {
|
||||
result, err := NewAssetServerWithHandler(ctx, handler, bindingsJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result.wsHandler = wsHandler
|
||||
result.appendSpinnerToBody = true
|
||||
result.ipcJS = func(req *http.Request) []byte {
|
||||
if strings.Contains(req.UserAgent(), WailsUserAgentValue) {
|
||||
@@ -8,9 +8,26 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
func BuildAssetServerConfig(options *options.App) assetserver.Options {
|
||||
if opts := options.AssetServer; opts != nil {
|
||||
if options.Assets != nil || options.AssetsHandler != nil {
|
||||
panic("It's not possible to use the deprecated Assets and AssetsHandler options and the new AssetServer option at the same time. Please migrate all your Assets options to the AssetServer option.")
|
||||
}
|
||||
|
||||
return *opts
|
||||
}
|
||||
|
||||
return assetserver.Options{
|
||||
Assets: options.Assets,
|
||||
Handler: options.AssetsHandler,
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
HeaderHost = "Host"
|
||||
HeaderContentType = "Content-Type"
|
||||
|
||||
@@ -90,7 +90,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
|
||||
} else {
|
||||
appBindings.DB().UpdateObfuscatedCallMap()
|
||||
}
|
||||
assets, err := assetserver.NewAssetServer(ctx, appoptions.Assets, appoptions.AssetsHandler, bindings)
|
||||
assets, err := assetserver.NewAssetServerMainPage(ctx, bindings, appoptions)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
|
||||
} else {
|
||||
appBindings.DB().UpdateObfuscatedCallMap()
|
||||
}
|
||||
assets, err := assetserver.NewAssetServer(ctx, appoptions.Assets, appoptions.AssetsHandler, bindings)
|
||||
assets, err := assetserver.NewAssetServerMainPage(ctx, bindings, appoptions)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
|
||||
appBindings.DB().UpdateObfuscatedCallMap()
|
||||
}
|
||||
|
||||
assets, err := assetserver.NewAssetServer(ctx, appoptions.Assets, appoptions.AssetsHandler, bindings)
|
||||
assets, err := assetserver.NewAssetServerMainPage(ctx, bindings, appoptions)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -435,9 +435,8 @@ func (f *Frontend) setupChromium() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
if opts := f.frontendOptions.Windows; opts != nil {
|
||||
if opts.ZoomFactor > 0.0 {
|
||||
if opts := f.frontendOptions.Windows; opts != nil {
|
||||
if opts.ZoomFactor > 0.0 {
|
||||
chromium.PutZoomFactor(opts.ZoomFactor)
|
||||
}
|
||||
err = settings.PutIsZoomControlEnabled(opts.IsZoomControlEnabled)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -53,7 +54,10 @@ func (d *DevWebServer) Run(ctx context.Context) error {
|
||||
d.server.GET("/wails/reload", d.handleReload)
|
||||
d.server.GET("/wails/ipc", d.handleIPCWebSocket)
|
||||
|
||||
assetServerConfig := assetserver.BuildAssetServerConfig(d.appoptions)
|
||||
|
||||
var assetHandler http.Handler
|
||||
var wsHandler http.Handler
|
||||
_fronendDevServerURL, _ := ctx.Value("frontenddevserverurl").(string)
|
||||
if _fronendDevServerURL == "" {
|
||||
assetdir, _ := ctx.Value("assetdir").(string)
|
||||
@@ -62,7 +66,7 @@ func (d *DevWebServer) Run(ctx context.Context) error {
|
||||
})
|
||||
|
||||
var err error
|
||||
assetHandler, err = assetserver.NewAssetHandler(ctx, d.appoptions.Assets, d.appoptions.AssetsHandler)
|
||||
assetHandler, err = assetserver.NewAssetHandler(ctx, assetServerConfig)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -81,7 +85,11 @@ func (d *DevWebServer) Run(ctx context.Context) error {
|
||||
d.logger.Error("Timeout waiting for frontend DevServer")
|
||||
}
|
||||
|
||||
assetHandler = newExternalDevServerAssetHandler(d.logger, externalURL, d.appoptions.AssetsHandler)
|
||||
assetHandler = newExternalDevServerAssetHandler(d.logger, externalURL, assetServerConfig)
|
||||
// WebSockets aren't currently supported in prod mode, so a WebSocket connection is the result of the
|
||||
// FrontendDevServer e.g. Vite to support auto reloads.
|
||||
// Therefore we direct WebSockets directly to the FrontendDevServer instead of returning a NotImplementedStatus.
|
||||
wsHandler = httputil.NewSingleHostReverseProxy(externalURL)
|
||||
}
|
||||
|
||||
// Setup internal dev server
|
||||
@@ -90,7 +98,7 @@ func (d *DevWebServer) Run(ctx context.Context) error {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
assetServer, err := assetserver.NewBrowserAssetServer(ctx, assetHandler, bindingsJSON)
|
||||
assetServer, err := assetserver.NewDevAssetServer(ctx, assetHandler, wsHandler, bindingsJSON)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -10,11 +10,21 @@ import (
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
func newExternalDevServerAssetHandler(logger *logger.Logger, url *url.URL, handler http.Handler) http.Handler {
|
||||
func newExternalDevServerAssetHandler(logger *logger.Logger, url *url.URL, options assetserver.Options) http.Handler {
|
||||
handler := newExternalAssetsHandler(logger, url, options.Handler)
|
||||
|
||||
if middleware := options.Middleware; middleware != nil {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
return handler
|
||||
}
|
||||
|
||||
func newExternalAssetsHandler(logger *logger.Logger, url *url.URL, handler http.Handler) http.Handler {
|
||||
errSkipProxy := fmt.Errorf("skip proxying")
|
||||
|
||||
proxy := httputil.NewSingleHostReverseProxy(url)
|
||||
@@ -56,23 +66,18 @@ func newExternalDevServerAssetHandler(logger *logger.Logger, url *url.URL, handl
|
||||
}
|
||||
}
|
||||
|
||||
e := echo.New()
|
||||
e.Any("/*",
|
||||
func(c echo.Context) error {
|
||||
req := c.Request()
|
||||
rw := c.Response()
|
||||
if c.IsWebSocket() || req.Method == http.MethodGet {
|
||||
return http.HandlerFunc(
|
||||
func(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method == http.MethodGet {
|
||||
proxy.ServeHTTP(rw, req)
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
if handler != nil {
|
||||
handler.ServeHTTP(rw, req)
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
return c.NoContent(http.StatusMethodNotAllowed)
|
||||
rw.WriteHeader(http.StatusMethodNotAllowed)
|
||||
})
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
@@ -16,10 +17,12 @@ func main() {
|
||||
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "staticanalysis",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
Assets: assets,
|
||||
Title: "staticanalysis",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
OnStartup: app.startup,
|
||||
Bind: []interface{}{
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package assetserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Middleware defines a HTTP middleware that can be applied to the AssetServer.
|
||||
// The handler passed as next is the next handler in the chain. One can decide to call the next handler
|
||||
// or implement a specialized handling.
|
||||
type Middleware func(next http.Handler) http.Handler
|
||||
|
||||
// ChainMiddleware allows chaining multiple middlewares to one middleware.
|
||||
func ChainMiddleware(middleware ...Middleware) Middleware {
|
||||
return func(h http.Handler) http.Handler {
|
||||
for i := len(middleware) - 1; i >= 0; i-- {
|
||||
h = middleware[i](h)
|
||||
}
|
||||
return h
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package assetserver
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Options defines the configuration of the AssetServer.
|
||||
type Options struct {
|
||||
// Assets defines the static assets to be used. A GET request is first tried to be served from this Assets. If the Assets returns
|
||||
// `os.ErrNotExist` for that file, the request handling will fallback to the Handler and tries to serve the GET
|
||||
// request from it.
|
||||
//
|
||||
// If set to nil, all GET requests will be forwarded to Handler.
|
||||
Assets fs.FS
|
||||
|
||||
// Handler will be called for every GET request that can't be served from Assets, due to `os.ErrNotExist`. Furthermore all
|
||||
// non GET requests will always be served from this Handler.
|
||||
//
|
||||
// If not defined, the result is the following in cases where the Handler would have been called:
|
||||
// GET request: `http.StatusNotFound`
|
||||
// Other request: `http.StatusMethodNotAllowed`
|
||||
Handler http.Handler
|
||||
|
||||
// Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default
|
||||
// request handler dynamically, e.g. implement specialized Routing etc.
|
||||
// The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default
|
||||
// handler used by the AssetServer as an argument.
|
||||
//
|
||||
// If not defined, the default AssetServer request chain is executed.
|
||||
//
|
||||
// Multiple Middlewares can be chained together with:
|
||||
// ChainMiddleware(middleware ...Middleware) Middleware
|
||||
Middleware Middleware
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"runtime"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/linux"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||||
@@ -47,9 +48,13 @@ type App struct {
|
||||
AlwaysOnTop bool
|
||||
// BackgroundColour is the background colour of the window
|
||||
// You can use the options.NewRGB and options.NewRGBA functions to create a new colour
|
||||
BackgroundColour *RGBA
|
||||
Assets fs.FS
|
||||
AssetsHandler http.Handler
|
||||
BackgroundColour *RGBA
|
||||
// Deprecated: Use AssetServer.Assets instead.
|
||||
Assets fs.FS
|
||||
// Deprecated: Use AssetServer.Handler instead.
|
||||
AssetsHandler http.Handler
|
||||
// AssetServer configures the Assets for the application
|
||||
AssetServer *assetserver.Options
|
||||
Menu *menu.Menu
|
||||
Logger logger.Logger `json:"-"`
|
||||
LogLevel logger.LogLevel
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
//go:embed frontend/dist
|
||||
@@ -16,10 +17,12 @@ app := NewApp()
|
||||
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "{{.ProjectName}}",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
Assets: assets,
|
||||
Title: "{{.ProjectName}}",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
OnStartup: app.startup,
|
||||
Bind: []interface{}{
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||||
)
|
||||
|
||||
@@ -37,7 +38,9 @@ Frameless: false,
|
||||
StartHidden: false,
|
||||
HideWindowOnClose: false,
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
Assets: assets,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
Menu: nil,
|
||||
Logger: nil,
|
||||
LogLevel: logger.DEBUG,
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
@@ -16,10 +17,12 @@ func main() {
|
||||
|
||||
// Create application with options
|
||||
err := wails.Run(&options.App{
|
||||
Title: "{{.ProjectName}}",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
Assets: assets,
|
||||
Title: "{{.ProjectName}}",
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
AssetServer: &assetserver.Options{
|
||||
Assets: assets,
|
||||
},
|
||||
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
|
||||
OnStartup: app.startup,
|
||||
Bind: []interface{}{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user