Compare commits

..

1 Commits

Author SHA1 Message Date
Lea Anthony 0c2b3fb1cb Update generate-contributors.yml 2023-04-14 19:57:07 +10:00
230 changed files with 872 additions and 13805 deletions
@@ -0,0 +1,40 @@
name: update-contributors-svg
on:
workflow_dispatch: # Can trigger manually
schedule:
- cron: '0 7 * * *' # Schedule on everyday 7:00
jobs:
update-svg:
name: Update contributors SVG
runs-on: ubuntu-latest # You can also try macos-latest
steps:
- uses: actions/checkout@v3
- name: Set node
uses: actions/setup-node@v3
with:
node-version: lts/*
- name: Install pnpm
uses: pnpm/action-setup@v2.2.2
with:
version: 7
- name: Install deps
run: pnpm install
- name: Run SVG generation script
run: pnpx make-github-contributor-svg -t ${{ secrets.GITHUB_TOKEN }} -o vuejs-translations -r docs-zh-cn
- name: Move SVG
run: mv .github-contributors/* website/static/img/
- name: Commit
uses: EndBug/add-and-commit@v4
with:
message: "chore(workflow): update contributors image"
add: "website/static/img/*"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+17
View File
@@ -0,0 +1,17 @@
name: Label Sponsors
on:
pull_request:
types: [opened]
issues:
types: [opened]
jobs:
build:
name: is-sponsor-label
if: github.repository == 'wailsapp/wails'
runs-on: ubuntu-latest
steps:
- uses: JasonEtco/is-sponsor-label-action@v1
with:
label: Sponsor ❤️
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+10 -34
View File
@@ -22,7 +22,6 @@ 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"
@@ -37,10 +36,6 @@ 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 {
@@ -93,11 +88,10 @@ 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, devServerViteVersion, err := runFrontendDevWatcherCommand(projectConfig.GetFrontendDir(), command, frontendDevAutoDiscovery)
closer, devServerURL, err := runFrontendDevWatcherCommand(projectConfig.GetFrontendDir(), command, frontendDevAutoDiscovery)
if err != nil {
return err
}
@@ -106,12 +100,6 @@ 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")
}
@@ -119,7 +107,7 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error {
// 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, legacyUseDevServerInsteadofCustomScheme)
debugBinaryProcess, appBinary, err := restartApp(buildOptions, nil, f, exitCodeChannel)
buildOptions.IgnoreFrontend = ignoreFrontend || f.FrontendDevServerURL != ""
if err != nil {
return err
@@ -165,7 +153,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(), legacyUseDevServerInsteadofCustomScheme)
debugBinaryProcess = doWatcherLoop(buildOptions, debugBinaryProcess, f, watcher, exitCodeChannel, quitChannel, f.DevServerURL())
// Kill the current program if running and remove dev binary
if err := killProcessAndCleanupBinary(debugBinaryProcess, appBinary); err != nil {
@@ -214,7 +202,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, string, error) {
func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, discoverViteServerURL bool) (func(), string, error) {
ctx, cancel := context.WithCancel(context.Background())
scanner := NewStdoutScanner()
cmdSlice := strings.Split(devCommand, " ")
@@ -226,7 +214,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
@@ -236,19 +224,10 @@ 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)
@@ -276,11 +255,11 @@ func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, d
}
cancel()
wg.Wait()
}, viteServerURL, viteVersion, nil
}, viteServerURL, 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, legacyUseDevServerInsteadofCustomScheme bool) (*process.Process, string, error) {
func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process, f *flags.Dev, exitCodeChannel chan int) (*process.Process, string, error) {
appBinary, err := build.Build(buildOptions)
println()
@@ -318,9 +297,6 @@ 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...)
@@ -340,7 +316,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, legacyUseDevServerInsteadofCustomScheme bool) *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) *process.Process {
// Main Loop
var extensionsThatTriggerARebuild = sliceToMap(strings.Split(f.Extensions, ","))
var dirsThatTriggerAReload []string
@@ -446,7 +422,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, legacyUseDevServerInsteadofCustomScheme)
newBinaryProcess, _, err := restartApp(buildOptions, debugBinaryProcess, f, exitCodeChannel)
if err != nil {
logutils.LogRed("Error during build: %s", err.Error())
continue
+2 -37
View File
@@ -2,47 +2,30 @@ 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
ViteServerVersionC chan string
versionDetected bool
ViteServerURLChan chan string
}
// NewStdoutScanner creates a new stdoutScanner
func NewStdoutScanner() *stdoutScanner {
return &stdoutScanner{
ViteServerURLChan: make(chan string, 2),
ViteServerVersionC: make(chan string, 2),
ViteServerURLChan: 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))
@@ -64,21 +47,3 @@ 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
}
@@ -8,6 +8,6 @@
"preview": "vite preview"
},
"devDependencies": {
"vite": "^3.0.7"
"vite": "^2.9.9"
}
}
+5 -44
View File
@@ -8,11 +8,9 @@ import (
"flag"
"fmt"
iofs "io/fs"
"net"
"net/url"
"os"
"path/filepath"
"time"
"github.com/wailsapp/wails/v2/pkg/assetserver"
@@ -106,35 +104,17 @@ func CreateApp(appoptions *options.App) (*App, error) {
}
if frontendDevServerURL != "" {
if os.Getenv("legacyusedevsererinsteadofcustomscheme") != "" {
startURL, err := url.Parse("http://" + devServer)
if err != nil {
return nil, err
}
ctx = context.WithValue(ctx, "starturl", startURL)
if devServer == "" {
return nil, fmt.Errorf("Unable to use FrontendDevServerUrl without a DevServer address")
}
ctx = context.WithValue(ctx, "frontenddevserverurl", frontendDevServerURL)
externalURL, err := url.Parse(frontendDevServerURL)
startURL, err := url.Parse("http://" + devServer)
if err != nil {
return nil, err
}
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
ctx = context.WithValue(ctx, "starturl", startURL)
ctx = context.WithValue(ctx, "frontenddevserverurl", frontendDevServerURL)
myLogger.Info("Serving assets from frontend DevServer URL: %s", frontendDevServerURL)
} else {
@@ -266,22 +246,3 @@ 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
}
@@ -12,6 +12,5 @@ typedef int Role;
static const Role AppMenu = 1;
static const Role EditMenu = 2;
static const Role WindowMenu = 3;
#endif /* Role_h */
@@ -68,20 +68,12 @@
appName = [[NSProcessInfo processInfo] processName];
}
WailsMenu *appMenu = [[[WailsMenu new] initWithNSTitle:appName] autorelease];
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;
if (ctx.aboutTitle != nil) {
[appMenu addItem:[self newMenuItemWithContext :ctx :[@"About " stringByAppendingString:appName] :@selector(About) :nil :0]];
}
[appMenu addItem:quitMenuItem];
[self appendSubmenu:appMenu];
break;
@@ -108,17 +100,6 @@
[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;
}
}
@@ -20,6 +20,7 @@ import (
"html/template"
"log"
"net/url"
"strconv"
"unsafe"
"github.com/wailsapp/wails/v2/pkg/assetserver"
@@ -113,6 +114,7 @@ func (f *Frontend) startMessageProcessor() {
func (f *Frontend) startRequestProcessor() {
for request := range requestBuffer {
f.assets.ServeWebViewRequest(request)
request.Release()
}
}
func (f *Frontend) startCallbackProcessor() {
@@ -335,11 +337,7 @@ func (f *Frontend) processMessage(message string) {
}
func (f *Frontend) Callback(message string) {
escaped, err := json.Marshal(message)
if err != nil {
panic(err)
}
f.ExecJS(`window.wails.Callback(` + string(escaped) + `);`)
f.ExecJS(`window.wails.Callback(` + strconv.Quote(message) + `);`)
}
func (f *Frontend) ExecJS(js string) {
@@ -81,6 +81,7 @@ import (
"net/url"
"os"
"runtime"
"strconv"
"strings"
"text/template"
"unsafe"
@@ -433,11 +434,7 @@ func (f *Frontend) processMessage(message string) {
}
func (f *Frontend) Callback(message string) {
escaped, err := json.Marshal(message)
if err != nil {
panic(err)
}
f.ExecJS(`window.wails.Callback(` + string(escaped) + `);`)
f.ExecJS(`window.wails.Callback(` + strconv.Quote(message) + `);`)
}
func (f *Frontend) startDrag() {
@@ -466,6 +463,7 @@ var requestBuffer = make(chan webview.Request, 100)
func (f *Frontend) startRequestProcessor() {
for request := range requestBuffer {
f.assets.ServeWebViewRequest(request)
request.Release()
}
}
+54 -54
View File
@@ -4,14 +4,13 @@
package windows
import (
"path/filepath"
"strings"
"syscall"
"github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
"github.com/wailsapp/wails/v2/internal/go-common-file-dialog/cfd"
"golang.org/x/sys/windows"
"path/filepath"
"strings"
"syscall"
)
func (f *Frontend) getHandleForDialog() w32.HWND {
@@ -41,20 +40,27 @@ func (f *Frontend) OpenDirectoryDialog(options frontend.OpenDialogOptions) (stri
Role: "PickFolder",
Folder: defaultFolder,
}
result, err := f.showCfdDialog(
func() (cfd.Dialog, error) {
return cfd.NewSelectFolderDialog(config)
}, false)
thisDialog, err := cfd.NewSelectFolderDialog(config)
if err != nil {
return "", err
}
thisDialog.SetParentWindowHandle(f.getHandleForDialog())
defer func(thisDialog cfd.SelectFolderDialog) {
err := thisDialog.Release()
if err != nil {
println("ERROR: Unable to release dialog:", err.Error())
}
}(thisDialog)
result, err := thisDialog.ShowAndGetResult()
if err != nil && err != cfd.ErrorCancelled {
return "", err
}
return result.(string), nil
return result, nil
}
// OpenFileDialog prompts the user to select a file
func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
defaultFolder, err := getDefaultFolder(options.DefaultDirectory)
if err != nil {
return "", err
@@ -66,16 +72,22 @@ func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, e
FileName: options.DefaultFilename,
Title: options.Title,
}
result, err := f.showCfdDialog(
func() (cfd.Dialog, error) {
return cfd.NewOpenFileDialog(config)
}, false)
thisdialog, err := cfd.NewOpenFileDialog(config)
if err != nil {
return "", err
}
thisdialog.SetParentWindowHandle(f.getHandleForDialog())
defer func(thisdialog cfd.OpenFileDialog) {
err := thisdialog.Release()
if err != nil {
println("ERROR: Unable to release dialog:", err.Error())
}
}(thisdialog)
result, err := thisdialog.ShowAndGetResult()
if err != nil && err != cfd.ErrorCancelled {
return "", err
}
return result.(string), nil
return result, nil
}
// OpenMultipleFilesDialog prompts the user to select a file
@@ -93,16 +105,22 @@ func (f *Frontend) OpenMultipleFilesDialog(options frontend.OpenDialogOptions) (
FileName: options.DefaultFilename,
Folder: defaultFolder,
}
result, err := f.showCfdDialog(
func() (cfd.Dialog, error) {
return cfd.NewOpenMultipleFilesDialog(config)
}, true)
thisdialog, err := cfd.NewOpenMultipleFilesDialog(config)
if err != nil {
return nil, err
}
thisdialog.SetParentWindowHandle(f.getHandleForDialog())
defer func(thisdialog cfd.OpenMultipleFilesDialog) {
err := thisdialog.Release()
if err != nil {
println("ERROR: Unable to release dialog:", err.Error())
}
}(thisdialog)
result, err := thisdialog.ShowAndGetResults()
if err != nil && err != cfd.ErrorCancelled {
return nil, err
}
return result.([]string), nil
return result, nil
}
// SaveFileDialog prompts the user to select a file
@@ -113,44 +131,26 @@ func (f *Frontend) SaveFileDialog(options frontend.SaveDialogOptions) (string, e
return "", err
}
config := cfd.DialogConfig{
saveDialog, err := cfd.NewSaveFileDialog(cfd.DialogConfig{
Title: options.Title,
Role: "SaveFile",
FileFilters: convertFilters(options.Filters),
FileName: options.DefaultFilename,
Folder: defaultFolder,
})
if err != nil {
return "", err
}
result, err := f.showCfdDialog(
func() (cfd.Dialog, error) {
return cfd.NewSaveFileDialog(config)
}, false)
saveDialog.SetParentWindowHandle(f.getHandleForDialog())
err = saveDialog.Show()
if err != nil {
return "", err
}
result, err := saveDialog.GetResult()
if err != nil && err != cfd.ErrorCancelled {
return "", err
}
return result.(string), nil
}
func (f *Frontend) showCfdDialog(newDlg func() (cfd.Dialog, error), isMultiSelect bool) (any, error) {
return invokeSync(f.mainWindow, func() (any, error) {
dlg, err := newDlg()
if err != nil {
return nil, err
}
defer func() {
err := dlg.Release()
if err != nil {
println("ERROR: Unable to release dialog:", err.Error())
}
}()
dlg.SetParentWindowHandle(f.getHandleForDialog())
if multi, _ := dlg.(cfd.OpenMultipleFilesDialog); multi != nil && isMultiSelect {
return multi.ShowAndGetResults()
}
return dlg.ShowAndGetResult()
})
return result, nil
}
func calculateMessageDialogFlags(options frontend.MessageDialogOptions) uint32 {
@@ -13,6 +13,7 @@ import (
"net/http/httptest"
"net/url"
"runtime"
"strconv"
"strings"
"sync"
"text/template"
@@ -636,12 +637,8 @@ func (f *Frontend) processMessage(message string) {
}
func (f *Frontend) Callback(message string) {
escaped, err := json.Marshal(message)
if err != nil {
panic(err)
}
f.mainWindow.Invoke(func() {
f.chromium.Eval(`window.wails.Callback(` + string(escaped) + `);`)
f.chromium.Eval(`window.wails.Callback(` + strconv.Quote(message) + `);`)
})
}
@@ -3,7 +3,6 @@
package windows
import (
"sync"
"unsafe"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/go-webview2/pkg/edge"
@@ -324,14 +323,3 @@ func (w *Window) SetTheme(theme winoptions.Theme) {
w.UpdateTheme()
})
}
func invokeSync[T any](cba *Window, fn func() (T, error)) (res T, err error) {
var wg sync.WaitGroup
wg.Add(1)
cba.Invoke(func() {
res, err = fn()
wg.Done()
})
wg.Wait()
return res, err
}
+37 -5
View File
@@ -10,11 +10,13 @@ import (
"encoding/json"
"fmt"
"log"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"sync"
"time"
"github.com/wailsapp/wails/v2/pkg/assetserver"
@@ -65,6 +67,7 @@ func (d *DevWebServer) Run(ctx context.Context) error {
myLogger = _logger.(*logger.Logger)
}
var assetHandler http.Handler
var wsHandler http.Handler
_fronendDevServerURL, _ := ctx.Value("frontenddevserverurl").(string)
@@ -74,23 +77,33 @@ func (d *DevWebServer) Run(ctx context.Context) error {
return c.String(http.StatusOK, assetdir)
})
var err error
assetHandler, err = assetserver.NewAssetHandler(assetServerConfig, myLogger)
if err != nil {
log.Fatal(err)
}
} else {
externalURL, err := url.Parse(_fronendDevServerURL)
if err != nil {
return err
}
if externalURL.Host == "" {
return fmt.Errorf("Invalid frontend:dev:serverUrl missing protocol scheme?")
}
waitCb := func() { d.LogDebug("Waiting for frontend DevServer '%s' to be ready", externalURL) }
if !checkPortIsOpen(externalURL.Host, time.Minute, waitCb) {
d.logger.Error("Timeout waiting for frontend DevServer")
}
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)
}
assetHandler, err := assetserver.NewAssetHandler(assetServerConfig, myLogger)
if err != nil {
log.Fatal(err)
}
// Setup internal dev server
bindingsJSON, err := d.appBindings.ToJSON()
if err != nil {
@@ -294,3 +307,22 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
result.server.HidePort = true
return result
}
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,7 +1,7 @@
//go:build dev
// +build dev
package assetserver
package devserver
import (
"errors"
@@ -10,12 +10,21 @@ import (
"net/http/httputil"
"net/url"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
func NewExternalAssetsHandler(logger Logger, options assetserver.Options, url *url.URL) http.Handler {
baseHandler := options.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)
@@ -28,7 +37,7 @@ func NewExternalAssetsHandler(logger Logger, options assetserver.Options, url *u
}
proxy.ModifyResponse = func(res *http.Response) error {
if baseHandler == nil {
if handler == nil {
return nil
}
@@ -44,11 +53,11 @@ func NewExternalAssetsHandler(logger Logger, options assetserver.Options, url *u
}
proxy.ErrorHandler = func(rw http.ResponseWriter, r *http.Request, err error) {
if baseHandler != nil && errors.Is(err, errSkipProxy) {
if handler != nil && errors.Is(err, errSkipProxy) {
if logger != nil {
logger.Debug("[ExternalAssetHandler] Loading '%s' failed, using original AssetHandler", r.URL)
logger.Debug("[ExternalAssetHandler] Loading '%s' failed, using AssetHandler", r.URL)
}
baseHandler.ServeHTTP(rw, r)
handler.ServeHTTP(rw, r)
} else {
if logger != nil {
logger.Error("[ExternalAssetHandler] Proxy error: %v", err)
@@ -57,24 +66,18 @@ func NewExternalAssetsHandler(logger Logger, options assetserver.Options, url *u
}
}
var result http.Handler = http.HandlerFunc(
return http.HandlerFunc(
func(rw http.ResponseWriter, req *http.Request) {
if req.Method == http.MethodGet {
proxy.ServeHTTP(rw, req)
return
}
if baseHandler != nil {
baseHandler.ServeHTTP(rw, req)
if handler != nil {
handler.ServeHTTP(rw, req)
return
}
rw.WriteHeader(http.StatusMethodNotAllowed)
})
if middleware := options.Middleware; middleware != nil {
result = middleware(result)
}
return result
}
@@ -1,8 +1,15 @@
package w32
//go:build windows
package win32
type Menu HMENU
type PopupMenu Menu
func CreatePopupMenu() PopupMenu {
ret, _, _ := procCreatePopupMenu.Call(0, 0, 0, 0)
return PopupMenu(ret)
}
func (m Menu) Destroy() bool {
ret, _, _ := procDestroyMenu.Call(uintptr(m))
return ret != 0
@@ -12,22 +19,31 @@ func (p PopupMenu) Destroy() bool {
return Menu(p).Destroy()
}
func (p PopupMenu) Track(hwnd HWND, flags uint32, x, y int32) bool {
return TrackPopupMenuEx(
HMENU(p),
flags,
x,
y,
hwnd,
nil)
func (p PopupMenu) Track(flags uint, x, y int, wnd HWND) bool {
ret, _, _ := procTrackPopupMenu.Call(
uintptr(p),
uintptr(flags),
uintptr(x),
uintptr(y),
0,
uintptr(wnd),
0,
)
return ret != 0
}
func (p PopupMenu) Append(flags uint32, id uintptr, text string) bool {
func (p PopupMenu) Append(flags uintptr, id uintptr, text string) bool {
return Menu(p).Append(flags, id, text)
}
func (m Menu) Append(flags uint32, id uintptr, text string) bool {
return AppendMenu(HMENU(m), flags, id, MustStringToUTF16Ptr(text))
func (m Menu) Append(flags uintptr, id uintptr, text string) bool {
ret, _, _ := procAppendMenuW.Call(
uintptr(m),
flags,
id,
MustStringToUTF16uintptr(text),
)
return ret != 0
}
func (p PopupMenu) Check(id uintptr, checked bool) bool {
@@ -54,7 +70,7 @@ func (m Menu) CheckRadio(startID int, endID int, selectedID int) bool {
func CheckMenuItem(menu HMENU, id uintptr, flags uint) uint {
ret, _, _ := procCheckMenuItem.Call(
menu,
uintptr(menu),
id,
uintptr(flags),
)
@@ -64,13 +80,3 @@ func CheckMenuItem(menu HMENU, id uintptr, flags uint) uint {
func (p PopupMenu) CheckRadio(startID, endID, selectedID int) bool {
return Menu(p).CheckRadio(startID, endID, selectedID)
}
func NewMenu() HMENU {
ret, _, _ := procCreateMenu.Call()
return HMENU(ret)
}
func NewPopupMenu() HMENU {
ret, _, _ := procCreatePopupMenu.Call()
return ret
}
+2 -8
View File
@@ -33,7 +33,6 @@ func (z *Zypper) Packages() packagemap {
{Name: "gtk3-devel", SystemPackage: true, Library: true},
},
"libwebkit": []*Package{
{Name: "webkit2gtk3-soup2-devel", SystemPackage: true, Library: true},
{Name: "webkit2gtk3-devel", SystemPackage: true, Library: true},
},
"gcc": []*Package{
@@ -41,7 +40,6 @@ func (z *Zypper) Packages() packagemap {
},
"pkg-config": []*Package{
{Name: "pkg-config", SystemPackage: true},
{Name: "pkgconf-pkg-config", SystemPackage: true},
},
"npm": []*Package{
{Name: "npm10", SystemPackage: true},
@@ -62,9 +60,7 @@ func (z *Zypper) PackageInstalled(pkg *Package) (bool, error) {
if pkg.SystemPackage == false {
return false, nil
}
var env []string
env = shell.SetEnv(env, "LANGUAGE", "en_US.utf-8")
stdout, _, err := shell.RunCommandWithEnv(env, ".", "zypper", "info", pkg.Name)
stdout, _, err := shell.RunCommand(".", "zypper", "info", pkg.Name)
if err != nil {
_, ok := err.(*exec.ExitError)
if ok {
@@ -87,9 +83,7 @@ func (z *Zypper) PackageAvailable(pkg *Package) (bool, error) {
if pkg.SystemPackage == false {
return false, nil
}
var env []string
env = shell.SetEnv(env, "LANGUAGE", "en_US.utf-8")
stdout, _, err := shell.RunCommandWithEnv(env, ".", "zypper", "info", pkg.Name)
stdout, _, err := shell.RunCommand(".", "zypper", "info", pkg.Name)
// We add a space to ensure we get a full match, not partial match
if err != nil {
_, ok := err.(*exec.ExitError)
+10 -2
View File
@@ -56,7 +56,13 @@ func (r legacyRequest) Response() webview.ResponseWriter {
return &legacyRequestNoOpCloserResponseWriter{r.rw}
}
func (r legacyRequest) Close() error { return nil }
func (r legacyRequest) AddRef() error {
return nil
}
func (r legacyRequest) Release() error {
return nil
}
func (r *legacyRequest) request() (*http.Request, error) {
if r.req != nil {
@@ -75,4 +81,6 @@ type legacyRequestNoOpCloserResponseWriter struct {
http.ResponseWriter
}
func (*legacyRequestNoOpCloserResponseWriter) Finish() {}
func (*legacyRequestNoOpCloserResponseWriter) Finish() error {
return nil
}
+7 -5
View File
@@ -22,7 +22,6 @@ type assetServerWebView struct {
// ServeWebViewRequest processes the HTTP Request asynchronously by faking a golang HTTP Server.
// The request will be finished with a StatusNotImplemented code if no handler has written to the response.
// The AssetServer takes ownership of the request and the caller mustn't close it or access it in any other way.
func (d *AssetServer) ServeWebViewRequest(req webview.Request) {
d.dispatchInit.Do(func() {
workers := d.dispatchWorkers
@@ -34,11 +33,8 @@ func (d *AssetServer) ServeWebViewRequest(req webview.Request) {
for i := 0; i < workers; i++ {
go func() {
for req := range workerC {
uri, _ := req.URL()
d.processWebViewRequest(req)
if err := req.Close(); err != nil {
d.logError("Unable to call close for request for uri '%s'", uri)
}
req.Release()
}
}()
}
@@ -49,6 +45,12 @@ func (d *AssetServer) ServeWebViewRequest(req webview.Request) {
d.dispatchReqC = dispatchC
})
if err := req.AddRef(); err != nil {
uri, _ := req.URL()
d.logError("Unable to call AddRef for request '%s'", uri)
return
}
d.dispatchReqC <- req
}
+2 -1
View File
@@ -13,5 +13,6 @@ type Request interface {
Response() ResponseWriter
Close() error
AddRef() error
Release() error
}

Some files were not shown because too many files have changed in this diff Show More