Skip to content

Commit

Permalink
Merge branch 'wailsapp:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
chenxi2015 committed Apr 25, 2023
2 parents c85c244 + 0bf4109 commit 363abc3
Show file tree
Hide file tree
Showing 100 changed files with 877 additions and 412 deletions.
44 changes: 34 additions & 10 deletions v2/cmd/wails/internal/dev/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/wailsapp/wails/v2/cmd/wails/flags"
"github.com/wailsapp/wails/v2/cmd/wails/internal/gomod"
"github.com/wailsapp/wails/v2/cmd/wails/internal/logutils"
"golang.org/x/mod/semver"

"github.com/wailsapp/wails/v2/pkg/commands/buildtags"

Expand All @@ -36,6 +37,10 @@ import (
"github.com/wailsapp/wails/v2/pkg/commands/build"
)

const (
viteMinVersion = "v3.0.0"
)

func sliceToMap(input []string) map[string]struct{} {
result := map[string]struct{}{}
for _, value := range input {
Expand Down Expand Up @@ -88,10 +93,11 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
buildOptions.IgnoreApplication = false
}

legacyUseDevServerInsteadofCustomScheme := false
// frontend:dev:watcher command.
frontendDevAutoDiscovery := projectConfig.IsFrontendDevServerURLAutoDiscovery()
if command := projectConfig.DevWatcherCommand; command != "" {
closer, devServerURL, err := runFrontendDevWatcherCommand(projectConfig.GetFrontendDir(), command, frontendDevAutoDiscovery)
closer, devServerURL, devServerViteVersion, err := runFrontendDevWatcherCommand(projectConfig.GetFrontendDir(), command, frontendDevAutoDiscovery)
if err != nil {
return err
}
Expand All @@ -100,14 +106,20 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
f.FrontendDevServerURL = devServerURL
}
defer closer()

if devServerViteVersion != "" && semver.Compare(devServerViteVersion, viteMinVersion) < 0 {
logutils.LogRed("Please upgrade your Vite Server to at least '%s' future Wails versions will require at least Vite '%s'", viteMinVersion, viteMinVersion)
time.Sleep(3 * time.Second)
legacyUseDevServerInsteadofCustomScheme = true
}
} else if frontendDevAutoDiscovery {
return fmt.Errorf("unable to auto discover frontend:dev:serverUrl without a frontend:dev:watcher command, please either set frontend:dev:watcher or remove the auto discovery from frontend:dev:serverUrl")
}

// Do initial build but only for the application.
logger.Println("Building application for development...")
buildOptions.IgnoreFrontend = true
debugBinaryProcess, appBinary, err := restartApp(buildOptions, nil, f, exitCodeChannel)
debugBinaryProcess, appBinary, err := restartApp(buildOptions, nil, f, exitCodeChannel, legacyUseDevServerInsteadofCustomScheme)
buildOptions.IgnoreFrontend = ignoreFrontend || f.FrontendDevServerURL != ""
if err != nil {
return err
Expand Down Expand Up @@ -153,7 +165,7 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
}()

// Watch for changes and trigger restartApp()
debugBinaryProcess = doWatcherLoop(buildOptions, debugBinaryProcess, f, watcher, exitCodeChannel, quitChannel, f.DevServerURL())
debugBinaryProcess = doWatcherLoop(buildOptions, debugBinaryProcess, f, watcher, exitCodeChannel, quitChannel, f.DevServerURL(), legacyUseDevServerInsteadofCustomScheme)

// Kill the current program if running and remove dev binary
if err := killProcessAndCleanupBinary(debugBinaryProcess, appBinary); err != nil {
Expand Down Expand Up @@ -202,7 +214,7 @@ func runCommand(dir string, exitOnError bool, command string, args ...string) er
}

