5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 00:53:16 +08:00

Refactor app (#1909)

* Application refactor

* [windows] refactor out main loop. Create new application struct. Refactor assethandler/assetserver signatures.

* Refactor darwin app

* Refactor app for linux

* Update v2/internal/frontend/assetserver/assethandler.go

Co-authored-by: stffabi <stffabi@users.noreply.github.com>

* Update v2/internal/frontend/assetserver/assethandler.go

Co-authored-by: stffabi <stffabi@users.noreply.github.com>

* Update v2/internal/frontend/assetserver/assetserver.go

Co-authored-by: stffabi <stffabi@users.noreply.github.com>

* Update v2/internal/frontend/assetserver/assetserver.go

Co-authored-by: stffabi <stffabi@users.noreply.github.com>

Co-authored-by: stffabi <stffabi@users.noreply.github.com>
This commit is contained in:
Lea Anthony 2022-09-29 18:43:35 +10:00 committed by GitHub
parent e22cfc18c9
commit b2069c871d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 205 additions and 198 deletions

View File

@ -1,6 +1,6 @@
module github.com/wailsapp/wails/v2
go 1.19
go 1.18
require (
github.com/Masterminds/semver v1.5.0

41
v2/internal/app/app.go Normal file
View File

@ -0,0 +1,41 @@
package app
import (
"context"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/menumanager"
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/options"
)
// App defines a Wails application structure
type App struct {
frontend frontend.Frontend
logger *logger.Logger
options *options.App
menuManager *menumanager.Manager
// Indicates if the app is in debug mode
debug bool
// OnStartup/OnShutdown
startupCallback func(ctx context.Context)
shutdownCallback func(ctx context.Context)
ctx context.Context
}
// Shutdown the application
func (a *App) Shutdown() {
if a.frontend != nil {
a.frontend.Quit()
}
}
// SetApplicationMenu sets the application menu
func (a *App) SetApplicationMenu(menu *menu.Menu) {
if a.frontend != nil {
a.frontend.MenuSetApplicationMenu(menu)
}
}

View File

@ -1,5 +1,4 @@
//go:build bindings
// +build bindings
package app
@ -16,23 +15,17 @@ import (
"github.com/wailsapp/wails/v2/pkg/options"
)
// App defines a Wails application structure
type App struct {
logger *logger.Logger
appoptions *options.App
}
func (a *App) Run() error {
// Create binding exemptions - Ugly hack. There must be a better way
bindingExemptions := []interface{}{
a.appoptions.OnStartup,
a.appoptions.OnShutdown,
a.appoptions.OnDomReady,
a.appoptions.OnBeforeClose,
a.options.OnStartup,
a.options.OnShutdown,
a.options.OnDomReady,
a.options.OnBeforeClose,
}
appBindings := binding.NewBindings(a.logger, a.appoptions.Bind, bindingExemptions, IsObfuscated())
appBindings := binding.NewBindings(a.logger, a.options.Bind, bindingExemptions, IsObfuscated())
err := generateBindings(appBindings)
if err != nil {
@ -41,8 +34,6 @@ func (a *App) Run() error {
return nil
}
func (a *App) Shutdown() {}
// CreateApp creates the app!
func CreateApp(appoptions *options.App) (*App, error) {
// Set up logger
@ -50,8 +41,8 @@ func CreateApp(appoptions *options.App) (*App, error) {
myLogger.SetLogLevel(appoptions.LogLevel)
result := &App{
logger: myLogger,
appoptions: appoptions,
logger: myLogger,
options: appoptions,
}
return result, nil

View File

@ -1,16 +0,0 @@
//go:build darwin && !bindings
// +build darwin,!bindings
package app
import (
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
)
func PreflightChecks(options *options.App, logger *logger.Logger) error {
_ = options
return nil
}

View File

@ -1,5 +1,4 @@
//go:build debug
// +build debug
package app

View File

@ -1,5 +1,4 @@
//go:build !debug
// +build !debug
package app

View File

@ -1,24 +0,0 @@
//go:build !dev && !production && !bindings && darwin
// +build !dev,!production,!bindings,darwin
package app
import (
"fmt"
"github.com/wailsapp/wails/v2/pkg/options"
)
// App defines a Wails application structure
type App struct{}
func (a *App) Run() error {
return nil
}
func (a *App) Shutdown() {}
// CreateApp creates the app!
func CreateApp(_ *options.App) (*App, error) {
return nil, fmt.Errorf(`Wails applications will not build without the correct build tags.`)
}

View File

@ -1,5 +1,4 @@
//go:build !dev && !production && !bindings && linux
// +build !dev,!production,!bindings,linux
//go:build !dev && !production && !bindings && (linux || darwin)
package app
@ -9,15 +8,10 @@ import (
"github.com/wailsapp/wails/v2/pkg/options"
)
// App defines a Wails application structure
type App struct{}
func (a *App) Run() error {
return nil
}
func (a *App) Shutdown() {}
// CreateApp creates the app!
func CreateApp(_ *options.App) (*App, error) {
return nil, fmt.Errorf(`Wails applications will not build without the correct build tags.`)

View File

@ -1,5 +1,4 @@
//go:build !dev && !production && !bindings && windows
// +build !dev,!production,!bindings,windows
package app
@ -10,15 +9,10 @@ import (
"github.com/wailsapp/wails/v2/pkg/options"
)
// App defines a Wails application structure
type App struct{}
func (a *App) Run() error {
return nil
}
func (a *App) Shutdown() {}
// CreateApp creates the app!
func CreateApp(_ *options.App) (*App, error) {
result := w32.MessageBox(0,

View File

@ -1,5 +1,4 @@
//go:build dev
// +build dev
package app
@ -14,7 +13,6 @@ import (
"path/filepath"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/desktop"
"github.com/wailsapp/wails/v2/internal/frontend/devserver"
"github.com/wailsapp/wails/v2/internal/frontend/dispatcher"
@ -26,29 +24,10 @@ import (
"github.com/wailsapp/wails/v2/pkg/options"
)
// App defines a Wails application structure
type App struct {
frontend frontend.Frontend
logger *logger.Logger
options *options.App
menuManager *menumanager.Manager
// Indicates if the app is in debug mode
debug bool
// OnStartup/OnShutdown
startupCallback func(ctx context.Context)
shutdownCallback func(ctx context.Context)
ctx context.Context
}
func (a *App) Shutdown() {
a.frontend.Quit()
}
func (a *App) Run() error {
err := a.frontend.Run(a.ctx)
a.frontend.RunMainLoop()
a.frontend.WindowClose()
if a.shutdownCallback != nil {
a.shutdownCallback(a.ctx)
}

View File

@ -1,16 +0,0 @@
//go:build linux && !bindings
// +build linux,!bindings
package app
import (
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
)
func PreflightChecks(options *options.App, logger *logger.Logger) error {
_ = options
return nil
}

View File

@ -0,0 +1,12 @@
//go:build (linux || darwin) && !bindings
package app
import (
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
)
func PreflightChecks(_ *options.App, _ *logger.Logger) error {
return nil
}

View File

@ -1,5 +1,4 @@
//go:build windows && !bindings
// +build windows,!bindings
package app

View File

@ -6,7 +6,6 @@ import (
"context"
"github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/desktop"
"github.com/wailsapp/wails/v2/internal/frontend/dispatcher"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
@ -15,29 +14,10 @@ import (
"github.com/wailsapp/wails/v2/pkg/options"
)
// App defines a Wails application structure
type App struct {
frontend frontend.Frontend
logger *logger.Logger
options *options.App
menuManager *menumanager.Manager
// Indicates if the app is in debug mode
debug bool
// OnStartup/OnShutdown
startupCallback func(ctx context.Context)
shutdownCallback func(ctx context.Context)
ctx context.Context
}
func (a *App) Shutdown() {
a.frontend.Quit()
}
func (a *App) Run() error {
err := a.frontend.Run(a.ctx)
a.frontend.RunMainLoop()
a.frontend.WindowClose()
if a.shutdownCallback != nil {
a.shutdownCallback(a.ctx)
}

View File

@ -14,7 +14,6 @@ import (
"github.com/wailsapp/wails/v2/internal/fs"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
)
//go:embed defaultindex.html
@ -33,8 +32,7 @@ type assetHandler struct {
retryMissingFiles bool
}
func NewAssetHandler(ctx context.Context, options *options.App) (http.Handler, error) {
vfs := options.Assets
func NewAssetHandler(ctx context.Context, vfs iofs.FS, assetsHandler http.Handler) (http.Handler, error) {
if vfs != nil {
if _, err := vfs.Open("."); err != nil {
return nil, err
@ -53,7 +51,7 @@ func NewAssetHandler(ctx context.Context, options *options.App) (http.Handler, e
result := &assetHandler{
fs: vfs,
handler: options.AssetsHandler,
handler: assetsHandler,
}
if _logger := ctx.Value("logger"); _logger != nil {

View File

@ -4,13 +4,13 @@ import (
"bytes"
"context"
"fmt"
iofs "io/fs"
"net/http"
"net/http/httptest"
"strconv"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
"golang.org/x/net/html"
)
@ -31,8 +31,8 @@ type AssetServer struct {
appendSpinnerToBody bool
}
func NewAssetServer(ctx context.Context, options *options.App, bindingsJSON string) (*AssetServer, error) {
handler, err := NewAssetHandler(ctx, options)
func NewAssetServer(ctx context.Context, vfs iofs.FS, assetsHandler http.Handler, bindingsJSON string) (*AssetServer, error) {
handler, err := NewAssetHandler(ctx, vfs, assetsHandler)
if err != nil {
return nil, err
}

View File

@ -67,6 +67,8 @@ void SetAbout(void *inctx, const char* title, const char* description, void* ima
void* AppendMenuItem(void* inctx, void* nsmenu, const char* label, const char* shortcutKey, int modifiers, int disabled, int checked, int menuItemID);
void AppendSeparator(void* inMenu);
void UpdateMenuItem(void* nsmenuitem, int checked);
void RunMainLoop(void);
void ReleaseContext(void *inctx);
NSString* safeInit(const char* input);

View File

@ -381,6 +381,14 @@ void Run(void *inctx, const char* url) {
[_url release];
[app setMainMenu:ctx.applicationMenu];
}
void RunMainLoop(void) {
NSApplication *app = [NSApplication sharedApplication];
[app run];
}
void ReleaseContext(void *inctx) {
WailsContext *ctx = (__bridge WailsContext*) inctx;
[ctx release];
}

View File

@ -59,6 +59,14 @@ type Frontend struct {
dispatcher frontend.Dispatcher
}
func (f *Frontend) RunMainLoop() {
C.RunMainLoop()
}
func (f *Frontend) WindowClose() {
C.ReleaseContext(f.mainWindow.context)
}
func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) *Frontend {
result := &Frontend{
frontendOptions: appoptions,
@ -82,7 +90,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
} else {
appBindings.DB().UpdateObfuscatedCallMap()
}
assets, err := assetserver.NewAssetServer(ctx, appoptions, bindings)
assets, err := assetserver.NewAssetServer(ctx, appoptions.Assets, appoptions.AssetsHandler, bindings)
if err != nil {
log.Fatal(err)
}

View File

@ -52,6 +52,14 @@ type Frontend struct {
dispatcher frontend.Dispatcher
}
func (f *Frontend) RunMainLoop() {
C.gtk_main()
}
func (f *Frontend) WindowClose() {
f.mainWindow.Destroy()
}
func init() {
runtime.LockOSThread()
}
@ -85,7 +93,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
} else {
appBindings.DB().UpdateObfuscatedCallMap()
}
assets, err := assetserver.NewAssetServer(ctx, appoptions, bindings)
assets, err := assetserver.NewAssetServer(ctx, appoptions.Assets, appoptions.AssetsHandler, bindings)
if err != nil {
log.Fatal(err)
}

View File

@ -861,8 +861,6 @@ func (w *Window) Run(url string) {
w.Maximise()
}
C.gtk_main()
w.Destroy()
}
func (w *Window) SetKeepAbove(top bool) {

View File

@ -102,7 +102,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
appBindings.DB().UpdateObfuscatedCallMap()
}
assets, err := assetserver.NewAssetServer(ctx, appoptions, bindings)
assets, err := assetserver.NewAssetServer(ctx, appoptions.Assets, appoptions.AssetsHandler, bindings)
if err != nil {
log.Fatal(err)
}
@ -180,11 +180,20 @@ func (f *Frontend) Run(ctx context.Context) error {
f.frontendOptions.OnStartup(f.ctx)
}
}()
mainWindow.Run()
mainWindow.Close()
mainWindow.UpdateTheme()
return nil
}
func (f *Frontend) WindowClose() {
if f.mainWindow != nil {
f.mainWindow.Close()
}
}
func (f *Frontend) RunMainLoop() {
_ = winc.RunMainLoop()
}
func (f *Frontend) WindowCenter() {
runtime.LockOSThread()
defer runtime.UnlockOSThread()

View File

@ -5,7 +5,7 @@ import (
"github.com/wailsapp/wails/v2/pkg/options/windows"
)
func (w *Window) updateTheme() {
func (w *Window) UpdateTheme() {
// Don't redraw theme if nothing has changed
if !w.themeChanged {

View File

@ -99,7 +99,7 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
result.SetMaxSize(appoptions.MaxWidth, appoptions.MaxHeight)
}
result.updateTheme()
result.UpdateTheme()
if appoptions.Windows != nil {
result.OnSuspend = appoptions.Windows.OnSuspend
@ -129,11 +129,6 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
return result
}
func (w *Window) Run() int {
w.updateTheme()
return winc.RunMainLoop()
}
func (w *Window) Fullscreen() {
w.Form.SetMaxSize(0, 0)
w.Form.SetMinSize(0, 0)
@ -190,7 +185,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
settingChanged := w32.UTF16PtrToString((*uint16)(unsafe.Pointer(lparam)))
if settingChanged == "ImmersiveColorSet" {
w.themeChanged = true
w.updateTheme()
w.UpdateTheme()
}
return 0
case w32.WM_NCLBUTTONDOWN:
@ -204,10 +199,10 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
w.themeChanged = true
if int(wparam) == w32.WA_INACTIVE {
w.isActive = false
w.updateTheme()
w.UpdateTheme()
} else {
w.isActive = true
w.updateTheme()
w.UpdateTheme()
//}
}
@ -303,6 +298,6 @@ func (w *Window) SetTheme(theme winoptions.Theme) {
w.theme = theme
w.themeChanged = true
w.Invoke(func() {
w.updateTheme()
w.UpdateTheme()
})
}

View File

@ -10,7 +10,7 @@ import (
// FileFilter defines a filter for dialog boxes
type FileFilter struct {
DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)"
Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png"
Pattern string // semicolon separated list of extensions, EG: "*.jpg;*.png"
}
// OpenDialogOptions contains the options for the OpenDialogOptions runtime method
@ -65,6 +65,7 @@ type MessageDialogOptions struct {
type Frontend interface {
Run(context.Context) error
RunMainLoop()
Hide()
Show()
Quit()
@ -105,6 +106,7 @@ type Frontend interface {
WindowIsMinimised() bool
WindowIsNormal() bool
WindowIsFullscreen() bool
WindowClose()
//Screen
ScreenGetAll() ([]Screen, error)

View File

@ -0,0 +1,75 @@
package application
import (
"github.com/wailsapp/wails/v2/internal/app"
"github.com/wailsapp/wails/v2/internal/signal"
"github.com/wailsapp/wails/v2/pkg/menu"
"github.com/wailsapp/wails/v2/pkg/options"
)
// Application is the main Wails application
type Application struct {
application *app.App
options *options.App
// running flag
running bool
}
// NewWithOptions creates a new Application with the given options
func NewWithOptions(options *options.App) *Application {
if options == nil {
return New()
}
return &Application{
options: options,
}
}
// New creates a new Application with the default options
func New() *Application {
return &Application{
options: &options.App{},
}
}
// SetApplicationMenu sets the application menu
func (a *Application) SetApplicationMenu(appMenu *menu.Menu) {
if a.running {
a.application.SetApplicationMenu(appMenu)
return
}
a.options.Menu = appMenu
}
// Run starts the application
func (a *Application) Run() error {
err := applicationInit()
if err != nil {
return err
}
application, err := app.CreateApp(a.options)
if err != nil {
return err
}
a.application = application
// Control-C handlers
signal.OnShutdown(func() {
a.application.Shutdown()
})
signal.Start()
a.running = true
return a.application.Run()
}
// Quit will shut down the application
func (a *Application) Quit() {
a.application.Shutdown()
}

View File

@ -1,8 +1,8 @@
//go:build !windows
// +build !windows
package wails
package application
func Init() error {
func applicationInit() error {
return nil
}

View File

@ -1,12 +1,13 @@
package wails
//go:build windows
package application
import (
"fmt"
"syscall"
)
// Init is called at the start of the application
func Init() error {
func applicationInit() error {
status, r, err := syscall.NewLazyDLL("user32.dll").NewProc("SetProcessDPIAware").Call()
if status == 0 {
return fmt.Errorf("exit status %d: %v %v", status, r, err)

View File

@ -47,9 +47,7 @@ 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
// RGBA is deprecated. Please use BackgroundColour
RGBA *RGBA
BackgroundColour *RGBA
Assets fs.FS
AssetsHandler http.Handler
Menu *menu.Menu

View File

@ -3,40 +3,13 @@
package wails
import (
"github.com/wailsapp/wails/v2/internal/app"
_ "github.com/wailsapp/wails/v2/internal/goversion" // Add Compile-Time version check for minimum go version
"github.com/wailsapp/wails/v2/internal/signal"
"github.com/wailsapp/wails/v2/pkg/application"
"github.com/wailsapp/wails/v2/pkg/options"
)
// Run creates an application based on the given config and executes it
func Run(options *options.App) error {
if options.RGBA != nil {
println("---- WARNING ----")
println("The `RGBA` option has been deprecated. Please use `BackgroundColour`.")
if options.BackgroundColour == nil {
options.BackgroundColour = options.RGBA
}
}
// Call an Init method manually
err := Init()
if err != nil {
return err
}
mainapp, err := app.CreateApp(options)
if err != nil {
return err
}
signal.OnShutdown(func() {
mainapp.Shutdown()
})
signal.Start()
return mainapp.Run()
mainApp := application.NewWithOptions(options)
return mainApp.Run()
}