mirror of
https://github.com/wavetermdev/wails.git
synced 2026-04-22 15:26:15 -07:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f4c99764f3 | |||
| 4cdc166165 | |||
| cc6158b155 | |||
| a0e05e6422 | |||
| f7b3ed4904 | |||
| d1aa829164 | |||
| 9725fbf691 | |||
| d66e4da59c |
@@ -0,0 +1,439 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/colour"
|
||||
"github.com/wailsapp/wails/v2/internal/project"
|
||||
"github.com/wailsapp/wails/v2/internal/system"
|
||||
|
||||
"github.com/wailsapp/wails/v2/cmd/wails/internal"
|
||||
"github.com/wailsapp/wails/v2/internal/gomod"
|
||||
|
||||
"github.com/leaanthony/clir"
|
||||
"github.com/leaanthony/slicer"
|
||||
"github.com/wailsapp/wails/v2/pkg/clilogger"
|
||||
"github.com/wailsapp/wails/v2/pkg/commands/build"
|
||||
)
|
||||
|
||||
// AddBuildSubcommand adds the `build` command for the Wails application
|
||||
func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
command := app.NewSubCommand("build", "Builds the application")
|
||||
|
||||
outputType := "desktop"
|
||||
validTargetTypes := slicer.String([]string{"desktop", "hybrid", "server"})
|
||||
|
||||
command.StringFlag("outputType", fmt.Sprintf("Type of binary %s", validTargetTypes.AsSlice()), &outputType)
|
||||
|
||||
// Setup noPackage flag
|
||||
noPackage := false
|
||||
command.BoolFlag("noPackage", "Skips platform specific packaging", &noPackage)
|
||||
|
||||
compilerCommand := "go"
|
||||
command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &compilerCommand)
|
||||
|
||||
skipModTidy := false
|
||||
command.BoolFlag("m", "Skip mod tidy before compile", &skipModTidy)
|
||||
|
||||
compress := false
|
||||
command.BoolFlag("upx", "Compress final binary with UPX (if installed)", &compress)
|
||||
|
||||
compressFlags := ""
|
||||
command.StringFlag("upxflags", "Flags to pass to upx", &compressFlags)
|
||||
|
||||
defaultPlatform := os.Getenv("GOOS")
|
||||
if defaultPlatform == "" {
|
||||
defaultPlatform = runtime.GOOS
|
||||
}
|
||||
defaultArch := os.Getenv("GOARCH")
|
||||
if defaultArch == "" {
|
||||
if system.IsAppleSilicon {
|
||||
defaultArch = "arm64"
|
||||
} else {
|
||||
defaultArch = runtime.GOARCH
|
||||
}
|
||||
}
|
||||
platform := defaultPlatform + "/" + defaultArch
|
||||
|
||||
command.StringFlag("platform", "Platform to target. Comma separate multiple platforms", &platform)
|
||||
|
||||
// Verbosity
|
||||
verbosity := 1
|
||||
command.IntFlag("v", "Verbosity level (0 - silent, 1 - default, 2 - verbose)", &verbosity)
|
||||
|
||||
// ldflags to pass to `go`
|
||||
ldflags := ""
|
||||
command.StringFlag("ldflags", "optional ldflags", &ldflags)
|
||||
|
||||
// tags to pass to `go`
|
||||
tags := ""
|
||||
command.StringFlag("tags", "tags to pass to Go compiler (quoted and space separated)", &tags)
|
||||
|
||||
outputFilename := ""
|
||||
command.StringFlag("o", "Output filename", &outputFilename)
|
||||
|
||||
// Clean build directory
|
||||
cleanBuildDirectory := false
|
||||
command.BoolFlag("clean", "Clean the build directory before building", &cleanBuildDirectory)
|
||||
|
||||
webview2 := "download"
|
||||
command.StringFlag("webview2", "WebView2 installer strategy: download,embed,browser,error.", &webview2)
|
||||
|
||||
skipFrontend := false
|
||||
command.BoolFlag("s", "Skips building the frontend", &skipFrontend)
|
||||
|
||||
forceBuild := false
|
||||
command.BoolFlag("f", "Force build application", &forceBuild)
|
||||
|
||||
updateGoMod := false
|
||||
command.BoolFlag("u", "Updates go.mod to use the same Wails version as the CLI", &updateGoMod)
|
||||
|
||||
debug := false
|
||||
command.BoolFlag("debug", "Retains debug data in the compiled application", &debug)
|
||||
|
||||
nsis := false
|
||||
command.BoolFlag("nsis", "Generate NSIS installer for Windows", &nsis)
|
||||
|
||||
trimpath := false
|
||||
command.BoolFlag("trimpath", "Remove all file system paths from the resulting executable", &trimpath)
|
||||
|
||||
raceDetector := false
|
||||
command.BoolFlag("race", "Build with Go's race detector", &raceDetector)
|
||||
|
||||
windowsConsole := false
|
||||
command.BoolFlag("windowsconsole", "Keep the console when building for Windows", &windowsConsole)
|
||||
|
||||
dryRun := false
|
||||
command.BoolFlag("dryrun", "Dry run, prints the config for the command that would be executed", &dryRun)
|
||||
|
||||
command.Action(func() error {
|
||||
|
||||
quiet := verbosity == 0
|
||||
|
||||
// Create logger
|
||||
logger := clilogger.New(w)
|
||||
logger.Mute(quiet)
|
||||
|
||||
// Validate output type
|
||||
if !validTargetTypes.Contains(outputType) {
|
||||
return fmt.Errorf("output type '%s' is not valid", outputType)
|
||||
}
|
||||
|
||||
if !quiet {
|
||||
app.PrintBanner()
|
||||
}
|
||||
|
||||
// Lookup compiler path
|
||||
compilerPath, err := exec.LookPath(compilerCommand)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to find compiler: %s", compilerCommand)
|
||||
}
|
||||
|
||||
// Tags
|
||||
userTags := []string{}
|
||||
for _, tag := range strings.Split(tags, " ") {
|
||||
thisTag := strings.TrimSpace(tag)
|
||||
if thisTag != "" {
|
||||
userTags = append(userTags, thisTag)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate experimental
|
||||
if slicer.String([]string{"hybrid", "server"}).Contains(outputType) {
|
||||
if !slicer.String(userTags).Contains("exp") {
|
||||
return fmt.Errorf("output type '%s' requires the '-tags exp'", outputType)
|
||||
}
|
||||
}
|
||||
|
||||
// Webview2 installer strategy (download by default)
|
||||
wv2rtstrategy := ""
|
||||
webview2 = strings.ToLower(webview2)
|
||||
if webview2 != "" {
|
||||
validWV2Runtime := slicer.String([]string{"download", "embed", "browser", "error"})
|
||||
if !validWV2Runtime.Contains(webview2) {
|
||||
return fmt.Errorf("invalid option for flag 'webview2': %s", webview2)
|
||||
}
|
||||
// These are the build tags associated with the strategies
|
||||
switch webview2 {
|
||||
case "embed":
|
||||
wv2rtstrategy = "wv2runtime.embed"
|
||||
case "error":
|
||||
wv2rtstrategy = "wv2runtime.error"
|
||||
case "browser":
|
||||
wv2rtstrategy = "wv2runtime.browser"
|
||||
}
|
||||
}
|
||||
|
||||
mode := build.Production
|
||||
modeString := "Production"
|
||||
if debug {
|
||||
mode = build.Debug
|
||||
modeString = "Debug"
|
||||
}
|
||||
|
||||
var targets slicer.StringSlicer
|
||||
targets.AddSlice(strings.Split(platform, ","))
|
||||
targets.Deduplicate()
|
||||
|
||||
// Create BuildOptions
|
||||
buildOptions := &build.Options{
|
||||
Logger: logger,
|
||||
OutputType: outputType,
|
||||
OutputFile: outputFilename,
|
||||
CleanBuildDirectory: cleanBuildDirectory,
|
||||
Mode: mode,
|
||||
Pack: !noPackage,
|
||||
LDFlags: ldflags,
|
||||
Compiler: compilerCommand,
|
||||
SkipModTidy: skipModTidy,
|
||||
Verbosity: verbosity,
|
||||
ForceBuild: forceBuild,
|
||||
IgnoreFrontend: skipFrontend,
|
||||
Compress: compress,
|
||||
CompressFlags: compressFlags,
|
||||
UserTags: userTags,
|
||||
WebView2Strategy: wv2rtstrategy,
|
||||
TrimPath: trimpath,
|
||||
RaceDetector: raceDetector,
|
||||
WindowsConsole: windowsConsole,
|
||||
}
|
||||
|
||||
// Start a new tabwriter
|
||||
if !quiet {
|
||||
w := new(tabwriter.Writer)
|
||||
w.Init(os.Stdout, 8, 8, 0, '\t', 0)
|
||||
|
||||
// Write out the system information
|
||||
_, _ = fmt.Fprintf(w, "App Type: \t%s\n", buildOptions.OutputType)
|
||||
_, _ = fmt.Fprintf(w, "Platforms: \t%s\n", platform)
|
||||
_, _ = fmt.Fprintf(w, "Compiler: \t%s\n", compilerPath)
|
||||
_, _ = fmt.Fprintf(w, "Build Mode: \t%s\n", modeString)
|
||||
_, _ = fmt.Fprintf(w, "Skip Frontend: \t%t\n", skipFrontend)
|
||||
_, _ = fmt.Fprintf(w, "Compress: \t%t\n", buildOptions.Compress)
|
||||
_, _ = fmt.Fprintf(w, "Package: \t%t\n", buildOptions.Pack)
|
||||
_, _ = fmt.Fprintf(w, "Clean Build Dir: \t%t\n", buildOptions.CleanBuildDirectory)
|
||||
_, _ = fmt.Fprintf(w, "LDFlags: \t\"%s\"\n", buildOptions.LDFlags)
|
||||
_, _ = fmt.Fprintf(w, "Tags: \t[%s]\n", strings.Join(buildOptions.UserTags, ","))
|
||||
_, _ = fmt.Fprintf(w, "Race Detector: \t%t\n", buildOptions.RaceDetector)
|
||||
if len(buildOptions.OutputFile) > 0 && targets.Length() == 1 {
|
||||
_, _ = fmt.Fprintf(w, "Output File: \t%s\n", buildOptions.OutputFile)
|
||||
}
|
||||
_, _ = fmt.Fprintf(w, "\n")
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = checkGoModVersion(logger, updateGoMod)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
projectOptions, err := project.Load(cwd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check platform
|
||||
validPlatformArch := slicer.String([]string{
|
||||
"darwin",
|
||||
"darwin/amd64",
|
||||
"darwin/arm64",
|
||||
"darwin/universal",
|
||||
"linux",
|
||||
"linux/amd64",
|
||||
"linux/arm64",
|
||||
"linux/arm",
|
||||
"windows",
|
||||
"windows/amd64",
|
||||
"windows/arm64",
|
||||
"windows/386",
|
||||
})
|
||||
|
||||
outputBinaries := map[string]string{}
|
||||
|
||||
// Allows cancelling the build after the first error. It would be nice if targets.Each would support funcs
|
||||
// returning an error.
|
||||
var targetErr error
|
||||
targets.Each(func(platform string) {
|
||||
if targetErr != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !validPlatformArch.Contains(platform) {
|
||||
buildOptions.Logger.Println("platform '%s' is not supported - skipping. Supported platforms: %s", platform, validPlatformArch.Join(","))
|
||||
return
|
||||
}
|
||||
|
||||
desiredFilename := projectOptions.OutputFilename
|
||||
if desiredFilename == "" {
|
||||
desiredFilename = projectOptions.Name
|
||||
}
|
||||
desiredFilename = strings.TrimSuffix(desiredFilename, ".exe")
|
||||
|
||||
// Calculate platform and arch
|
||||
platformSplit := strings.Split(platform, "/")
|
||||
buildOptions.Platform = platformSplit[0]
|
||||
buildOptions.Arch = defaultArch
|
||||
if len(platformSplit) > 1 {
|
||||
buildOptions.Arch = platformSplit[1]
|
||||
}
|
||||
banner := "Building target: " + buildOptions.Platform + "/" + buildOptions.Arch
|
||||
logger.Println(banner)
|
||||
logger.Println(strings.Repeat("-", len(banner)))
|
||||
|
||||
if compress && platform == "darwin/universal" {
|
||||
logger.Println("Warning: compress flag unsupported for universal binaries. Ignoring.")
|
||||
compress = false
|
||||
}
|
||||
|
||||
switch buildOptions.Platform {
|
||||
case "linux":
|
||||
if runtime.GOOS != "linux" {
|
||||
logger.Println("Crosscompiling to Linux not currently supported.\n")
|
||||
return
|
||||
}
|
||||
case "darwin":
|
||||
if runtime.GOOS != "darwin" {
|
||||
logger.Println("Crosscompiling to Mac not currently supported.\n")
|
||||
return
|
||||
}
|
||||
macTargets := targets.Filter(func(platform string) bool {
|
||||
return strings.HasPrefix(platform, "darwin")
|
||||
})
|
||||
if macTargets.Length() == 2 {
|
||||
buildOptions.BundleName = fmt.Sprintf("%s-%s.app", desiredFilename, buildOptions.Arch)
|
||||
}
|
||||
}
|
||||
|
||||
if targets.Length() > 1 {
|
||||
// target filename
|
||||
switch buildOptions.Platform {
|
||||
case "windows":
|
||||
desiredFilename = fmt.Sprintf("%s-%s", desiredFilename, buildOptions.Arch)
|
||||
case "linux", "darwin":
|
||||
desiredFilename = fmt.Sprintf("%s-%s-%s", desiredFilename, buildOptions.Platform, buildOptions.Arch)
|
||||
}
|
||||
}
|
||||
if buildOptions.Platform == "windows" {
|
||||
desiredFilename += ".exe"
|
||||
}
|
||||
buildOptions.OutputFile = desiredFilename
|
||||
|
||||
if outputFilename != "" {
|
||||
buildOptions.OutputFile = outputFilename
|
||||
}
|
||||
|
||||
if !dryRun {
|
||||
// Start Time
|
||||
start := time.Now()
|
||||
|
||||
compiledBinary, err := build.Build(buildOptions)
|
||||
if err != nil {
|
||||
logger.Println("Error: %s", err.Error())
|
||||
targetErr = err
|
||||
return
|
||||
}
|
||||
|
||||
buildOptions.IgnoreFrontend = true
|
||||
buildOptions.CleanBuildDirectory = false
|
||||
|
||||
// Output stats
|
||||
buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.\n", compiledBinary, time.Since(start).Round(time.Millisecond).String()))
|
||||
|
||||
outputBinaries[buildOptions.Platform+"/"+buildOptions.Arch] = compiledBinary
|
||||
} else {
|
||||
logger.Println("Dry run: skipped build.")
|
||||
}
|
||||
})
|
||||
|
||||
if targetErr != nil {
|
||||
return targetErr
|
||||
}
|
||||
|
||||
if dryRun {
|
||||
return nil
|
||||
}
|
||||
|
||||
if nsis {
|
||||
amd64Binary := outputBinaries["windows/amd64"]
|
||||
arm64Binary := outputBinaries["windows/arm64"]
|
||||
if amd64Binary == "" && arm64Binary == "" {
|
||||
return fmt.Errorf("cannot build nsis installer - no windows targets")
|
||||
}
|
||||
|
||||
if err := build.GenerateNSISInstaller(buildOptions, amd64Binary, arm64Binary); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func checkGoModVersion(logger *clilogger.CLILogger, updateGoMod bool) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gomodFilename := filepath.Join(cwd, "go.mod")
|
||||
gomodData, err := os.ReadFile(gomodFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
outOfSync, err := gomod.GoModOutOfSync(gomodData, internal.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !outOfSync {
|
||||
return nil
|
||||
}
|
||||
gomodversion, err := gomod.GetWailsVersionFromModFile(gomodData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if updateGoMod {
|
||||
return syncGoModVersion(cwd)
|
||||
}
|
||||
|
||||
logger.Println("Warning: go.mod is using Wails '%s' but the CLI is '%s'. Consider updating your project's `go.mod` file.\n", gomodversion.String(), internal.Version)
|
||||
return nil
|
||||
}
|
||||
|
||||
func LogGreen(message string, args ...interface{}) {
|
||||
text := fmt.Sprintf(message, args...)
|
||||
println(colour.Green(text))
|
||||
}
|
||||
|
||||
func syncGoModVersion(cwd string) error {
|
||||
gomodFilename := filepath.Join(cwd, "go.mod")
|
||||
gomodData, err := os.ReadFile(gomodFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
outOfSync, err := gomod.GoModOutOfSync(gomodData, internal.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !outOfSync {
|
||||
return nil
|
||||
}
|
||||
LogGreen("Updating go.mod to use Wails '%s'", internal.Version)
|
||||
newGoData, err := gomod.UpdateGoModVersion(gomodData, internal.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(gomodFilename, newGoData, 0755)
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
module github.com/wailsapp/wails/v2
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
toolchain go1.22.1
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
|
||||
@@ -14,6 +14,7 @@ github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzX
|
||||
github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c=
|
||||
github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=
|
||||
github.com/MarvinJWendt/testza v0.4.3 h1:u2XaM4IqGp9dsdUmML8/Z791fu4yjQYzOiufOtJwTII=
|
||||
github.com/MarvinJWendt/testza v0.4.3/go.mod h1:CpXaOfceNEYnLDtNIyTrPPcCpDJYqzZnu2aiA2Wp33U=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
@@ -28,7 +29,9 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat6
|
||||
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
||||
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
@@ -52,6 +55,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/flytam/filenamify v1.0.0 h1:ewx6BY2dj7U6h2zGPJmt33q/BjkSf/YsY/woQvnUNIs=
|
||||
@@ -61,11 +65,13 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
|
||||
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
@@ -78,6 +84,7 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
@@ -105,11 +112,14 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
|
||||
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0=
|
||||
github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
|
||||
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
@@ -161,6 +171,7 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
@@ -183,6 +194,7 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
|
||||
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
|
||||
@@ -271,6 +283,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -330,6 +343,7 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build dev
|
||||
//go:build dev && desktop
|
||||
|
||||
package app
|
||||
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
//go:build (exp && hybrid) || (exp && server)
|
||||
// +build exp,hybrid exp,server
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/hybrid"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||
"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)
|
||||
if a.shutdownCallback != nil {
|
||||
a.shutdownCallback(a.ctx)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateApp creates the app!
|
||||
func CreateApp(appoptions *options.App) (*App, error) {
|
||||
var err error
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
host, port := "localhost", int32(3112)
|
||||
if appoptions.Server != nil {
|
||||
host = appoptions.Server.Host
|
||||
port = appoptions.Server.Port
|
||||
}
|
||||
|
||||
serverURI := fmt.Sprintf("%s:%d", host, port)
|
||||
ctx = context.WithValue(ctx, "starturl", serverURI)
|
||||
ctx = context.WithValue(ctx, "devserver", fmt.Sprintf("%s:%d", host, port))
|
||||
|
||||
// Merge default options
|
||||
options.MergeDefaults(appoptions)
|
||||
|
||||
debug := IsDebug()
|
||||
ctx = context.WithValue(ctx, "debug", debug)
|
||||
|
||||
// Set up logger
|
||||
myLogger := logger.New(appoptions.Logger)
|
||||
myLogger.Info("Frontend available at 'http://%s'", serverURI)
|
||||
if IsDebug() {
|
||||
myLogger.SetLogLevel(appoptions.LogLevel)
|
||||
} else {
|
||||
myLogger.SetLogLevel(appoptions.LogLevelProduction)
|
||||
}
|
||||
ctx = context.WithValue(ctx, "logger", myLogger)
|
||||
|
||||
// Preflight Checks
|
||||
err = PreflightChecks(appoptions, myLogger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create the menu manager
|
||||
menuManager := menumanager.NewManager()
|
||||
|
||||
// Process the application menu
|
||||
if appoptions.Menu != nil {
|
||||
err = menuManager.SetApplicationMenu(appoptions.Menu)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Create binding exemptions - Ugly hack. There must be a better way
|
||||
bindingExemptions := []interface{}{appoptions.OnStartup, appoptions.OnShutdown, appoptions.OnDomReady}
|
||||
appBindings := binding.NewBindings(myLogger, appoptions.Bind, bindingExemptions)
|
||||
eventHandler := runtime.NewEvents(myLogger)
|
||||
ctx = context.WithValue(ctx, "events", eventHandler)
|
||||
// Attach logger to context
|
||||
if debug {
|
||||
ctx = context.WithValue(ctx, "buildtype", "debug")
|
||||
} else {
|
||||
ctx = context.WithValue(ctx, "buildtype", "production")
|
||||
}
|
||||
|
||||
messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler)
|
||||
appFrontend := hybrid.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher)
|
||||
eventHandler.AddFrontend(appFrontend)
|
||||
|
||||
result := &App{
|
||||
ctx: ctx,
|
||||
frontend: appFrontend,
|
||||
logger: myLogger,
|
||||
menuManager: menuManager,
|
||||
startupCallback: appoptions.OnStartup,
|
||||
shutdownCallback: appoptions.OnShutdown,
|
||||
debug: debug,
|
||||
options: appoptions,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build production
|
||||
//go:build production && desktop
|
||||
|
||||
package app
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package null
|
||||
|
||||
// BrowserOpenURL does nothing
|
||||
func (f *Frontend) BrowserOpenURL(url string) {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package null
|
||||
|
||||
import "github.com/wailsapp/wails/v2/internal/frontend"
|
||||
|
||||
// OpenFileDialog does nothing
|
||||
func (f *Frontend) OpenFileDialog(dialogOptions frontend.OpenDialogOptions) (result string, err error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// OpenMultipleFilesDialog does nothing
|
||||
func (f *Frontend) OpenMultipleFilesDialog(dialogOptions frontend.OpenDialogOptions) ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
// OpenDirectoryDialog does nothing
|
||||
func (f *Frontend) OpenDirectoryDialog(dialogOptions frontend.OpenDialogOptions) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// SaveFileDialog does nothing
|
||||
func (f *Frontend) SaveFileDialog(dialogOptions frontend.SaveDialogOptions) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// MessageDialog does nothing
|
||||
func (f *Frontend) MessageDialog(dialogOptions frontend.MessageDialogOptions) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package null
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
)
|
||||
|
||||
// Frontend implements an empty Frontend that simply waits until the context is done.
|
||||
type Frontend struct {
|
||||
// Context
|
||||
ctx context.Context
|
||||
frontendOptions *options.App
|
||||
|
||||
done bool
|
||||
}
|
||||
|
||||
// NewFrontend returns an initialized Frontend
|
||||
func NewFrontend(ctx context.Context, appoptions *options.App) *Frontend {
|
||||
return &Frontend{
|
||||
frontendOptions: appoptions,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// Show does nothing
|
||||
func (f *Frontend) Show() {
|
||||
|
||||
}
|
||||
|
||||
// Hide does nothing
|
||||
func (f *Frontend) Hide() {
|
||||
|
||||
}
|
||||
|
||||
// ScreenGetAll returns an empty slice
|
||||
func (f *Frontend) ScreenGetAll() ([]frontend.Screen, error) {
|
||||
return []frontend.Screen{}, nil
|
||||
}
|
||||
|
||||
// WindowSetBackgroundColour does nothing
|
||||
func (f *Frontend) WindowSetBackgroundColour(col *options.RGBA) {
|
||||
|
||||
}
|
||||
|
||||
// WindowReload does nothing
|
||||
func (f *Frontend) WindowReload() {
|
||||
|
||||
}
|
||||
|
||||
// WindowReloadApp does nothing
|
||||
func (f *Frontend) WindowReloadApp() {
|
||||
|
||||
}
|
||||
|
||||
// WindowSetAlwaysOnTop does nothing
|
||||
func (f *Frontend) WindowSetAlwaysOnTop(b bool) {
|
||||
|
||||
}
|
||||
|
||||
// WindowSetSystemDefaultTheme does nothing
|
||||
func (f *Frontend) WindowSetSystemDefaultTheme() {
|
||||
|
||||
}
|
||||
|
||||
// WindowSetLightTheme does nothing
|
||||
func (f *Frontend) WindowSetLightTheme() {
|
||||
|
||||
}
|
||||
|
||||
// WindowSetDarkTheme does nothing
|
||||
func (f *Frontend) WindowSetDarkTheme() {
|
||||
|
||||
}
|
||||
|
||||
// Run waits until the context is done and then exits
|
||||
func (f *Frontend) Run(ctx context.Context) (err error) {
|
||||
err = nil
|
||||
go func() {
|
||||
if f.frontendOptions.OnStartup != nil {
|
||||
f.frontendOptions.OnStartup(f.ctx)
|
||||
}
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
}
|
||||
if f.done {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// WindowCenter does nothing
|
||||
func (f *Frontend) WindowCenter() {
|
||||
|
||||
}
|
||||
|
||||
// WindowSetPosition does nothing
|
||||
func (f *Frontend) WindowSetPosition(x, y int) {
|
||||
|
||||
}
|
||||
|
||||
// WindowGetPosition does nothing
|
||||
func (f *Frontend) WindowGetPosition() (int, int) {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// WindowSetSize does nothing
|
||||
func (f *Frontend) WindowSetSize(width, height int) {
|
||||
|
||||
}
|
||||
|
||||
// WindowGetSize does nothing
|
||||
func (f *Frontend) WindowGetSize() (int, int) {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// WindowSetTitle does nothing
|
||||
func (f *Frontend) WindowSetTitle(title string) {
|
||||
|
||||
}
|
||||
|
||||
// WindowFullscreen does nothing
|
||||
func (f *Frontend) WindowFullscreen() {
|
||||
|
||||
}
|
||||
|
||||
// WindowUnfullscreen does nothing
|
||||
func (f *Frontend) WindowUnfullscreen() {
|
||||
|
||||
}
|
||||
|
||||
// WindowShow does nothing
|
||||
func (f *Frontend) WindowShow() {
|
||||
|
||||
}
|
||||
|
||||
// WindowHide does nothing
|
||||
func (f *Frontend) WindowHide() {
|
||||
|
||||
}
|
||||
|
||||
// WindowMaximize does nothing
|
||||
func (f *Frontend) WindowMaximise() {
|
||||
|
||||
}
|
||||
|
||||
// WindowToggleMaximise does nothing
|
||||
func (f *Frontend) WindowToggleMaximise() {
|
||||
|
||||
}
|
||||
|
||||
// WindowUnmaximise does nothing
|
||||
func (f *Frontend) WindowUnmaximise() {
|
||||
}
|
||||
|
||||
// WindowMinimise does nothing
|
||||
func (f *Frontend) WindowMinimise() {
|
||||
|
||||
}
|
||||
|
||||
// WindowUnminimise does nothing
|
||||
func (f *Frontend) WindowUnminimise() {
|
||||
|
||||
}
|
||||
|
||||
// WindowSetMinSize does nothing
|
||||
func (f *Frontend) WindowSetMinSize(width int, height int) {
|
||||
|
||||
}
|
||||
|
||||
// WindowSetMaxSize does nothing
|
||||
func (f *Frontend) WindowSetMaxSize(width int, height int) {
|
||||
|
||||
}
|
||||
|
||||
// WindowSetRGBA does nothing
|
||||
func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
|
||||
}
|
||||
|
||||
// Quit does nothing
|
||||
func (f *Frontend) Quit() {
|
||||
f.done = true
|
||||
}
|
||||
|
||||
// Notify does nothing
|
||||
func (f *Frontend) Notify(name string, data ...interface{}) {
|
||||
|
||||
}
|
||||
|
||||
// Callback does nothing
|
||||
func (f *Frontend) Callback(message string) {
|
||||
|
||||
}
|
||||
|
||||
// startDrag does nothing
|
||||
func (f *Frontend) startDrag() {
|
||||
|
||||
}
|
||||
|
||||
// ExecJS does nothing
|
||||
func (f *Frontend) ExecJS(js string) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package null
|
||||
|
||||
import "github.com/wailsapp/wails/v2/pkg/menu"
|
||||
|
||||
//MenuSetApplicationMenu does nothing
|
||||
func (f *Frontend) MenuSetApplicationMenu(menu *menu.Menu) {
|
||||
}
|
||||
|
||||
// MenuUpdateApplicationMenu does nothing
|
||||
func (f *Frontend) MenuUpdateApplicationMenu() {
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//go:build dev
|
||||
// +build dev
|
||||
//go:build dev || server || hybrid
|
||||
// +build dev server hybrid
|
||||
|
||||
// Package devserver provides a web-based frontend so that
|
||||
// it is possible to run a Wails app in a browsers.
|
||||
@@ -110,7 +110,7 @@ func (d *DevWebServer) Run(ctx context.Context) error {
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
d.LogDebug("Serving DevServer at http://%s", d.devServerAddr)
|
||||
if devServerAddr := d.devServerAddr; devServerAddr != "" {
|
||||
// Start server
|
||||
go func(server *echo.Echo, log *logger.Logger) {
|
||||
@@ -156,7 +156,7 @@ func (d *DevWebServer) handleReloadApp(c echo.Context) error {
|
||||
|
||||
func (d *DevWebServer) handleIPCWebSocket(c echo.Context) error {
|
||||
websocket.Handler(func(c *websocket.Conn) {
|
||||
d.LogDebug(fmt.Sprintf("Websocket client %p connected", c))
|
||||
d.LogDebug(fmt.Sprintf("Websocket client %v connected", c.Request().RemoteAddr))
|
||||
d.socketMutex.Lock()
|
||||
d.websocketClients[c] = &sync.Mutex{}
|
||||
locker := d.websocketClients[c]
|
||||
@@ -166,7 +166,7 @@ func (d *DevWebServer) handleIPCWebSocket(c echo.Context) error {
|
||||
d.socketMutex.Lock()
|
||||
delete(d.websocketClients, c)
|
||||
d.socketMutex.Unlock()
|
||||
d.LogDebug(fmt.Sprintf("Websocket client %p disconnected", c))
|
||||
d.LogDebug(fmt.Sprintf("Websocket client %v disconnected", c.Request().RemoteAddr))
|
||||
}()
|
||||
|
||||
var msg string
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
//go:build exp && hybrid
|
||||
// +build exp,hybrid
|
||||
|
||||
package hybrid
|
||||
|
||||
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/devserver"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
)
|
||||
|
||||
// New returns a new Hybrid frontend
|
||||
// A hybrid Frontend implementation contains a devserver.Frontend wrapping a desktop.Frontend
|
||||
func NewFrontend(ctx context.Context, appoptions *options.App, logger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) frontend.Frontend {
|
||||
appFrontend := desktop.NewFrontend(ctx, appoptions, logger, appBindings, dispatcher)
|
||||
return devserver.NewFrontend(ctx, appoptions, logger, appBindings, dispatcher, nil, appFrontend)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
//go:build exp && server
|
||||
// +build exp,server
|
||||
|
||||
package hybrid
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop/null"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/devserver"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
)
|
||||
|
||||
// New returns a new Server frontend
|
||||
// A server Frontend implementation contains a devserver.Frontend wrapping a null.Frontend
|
||||
func NewFrontend(ctx context.Context, appoptions *options.App, logger *logger.Logger, appBindings *binding.Bindings, dispatcher frontend.Dispatcher) frontend.Frontend {
|
||||
return devserver.NewFrontend(ctx, appoptions, logger, appBindings, dispatcher, nil, null.NewFrontend(ctx, appoptions))
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//go:build dev
|
||||
// +build dev
|
||||
//go:build dev || server || hybrid
|
||||
// +build dev server hybrid
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//go:build dev
|
||||
// +build dev
|
||||
//go:build dev || hybrid || server
|
||||
// +build dev hybrid server
|
||||
|
||||
package assetserver
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ func Build(options *Options) (string, error) {
|
||||
switch options.OutputType {
|
||||
case "desktop":
|
||||
builder = newDesktopBuilder(options)
|
||||
case "dev":
|
||||
case "dev", "hybrid", "server":
|
||||
builder = newDesktopBuilder(options)
|
||||
default:
|
||||
return "", fmt.Errorf("cannot build assets for output type %s", options.ProjectData.OutputType)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"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/server"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
@@ -95,6 +96,8 @@ type App struct {
|
||||
|
||||
// Debug options for debug builds. These options will be ignored in a production build.
|
||||
Debug Debug
|
||||
// Server options (also used by hybrid)
|
||||
Server *server.Options
|
||||
}
|
||||
|
||||
type ErrorFormatter func(error) any
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package server
|
||||
|
||||
// Options are options specific to the server
|
||||
type Options struct {
|
||||
EnableServer bool
|
||||
Host string
|
||||
Port int32
|
||||
}
|
||||
Reference in New Issue
Block a user