// runFrontendDevWatcherCommand will run the `frontend:dev:watcher` command if it was given, ex- `npm run dev`
func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, discoverViteServerURL bool) (func(), string, error) {
func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, discoverViteServerURL bool) (func(), string, string, error) {
ctx, cancel := context.WithCancel(context.Background())
scanner := NewStdoutScanner()
cmdSlice := strings.Split(devCommand, " ")
Expand All @@ -214,7 +226,7 @@ func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, d

if err := cmd.Start(); err != nil {
cancel()
return nil, "", fmt.Errorf("unable to start frontend DevWatcher: %w", err)
return nil, "", "", fmt.Errorf("unable to start frontend DevWatcher: %w", err)
}

var viteServerURL string
Expand All @@ -224,10 +236,19 @@ func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, d
viteServerURL = serverURL
case <-time.After(time.Second * 10):
cancel()
return nil, "", errors.New("failed to find Vite server URL")
return nil, "", "", errors.New("failed to find Vite server URL")
}
}

viteVersion := ""
select {
case version := <-scanner.ViteServerVersionC:
viteVersion = version

case <-time.After(time.Second * 5):
// That's fine, then most probably it was not vite that was running
}

logutils.LogGreen("Running frontend DevWatcher command: '%s'", devCommand)
var wg sync.WaitGroup
wg.Add(1)
Expand Down Expand Up @@ -255,11 +276,11 @@ func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, d
}
cancel()
wg.Wait()
}, viteServerURL, nil
}, viteServerURL, viteVersion, nil
}

// restartApp does the actual rebuilding of the application when files change
func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process, f *flags.Dev, exitCodeChannel chan int) (*process.Process, string, error) {
func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process, f *flags.Dev, exitCodeChannel chan int, legacyUseDevServerInsteadofCustomScheme bool) (*process.Process, string, error) {

appBinary, err := build.Build(buildOptions)
println()
Expand Down Expand Up @@ -297,6 +318,9 @@ func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process
os.Setenv("assetdir", f.AssetDir)
os.Setenv("devserver", f.DevServer)
os.Setenv("frontenddevserverurl", f.FrontendDevServerURL)
if legacyUseDevServerInsteadofCustomScheme {
os.Setenv("legacyusedevsererinsteadofcustomscheme", "true")
}

// Start up new binary with correct args
newProcess := process.NewProcess(appBinary, args...)
Expand All @@ -316,7 +340,7 @@ func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process
}

// doWatcherLoop is the main watch loop that runs while dev is active
func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Process, f *flags.Dev, watcher *fsnotify.Watcher, exitCodeChannel chan int, quitChannel chan os.Signal, devServerURL *url.URL) *process.Process {
func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Process, f *flags.Dev, watcher *fsnotify.Watcher, exitCodeChannel chan int, quitChannel chan os.Signal, devServerURL *url.URL, legacyUseDevServerInsteadofCustomScheme bool) *process.Process {
// Main Loop
var extensionsThatTriggerARebuild = sliceToMap(strings.Split(f.Extensions, ","))
var dirsThatTriggerAReload []string
Expand Down Expand Up @@ -422,7 +446,7 @@ func doWatcherLoop(buildOptions *build.Options, debugBinaryProcess *process.Proc
rebuild = false
logutils.LogGreen("[Rebuild triggered] files updated")
// Try and build the app
newBinaryProcess, _, err := restartApp(buildOptions, debugBinaryProcess, f, exitCodeChannel)
newBinaryProcess, _, err := restartApp(buildOptions, debugBinaryProcess, f, exitCodeChannel, legacyUseDevServerInsteadofCustomScheme)
if err != nil {
logutils.LogRed("Error during build: %s", err.Error())
continue
Expand Down
39 changes: 37 additions & 2 deletions v2/cmd/wails/internal/dev/stdout_scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,47 @@ package dev

import (
"bufio"
"fmt"
"net/url"
"os"
"strings"

"github.com/acarl005/stripansi"
"github.com/wailsapp/wails/v2/cmd/wails/internal/logutils"
"golang.org/x/mod/semver"
)

// stdoutScanner acts as a stdout target that will scan the incoming
// data to find out the vite server url
type stdoutScanner struct {
ViteServerURLChan chan string
ViteServerURLChan chan string
ViteServerVersionC chan string
versionDetected bool
}

// NewStdoutScanner creates a new stdoutScanner
func NewStdoutScanner() *stdoutScanner {
return &stdoutScanner{
ViteServerURLChan: make(chan string, 2),
ViteServerURLChan: make(chan string, 2),
ViteServerVersionC: make(chan string, 2),
}
}

// Write bytes to the scanner. Will copy the bytes to stdout
func (s *stdoutScanner) Write(data []byte) (n int, err error) {
input := stripansi.Strip(string(data))
if !s.versionDetected {
v, err := detectViteVersion(input)
if v != "" || err != nil {
if err != nil {
logutils.LogRed("ViteStdoutScanner: %s", err)
v = "v0.0.0"
}
s.ViteServerVersionC <- v
s.versionDetected = true
}
}

match := strings.Index(input, "Local:")
if match != -1 {
sc := bufio.NewScanner(strings.NewReader(input))
Expand All @@ -47,3 +64,21 @@ func (s *stdoutScanner) Write(data []byte) (n int, err error) {
}
return os.Stdout.Write(data)
}

func detectViteVersion(line string) (string, error) {
s := strings.Split(strings.TrimSpace(line), " ")
if strings.ToLower(s[0]) != "vite" {
return "", nil
}

if len(line) < 2 {
return "", fmt.Errorf("unable to parse vite version")
}

v := s[1]
if !semver.IsValid(v) {
return "", fmt.Errorf("%s is not a valid vite version string", v)
}

return v, nil
}
2 changes: 1 addition & 1 deletion v2/examples/customlayout/myfrontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"preview": "vite preview"
},
"devDependencies": {
"vite": "^2.9.9"
"vite": "^3.0.7"
}
}
49 changes: 44 additions & 5 deletions v2/internal/app/app_dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import (
"flag"
"fmt"
iofs "io/fs"
"net"
"net/url"
"os"
"path/filepath"
"time"

"github.com/wailsapp/wails/v2/pkg/assetserver"

Expand Down Expand Up @@ -104,17 +106,35 @@ func CreateApp(appoptions *options.App) (*App, error) {
}

if frontendDevServerURL != "" {
if devServer == "" {
return nil, fmt.Errorf("Unable to use FrontendDevServerUrl without a DevServer address")
if os.Getenv("legacyusedevsererinsteadofcustomscheme") != "" {
startURL, err := url.Parse("http://" + devServer)
if err != nil {
return nil, err
}

ctx = context.WithValue(ctx, "starturl", startURL)
}

startURL, err := url.Parse("http://" + devServer)
ctx = context.WithValue(ctx, "frontenddevserverurl", frontendDevServerURL)

externalURL, err := url.Parse(frontendDevServerURL)
if err != nil {
return nil, err
}

ctx = context.WithValue(ctx, "starturl", startURL)
ctx = context.WithValue(ctx, "frontenddevserverurl", frontendDevServerURL)
if externalURL.Host == "" {
return nil, fmt.Errorf("Invalid frontend:dev:serverUrl missing protocol scheme?")
}

waitCb := func() { myLogger.Debug("Waiting for frontend DevServer '%s' to be ready", externalURL) }
if !checkPortIsOpen(externalURL.Host, time.Minute, waitCb) {
myLogger.Error("Timeout waiting for frontend DevServer")
}

handler := assetserver.NewExternalAssetsHandler(myLogger, assetConfig, externalURL)
assetConfig.Assets = nil
assetConfig.Handler = handler
assetConfig.Middleware = nil

myLogger.Info("Serving assets from frontend DevServer URL: %s", frontendDevServerURL)
} else {
Expand Down Expand Up @@ -246,3 +266,22 @@ func tryInferAssetDirFromFS(assets iofs.FS) (string, error) {

return path, nil
}

func checkPortIsOpen(host string, timeout time.Duration, waitCB func()) (ret bool) {
if timeout == 0 {
timeout = time.Minute
}

deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
conn, _ := net.DialTimeout("tcp", host, 2*time.Second)
if conn != nil {
conn.Close()
return true
}

waitCB()
time.Sleep(1 * time.Second)
}
return false
}
1 change: 1 addition & 0 deletions v2/internal/frontend/desktop/darwin/Role.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ typedef int Role;

static const Role AppMenu = 1;
static const Role EditMenu = 2;
static const Role WindowMenu = 3;

#endif /* Role_h */
25 changes: 22 additions & 3 deletions v2/internal/frontend/desktop/darwin/WailsMenu.m
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,20 @@ - (void) appendRole :(WailsContext*)ctx :(Role)role {
appName = [[NSProcessInfo processInfo] processName];
}
WailsMenu *appMenu = [[[WailsMenu new] initWithNSTitle:appName] autorelease];
id quitTitle = [@"Quit " stringByAppendingString:appName];
NSMenuItem* quitMenuItem = [self newMenuItem:quitTitle :@selector(Quit) :@"q" :NSEventModifierFlagCommand];
quitMenuItem.target = ctx;

if (ctx.aboutTitle != nil) {
[appMenu addItem:[self newMenuItemWithContext :ctx :[@"About " stringByAppendingString:appName] :@selector(About) :nil :0]];
[appMenu addItem:[NSMenuItem separatorItem]];
}

[appMenu addItem:[self newMenuItem:[@"Hide " stringByAppendingString:appName] :@selector(hide:) :@"h" :NSEventModifierFlagCommand]];
[appMenu addItem:[self newMenuItem:@"Hide Others" :@selector(hideOtherApplications:) :@"h" :(NSEventModifierFlagOption | NSEventModifierFlagCommand)]];
[appMenu addItem:[self newMenuItem:@"Show All" :@selector(unhideAllApplications:) :@""]];
[appMenu addItem:[NSMenuItem separatorItem]];

id quitTitle = [@"Quit " stringByAppendingString:appName];
NSMenuItem* quitMenuItem = [self newMenuItem:quitTitle :@selector(Quit) :@"q" :NSEventModifierFlagCommand];
quitMenuItem.target = ctx;
[appMenu addItem:quitMenuItem];
[self appendSubmenu:appMenu];
break;
Expand All @@ -100,6 +108,17 @@ - (void) appendRole :(WailsContext*)ctx :(Role)role {
[editMenu appendSubmenu:speechMenu];
[self appendSubmenu:editMenu];

break;
}
case WindowMenu:
{
WailsMenu *windowMenu = [[[WailsMenu new] initWithNSTitle:@"Window"] autorelease];
[windowMenu addItem:[self newMenuItem:@"Minimize" :@selector(performMiniaturize:) :@"m" :NSEventModifierFlagCommand]];
[windowMenu addItem:[self newMenuItem:@"Zoom" :@selector(performZoom:) :@""]];
[windowMenu addItem:[NSMenuItem separatorItem]];
[windowMenu addItem:[self newMenuItem:@"Full Screen" :@selector(enterFullScreenMode:) :@"f" :(NSEventModifierFlagControl | NSEventModifierFlagCommand)]];
[self appendSubmenu:windowMenu];

break;
}
}
Expand Down
1 change: 0 additions & 1 deletion v2/internal/frontend/desktop/darwin/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ func (f *Frontend) startMessageProcessor() {
func (f *Frontend) startRequestProcessor() {
for request := range requestBuffer {
f.assets.ServeWebViewRequest(request)
request.Release()
}
}
func (f *Frontend) startCallbackProcessor() {
Expand Down
1 change: 0 additions & 1 deletion v2/internal/frontend/desktop/linux/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,6 @@ var requestBuffer = make(chan webview.Request, 100)
func (f *Frontend) startRequestProcessor() {
for request := range requestBuffer {
f.assets.ServeWebViewRequest(request)
request.Release()
}
}

Expand Down
Loading

0 comments on commit 363abc3

Please sign in to comment.