@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
- [1. Internationalization](#nav-1)
|
- [1. Internationalization](#nav-1)
|
||||||
- [2. Table of Contents](#nav-2)
|
- [2. Table of Contents](#nav-2)
|
||||||
- [3. Introductions](#nav-3)
|
- [3. Introduction](#nav-3)
|
||||||
- [3.1 Official Website](#nav-3-1)
|
- [3.1 Official Website](#nav-3-1)
|
||||||
- [4. Features](#nav-4)
|
- [4. Features](#nav-4)
|
||||||
- [5. Sponsors](#nav-5)
|
- [5. Sponsors](#nav-5)
|
||||||
|
@ -5,11 +5,15 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/cmd/wails/internal"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/gomod"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/internal/system"
|
"github.com/wailsapp/wails/v2/internal/system"
|
||||||
|
|
||||||
"github.com/leaanthony/clir"
|
"github.com/leaanthony/clir"
|
||||||
@ -129,8 +133,8 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if runtime.GOOS == "darwin" && !experimental {
|
if runtime.GOOS == "linux" && !experimental {
|
||||||
return fmt.Errorf("MacOS version coming soon!")
|
return fmt.Errorf("Linux version coming soon!")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Webview2 installer strategy (download by default)
|
// Webview2 installer strategy (download by default)
|
||||||
@ -205,6 +209,11 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
|||||||
fmt.Fprintf(w, "\n")
|
fmt.Fprintf(w, "\n")
|
||||||
w.Flush()
|
w.Flush()
|
||||||
|
|
||||||
|
err = checkGoModVersion(logger)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return doBuild(buildOptions)
|
return doBuild(buildOptions)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -228,3 +237,29 @@ func doBuild(buildOptions *build.Options) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkGoModVersion(logger *clilogger.CLILogger) 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
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Println("Warning: go.mod is using Wails '%s' but the CLI is '%s'. Consider updating it.\n", gomodversion.String(), internal.Version)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -113,8 +113,8 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if runtime.GOOS == "darwin" && !experimental {
|
if runtime.GOOS == "linux" && !experimental {
|
||||||
return fmt.Errorf("MacOS version coming soon!")
|
return fmt.Errorf("Linux version coming soon!")
|
||||||
}
|
}
|
||||||
|
|
||||||
cwd, err := os.Getwd()
|
cwd, err := os.Getwd()
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
html {
|
html {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: white;
|
color: white;
|
||||||
background-color: rgba(0, 0, 0, 255);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"embed"
|
"embed"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2"
|
"github.com/wailsapp/wails/v2"
|
||||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
@ -13,6 +15,9 @@ import (
|
|||||||
//go:embed frontend/dist
|
//go:embed frontend/dist
|
||||||
var assets embed.FS
|
var assets embed.FS
|
||||||
|
|
||||||
|
//go:embed build/appicon.png
|
||||||
|
var icon []byte
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Create an instance of the app structure
|
// Create an instance of the app structure
|
||||||
app := NewApp()
|
app := NewApp()
|
||||||
@ -31,7 +36,7 @@ func main() {
|
|||||||
Frameless: false,
|
Frameless: false,
|
||||||
StartHidden: false,
|
StartHidden: false,
|
||||||
HideWindowOnClose: false,
|
HideWindowOnClose: false,
|
||||||
RGBA: &options.RGBA{R: 255, G: 255, B: 255, A: 255},
|
RGBA: &options.RGBA{R: 0, G: 0, B: 0, A: 0},
|
||||||
Assets: assets,
|
Assets: assets,
|
||||||
LogLevel: logger.DEBUG,
|
LogLevel: logger.DEBUG,
|
||||||
OnStartup: app.startup,
|
OnStartup: app.startup,
|
||||||
@ -46,6 +51,17 @@ func main() {
|
|||||||
WindowIsTranslucent: false,
|
WindowIsTranslucent: false,
|
||||||
DisableWindowIcon: false,
|
DisableWindowIcon: false,
|
||||||
},
|
},
|
||||||
|
Mac: &mac.Options{
|
||||||
|
TitleBar: mac.TitleBarHiddenInset(),
|
||||||
|
Appearance: mac.NSAppearanceNameDarkAqua,
|
||||||
|
WebviewIsTransparent: true,
|
||||||
|
WindowIsTranslucent: true,
|
||||||
|
About: &mac.AboutInfo{
|
||||||
|
Title: "My Application",
|
||||||
|
Message: "© 2021 Me",
|
||||||
|
Icon: icon,
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
html {
|
html {
|
||||||
background-color: rgba(33, 37, 43, 1);
|
background-color: rgba(33, 37, 43, 0);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"embed"
|
"embed"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2"
|
"github.com/wailsapp/wails/v2"
|
||||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
@ -13,6 +15,9 @@ import (
|
|||||||
//go:embed frontend/src
|
//go:embed frontend/src
|
||||||
var assets embed.FS
|
var assets embed.FS
|
||||||
|
|
||||||
|
//go:embed build/appicon.png
|
||||||
|
var icon []byte
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Create an instance of the app structure
|
// Create an instance of the app structure
|
||||||
app := NewApp()
|
app := NewApp()
|
||||||
@ -31,7 +36,7 @@ func main() {
|
|||||||
Frameless: false,
|
Frameless: false,
|
||||||
StartHidden: false,
|
StartHidden: false,
|
||||||
HideWindowOnClose: false,
|
HideWindowOnClose: false,
|
||||||
RGBA: &options.RGBA{R: 255, G: 255, B: 255, A: 255},
|
RGBA: &options.RGBA{R: 0, G: 0, B: 0, A: 0},
|
||||||
Assets: assets,
|
Assets: assets,
|
||||||
LogLevel: logger.DEBUG,
|
LogLevel: logger.DEBUG,
|
||||||
OnStartup: app.startup,
|
OnStartup: app.startup,
|
||||||
@ -46,6 +51,16 @@ func main() {
|
|||||||
WindowIsTranslucent: false,
|
WindowIsTranslucent: false,
|
||||||
DisableWindowIcon: false,
|
DisableWindowIcon: false,
|
||||||
},
|
},
|
||||||
|
Mac: &mac.Options{
|
||||||
|
TitleBar: mac.TitleBarHiddenInset(),
|
||||||
|
WebviewIsTransparent: true,
|
||||||
|
WindowIsTranslucent: true,
|
||||||
|
About: &mac.AboutInfo{
|
||||||
|
Title: "Vanilla Template",
|
||||||
|
Message: "Part of the Wails projects",
|
||||||
|
Icon: icon,
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -13,6 +13,7 @@ require (
|
|||||||
github.com/gofiber/fiber/v2 v2.17.0
|
github.com/gofiber/fiber/v2 v2.17.0
|
||||||
github.com/gofiber/websocket/v2 v2.0.8
|
github.com/gofiber/websocket/v2 v2.0.8
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||||
github.com/google/uuid v1.1.2 // indirect
|
github.com/google/uuid v1.1.2 // indirect
|
||||||
github.com/gorilla/websocket v1.4.1
|
github.com/gorilla/websocket v1.4.1
|
||||||
github.com/imdario/mergo v0.3.12
|
github.com/imdario/mergo v0.3.12
|
||||||
@ -56,11 +57,11 @@ require (
|
|||||||
github.com/go-git/gcfg v1.5.0 // indirect
|
github.com/go-git/gcfg v1.5.0 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||||
github.com/google/go-cmp v0.5.5 // indirect
|
github.com/google/go-cmp v0.5.5 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
|
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
|
||||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||||
github.com/klauspost/compress v1.12.2 // indirect
|
github.com/klauspost/compress v1.12.2 // indirect
|
||||||
|
github.com/kr/pretty v0.3.0 // indirect
|
||||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e // indirect
|
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.7 // indirect
|
github.com/mattn/go-runewidth v0.0.7 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
@ -103,8 +103,9 @@ github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8
|
|||||||
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
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.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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@ -161,6 +162,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||||
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f h1:PgA+Olipyj258EIEYnpFFONrrCcAIWNUNoFhUfMqAGY=
|
github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f h1:PgA+Olipyj258EIEYnpFFONrrCcAIWNUNoFhUfMqAGY=
|
||||||
github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY=
|
github.com/savsgio/gotils v0.0.0-20200117113501-90175b0fbe3f/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY=
|
||||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||||
@ -282,10 +285,12 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
|||||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
"github.com/wailsapp/wails/v2/internal/logger"
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
"github.com/wailsapp/wails/v2/internal/menumanager"
|
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||||
"github.com/wailsapp/wails/v2/internal/project"
|
"github.com/wailsapp/wails/v2/internal/project"
|
||||||
"github.com/wailsapp/wails/v2/internal/signal"
|
|
||||||
pkglogger "github.com/wailsapp/wails/v2/pkg/logger"
|
pkglogger "github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
)
|
)
|
||||||
@ -27,7 +26,6 @@ import (
|
|||||||
type App struct {
|
type App struct {
|
||||||
frontend frontend.Frontend
|
frontend frontend.Frontend
|
||||||
logger *logger.Logger
|
logger *logger.Logger
|
||||||
signal *signal.Manager
|
|
||||||
options *options.App
|
options *options.App
|
||||||
|
|
||||||
menuManager *menumanager.Manager
|
menuManager *menumanager.Manager
|
||||||
|
@ -5,6 +5,7 @@ package appng
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/internal/binding"
|
"github.com/wailsapp/wails/v2/internal/binding"
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend/desktop"
|
"github.com/wailsapp/wails/v2/internal/frontend/desktop"
|
||||||
@ -12,7 +13,6 @@ import (
|
|||||||
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||||
"github.com/wailsapp/wails/v2/internal/logger"
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
"github.com/wailsapp/wails/v2/internal/menumanager"
|
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||||
"github.com/wailsapp/wails/v2/internal/signal"
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,7 +20,6 @@ import (
|
|||||||
type App struct {
|
type App struct {
|
||||||
frontend frontend.Frontend
|
frontend frontend.Frontend
|
||||||
logger *logger.Logger
|
logger *logger.Logger
|
||||||
signal *signal.Manager
|
|
||||||
options *options.App
|
options *options.App
|
||||||
|
|
||||||
menuManager *menumanager.Manager
|
menuManager *menumanager.Manager
|
||||||
@ -36,9 +35,6 @@ type App struct {
|
|||||||
|
|
||||||
func (a *App) Run() error {
|
func (a *App) Run() error {
|
||||||
err := a.frontend.Run(a.ctx)
|
err := a.frontend.Run(a.ctx)
|
||||||
if a.shutdownCallback != nil {
|
|
||||||
a.shutdownCallback(a.ctx)
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,12 @@
|
|||||||
#define AppDelegate_h
|
#define AppDelegate_h
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import "WailsContext.h"
|
||||||
|
|
||||||
@interface AppDelegate : NSResponder <NSTouchBarProvider>
|
@interface AppDelegate : NSResponder <NSTouchBarProvider>
|
||||||
|
|
||||||
@property bool alwaysOnTop;
|
@property bool alwaysOnTop;
|
||||||
@property (retain) NSWindow* mainWindow;
|
@property (retain) WailsWindow* mainWindow;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ void* NewMenu(const char* name);
|
|||||||
void AppendSubmenu(void* parent, void* child);
|
void AppendSubmenu(void* parent, void* child);
|
||||||
void AppendRole(void *inctx, void *inMenu, int role);
|
void AppendRole(void *inctx, void *inMenu, int role);
|
||||||
void SetAsApplicationMenu(void *inctx, void *inMenu);
|
void SetAsApplicationMenu(void *inctx, void *inMenu);
|
||||||
|
void UpdateApplicationMenu(void *inctx);
|
||||||
|
|
||||||
void SetAbout(void *inctx, const char* title, const char* description, void* imagedata, int datalen);
|
void SetAbout(void *inctx, const char* title, const char* description, void* imagedata, int datalen);
|
||||||
void* AppendMenuItem(void* inctx, void* nsmenu, const char* label, const char* shortcutKey, int modifiers, int disabled, int checked, int menuItemID);
|
void* AppendMenuItem(void* inctx, void* nsmenu, const char* label, const char* shortcutKey, int modifiers, int disabled, int checked, int menuItemID);
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug) {
|
WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int debug) {
|
||||||
|
|
||||||
|
[NSApplication sharedApplication];
|
||||||
|
|
||||||
WailsContext *result = [WailsContext new];
|
WailsContext *result = [WailsContext new];
|
||||||
|
|
||||||
result.debug = debug;
|
result.debug = debug;
|
||||||
@ -256,6 +258,14 @@ void SetAsApplicationMenu(void *inctx, void *inMenu) {
|
|||||||
ctx.applicationMenu = menu;
|
ctx.applicationMenu = menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateApplicationMenu(void *inctx) {
|
||||||
|
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||||
|
ON_MAIN_THREAD(
|
||||||
|
NSApplication *app = [NSApplication sharedApplication];
|
||||||
|
[app setMainMenu:ctx.applicationMenu];
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
void SetAbout(void *inctx, const char* title, const char* description, void* imagedata, int datalen) {
|
void SetAbout(void *inctx, const char* title, const char* description, void* imagedata, int datalen) {
|
||||||
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||||
NSString *_title = safeInit(title);
|
NSString *_title = safeInit(title);
|
||||||
|
@ -13,14 +13,12 @@
|
|||||||
|
|
||||||
#define ON_MAIN_THREAD(str) dispatch_async(dispatch_get_main_queue(), ^{ str; });
|
#define ON_MAIN_THREAD(str) dispatch_async(dispatch_get_main_queue(), ^{ str; });
|
||||||
#define unicode(input) [NSString stringWithFormat:@"%C", input]
|
#define unicode(input) [NSString stringWithFormat:@"%C", input]
|
||||||
#define STREQ(a,b) strcmp(a, b) == 0
|
|
||||||
|
|
||||||
|
|
||||||
@interface WailsWindow : NSWindow
|
@interface WailsWindow : NSWindow
|
||||||
- (BOOL)canBecomeKeyWindow;
|
- (BOOL)canBecomeKeyWindow;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface WailsContext : NSObject <WKURLSchemeHandler,WKScriptMessageHandler>
|
@interface WailsContext : NSObject <WKURLSchemeHandler,WKScriptMessageHandler,WKNavigationDelegate>
|
||||||
|
|
||||||
@property (retain) WailsWindow* mainWindow;
|
@property (retain) WailsWindow* mainWindow;
|
||||||
@property (retain) WKWebView* webview;
|
@property (retain) WKWebView* webview;
|
||||||
|
@ -93,7 +93,7 @@
|
|||||||
if ( currentFrame.size.height > self.maxSize.height ) currentFrame.size.height = self.maxSize.height;
|
if ( currentFrame.size.height > self.maxSize.height ) currentFrame.size.height = self.maxSize.height;
|
||||||
if ( currentFrame.size.height < self.minSize.height ) currentFrame.size.height = self.minSize.height;
|
if ( currentFrame.size.height < self.minSize.height ) currentFrame.size.height = self.minSize.height;
|
||||||
|
|
||||||
[self.mainWindow setFrame:currentFrame display:TRUE animate:FALSE];
|
[self.mainWindow setFrame:currentFrame display:YES animate:FALSE];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,41 +135,46 @@
|
|||||||
|
|
||||||
self.urlRequests = [NSMutableDictionary new];
|
self.urlRequests = [NSMutableDictionary new];
|
||||||
|
|
||||||
NSWindowStyleMask styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
|
NSWindowStyleMask styleMask = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
|
||||||
|
|
||||||
if (frameless) {
|
if (frameless) {
|
||||||
styleMask = NSWindowStyleMaskBorderless;
|
styleMask = NSWindowStyleMaskBorderless;
|
||||||
|
titlebarAppearsTransparent = true;
|
||||||
|
hideTitle = true;
|
||||||
} else {
|
} else {
|
||||||
if (resizable) {
|
if (!hideTitleBar) {
|
||||||
styleMask |= NSWindowStyleMaskResizable;
|
styleMask |= NSWindowStyleMaskTitled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fullscreen) {
|
||||||
|
styleMask |= NSWindowStyleMaskFullScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fullSizeContent || frameless || titlebarAppearsTransparent ) {
|
||||||
|
styleMask |= NSWindowStyleMaskFullSizeContentView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fullscreen) {
|
|
||||||
styleMask |= NSWindowStyleMaskFullScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( fullSizeContent || frameless || titlebarAppearsTransparent ) {
|
if (resizable) {
|
||||||
styleMask |= NSWindowStyleMaskFullSizeContentView;
|
styleMask |= NSWindowStyleMaskResizable;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.mainWindow = [[[WailsWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height)
|
self.mainWindow = [[[WailsWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height)
|
||||||
styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]
|
styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]
|
||||||
autorelease];
|
autorelease];
|
||||||
|
|
||||||
if (frameless) {
|
if (!frameless && useToolbar) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useToolbar) {
|
|
||||||
id toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"];
|
id toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"];
|
||||||
[toolbar autorelease];
|
[toolbar autorelease];
|
||||||
[toolbar setShowsBaselineSeparator:!hideToolbarSeparator];
|
[toolbar setShowsBaselineSeparator:!hideToolbarSeparator];
|
||||||
[self.mainWindow setToolbar:toolbar];
|
[self.mainWindow setToolbar:toolbar];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[self.mainWindow setTitleVisibility:hideTitle];
|
[self.mainWindow setTitleVisibility:hideTitle];
|
||||||
[self.mainWindow setTitlebarAppearsTransparent:titlebarAppearsTransparent];
|
[self.mainWindow setTitlebarAppearsTransparent:titlebarAppearsTransparent];
|
||||||
[self.mainWindow canBecomeKeyWindow];
|
|
||||||
|
// [self.mainWindow canBecomeKeyWindow];
|
||||||
|
|
||||||
id contentView = [self.mainWindow contentView];
|
id contentView = [self.mainWindow contentView];
|
||||||
if (windowIsTranslucent) {
|
if (windowIsTranslucent) {
|
||||||
@ -203,7 +208,7 @@
|
|||||||
config.suppressesIncrementalRendering = true;
|
config.suppressesIncrementalRendering = true;
|
||||||
[config setURLSchemeHandler:self forURLScheme:@"wails"];
|
[config setURLSchemeHandler:self forURLScheme:@"wails"];
|
||||||
|
|
||||||
[config.preferences setValue:[NSNumber numberWithBool:true] forKey:@"developerExtrasEnabled"];
|
// [config.preferences setValue:[NSNumber numberWithBool:true] forKey:@"developerExtrasEnabled"];
|
||||||
|
|
||||||
WKUserContentController* userContentController = [WKUserContentController new];
|
WKUserContentController* userContentController = [WKUserContentController new];
|
||||||
[userContentController addScriptMessageHandler:self name:@"external"];
|
[userContentController addScriptMessageHandler:self name:@"external"];
|
||||||
@ -233,6 +238,8 @@
|
|||||||
[self.webview setValue:[NSNumber numberWithBool:!webviewIsTransparent] forKey:@"drawsBackground"];
|
[self.webview setValue:[NSNumber numberWithBool:!webviewIsTransparent] forKey:@"drawsBackground"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self.webview setNavigationDelegate:self];
|
||||||
|
|
||||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
[defaults setBool:FALSE forKey:@"NSAutomaticQuoteSubstitutionEnabled"];
|
[defaults setBool:FALSE forKey:@"NSAutomaticQuoteSubstitutionEnabled"];
|
||||||
|
|
||||||
@ -390,6 +397,10 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
|
||||||
|
processMessage("DomReady");
|
||||||
|
}
|
||||||
|
|
||||||
- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
|
- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
|
||||||
NSString *m = message.body;
|
NSString *m = message.body;
|
||||||
|
|
||||||
|
@ -60,7 +60,10 @@
|
|||||||
switch(role) {
|
switch(role) {
|
||||||
case AppMenu:
|
case AppMenu:
|
||||||
{
|
{
|
||||||
NSString *appName = [[NSProcessInfo processInfo] processName];
|
NSString *appName = [NSRunningApplication currentApplication].localizedName;
|
||||||
|
if( appName == nil ) {
|
||||||
|
appName = [[NSProcessInfo processInfo] processName];
|
||||||
|
}
|
||||||
WailsMenu *appMenu = [[WailsMenu new] initWithNSTitle:appName];
|
WailsMenu *appMenu = [[WailsMenu new] initWithNSTitle:appName];
|
||||||
id quitTitle = [@"Quit " stringByAppendingString:appName];
|
id quitTitle = [@"Quit " stringByAppendingString:appName];
|
||||||
NSMenuItem* quitMenuItem = [self newMenuItem:quitTitle :@selector(Quit) :@"q" :NSEventModifierFlagCommand];
|
NSMenuItem* quitMenuItem = [self newMenuItem:quitTitle :@selector(Quit) :@"q" :NSEventModifierFlagCommand];
|
||||||
|
@ -9,10 +9,11 @@
|
|||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#import "WindowDelegate.h"
|
#import "WindowDelegate.h"
|
||||||
#import "message.h"
|
#import "message.h"
|
||||||
|
#import "WailsContext.h"
|
||||||
|
|
||||||
@implementation WindowDelegate
|
@implementation WindowDelegate
|
||||||
|
|
||||||
- (BOOL)windowShouldClose:(NSWindow *)sender {
|
- (BOOL)windowShouldClose:(WailsWindow *)sender {
|
||||||
[sender orderOut:nil];
|
[sender orderOut:nil];
|
||||||
if( self.hideOnClose == false ) {
|
if( self.hideOnClose == false ) {
|
||||||
processMessage("Q");
|
processMessage("Q");
|
||||||
|
@ -214,6 +214,9 @@ func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
|
|||||||
|
|
||||||
func (f *Frontend) Quit() {
|
func (f *Frontend) Quit() {
|
||||||
f.mainWindow.Quit()
|
f.mainWindow.Quit()
|
||||||
|
if f.frontendOptions.OnShutdown != nil {
|
||||||
|
f.frontendOptions.OnShutdown(f.ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventNotify struct {
|
type EventNotify struct {
|
||||||
@ -235,6 +238,14 @@ func (f *Frontend) Notify(name string, data ...interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) processMessage(message string) {
|
func (f *Frontend) processMessage(message string) {
|
||||||
|
|
||||||
|
if message == "DomReady" {
|
||||||
|
if f.frontendOptions.OnDomReady != nil {
|
||||||
|
f.frontendOptions.OnDomReady(f.ctx)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
result, err := f.dispatcher.ProcessMessage(message, f)
|
result, err := f.dispatcher.ProcessMessage(message, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.logger.Error(err.Error())
|
f.logger.Error(err.Error())
|
||||||
|
@ -32,7 +32,7 @@ void processCallback(int callbackID) {
|
|||||||
void processURLRequest(void *ctx, const char* url) {
|
void processURLRequest(void *ctx, const char* url) {
|
||||||
NSLog(@"processURLRequest called");
|
NSLog(@"processURLRequest called");
|
||||||
const char myByteArray[] = { 0x3c,0x68,0x31,0x3e,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64,0x21,0x3c,0x2f,0x68,0x31,0x3e };
|
const char myByteArray[] = { 0x3c,0x68,0x31,0x3e,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64,0x21,0x3c,0x2f,0x68,0x31,0x3e };
|
||||||
ProcessURLResponse(ctx, url, "text/html", myByteArray, 21);
|
ProcessURLResponse(ctx, url, "text/html", (void*)myByteArray, 21);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char _Users_username_Pictures_SaltBae_png[] = {
|
unsigned char _Users_username_Pictures_SaltBae_png[] = {
|
||||||
@ -200,17 +200,17 @@ unsigned int _Users_username_Pictures_SaltBae_png_len = 1863;
|
|||||||
|
|
||||||
int main(int argc, const char * argv[]) {
|
int main(int argc, const char * argv[]) {
|
||||||
// insert code here...
|
// insert code here...
|
||||||
int frameless = 0;
|
int frameless = 1;
|
||||||
int resizable = 1;
|
int resizable = 0;
|
||||||
int fullscreen = 0;
|
int fullscreen = 0;
|
||||||
int fullSizeContent = 1;
|
int fullSizeContent = 1;
|
||||||
int hideTitleBar = 0;
|
int hideTitleBar = 0;
|
||||||
int titlebarAppearsTransparent = 1;
|
int titlebarAppearsTransparent = 0;
|
||||||
int hideTitle = 0;
|
int hideTitle = 0;
|
||||||
int useToolbar = 1;
|
int useToolbar = 0;
|
||||||
int hideToolbarSeparator = 1;
|
int hideToolbarSeparator = 0;
|
||||||
int webviewIsTransparent = 0;
|
int webviewIsTransparent = 1;
|
||||||
int alwaysOnTop = 1;
|
int alwaysOnTop = 0;
|
||||||
int hideWindowOnClose = 0;
|
int hideWindowOnClose = 0;
|
||||||
const char* appearance = "NSAppearanceNameDarkAqua";
|
const char* appearance = "NSAppearanceNameDarkAqua";
|
||||||
int windowIsTranslucent = 1;
|
int windowIsTranslucent = 1;
|
||||||
|
@ -130,5 +130,6 @@ func (f *Frontend) MenuSetApplicationMenu(menu *menu.Menu) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frontend) MenuUpdateApplicationMenu() {
|
func (f *Frontend) MenuUpdateApplicationMenu() {
|
||||||
//processMenu(f.mainWindow, f.mainWindow.applicationMenu)
|
f.MenuSetApplicationMenu(f.frontendOptions.Menu)
|
||||||
|
f.mainWindow.UpdateApplicationMenu()
|
||||||
}
|
}
|
||||||
|
@ -215,19 +215,12 @@ func (w *Window) Size() (int, int) {
|
|||||||
return parseIntDuo(temp)
|
return parseIntDuo(temp)
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (w *Window) parseMenu(inMenu *menu.Menu) {
|
|
||||||
// for index, item := range inMenu.Items {
|
|
||||||
// switch item.Type {
|
|
||||||
// case menu.TextType:
|
|
||||||
// // Create NSMenuItem
|
|
||||||
// // Append to NSMenu
|
|
||||||
// // Keep track of index
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (w *Window) SetApplicationMenu(inMenu *menu.Menu) {
|
func (w *Window) SetApplicationMenu(inMenu *menu.Menu) {
|
||||||
mainMenu := NewNSMenu(w.context, "")
|
mainMenu := NewNSMenu(w.context, "")
|
||||||
processMenu(mainMenu, inMenu)
|
processMenu(mainMenu, inMenu)
|
||||||
C.SetAsApplicationMenu(w.context, mainMenu.nsmenu)
|
C.SetAsApplicationMenu(w.context, mainMenu.nsmenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Window) UpdateApplicationMenu() {
|
||||||
|
C.UpdateApplicationMenu(w.context)
|
||||||
|
}
|
||||||
|
@ -35,7 +35,7 @@ func NewManager(ctx context.Context, cancel context.CancelFunc, bus *servicebus.
|
|||||||
|
|
||||||
result := &Manager{
|
result := &Manager{
|
||||||
bus: bus,
|
bus: bus,
|
||||||
logger: logger.CustomLogger("Event Manager"),
|
logger: logger.CustomLogger("Signal Manager"),
|
||||||
signalchannel: make(chan os.Signal, 2),
|
signalchannel: make(chan os.Signal, 2),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
@ -49,7 +49,7 @@ func NewManager(ctx context.Context, cancel context.CancelFunc, bus *servicebus.
|
|||||||
func (m *Manager) Start() {
|
func (m *Manager) Start() {
|
||||||
|
|
||||||
// Hook into interrupts
|
// Hook into interrupts
|
||||||
gosignal.Notify(m.signalchannel, os.Interrupt, syscall.SIGTERM)
|
gosignal.Notify(m.signalchannel, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
|
||||||
|
|
||||||
m.wg.Add(1)
|
m.wg.Add(1)
|
||||||
|
|
||||||
|
@ -2,10 +2,11 @@ package buildassets
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"github.com/leaanthony/debme"
|
|
||||||
"github.com/leaanthony/gosod"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/leaanthony/debme"
|
||||||
|
"github.com/leaanthony/gosod"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed build
|
//go:embed build
|
||||||
@ -50,3 +51,17 @@ func RegenerateAppIcon(target string) error {
|
|||||||
}
|
}
|
||||||
return a.CopyFile("appicon.png", target, 0644)
|
return a.CopyFile("appicon.png", target, 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RegeneratePlist(targetDir string, projectName string) error {
|
||||||
|
darwinAssets, err := debme.FS(assets, "build/darwin")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
templateDir := gosod.New(darwinAssets)
|
||||||
|
err = templateDir.Extract(targetDir, &assetData{Name: projectName})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -298,7 +298,7 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
|||||||
if v != "" {
|
if v != "" {
|
||||||
v += " "
|
v += " "
|
||||||
}
|
}
|
||||||
v += "-I" + buildBaseDir
|
v += "-mmacosx-version-min=10.13"
|
||||||
return v
|
return v
|
||||||
})
|
})
|
||||||
// Use upsertEnv so we don't overwrite user's CGO_CXXFLAGS
|
// Use upsertEnv so we don't overwrite user's CGO_CXXFLAGS
|
||||||
@ -313,6 +313,17 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
|||||||
cmd.Env = upsertEnv(cmd.Env, "CGO_ENABLED", func(v string) string {
|
cmd.Env = upsertEnv(cmd.Env, "CGO_ENABLED", func(v string) string {
|
||||||
return "1"
|
return "1"
|
||||||
})
|
})
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
// Set the minimum Mac SDK to 10.13
|
||||||
|
cmd.Env = upsertEnv(cmd.Env, "CGO_LDFLAGS", func(v string) string {
|
||||||
|
if v != "" {
|
||||||
|
v += " "
|
||||||
|
}
|
||||||
|
v += "-mmacosx-version-min=10.13"
|
||||||
|
|
||||||
|
return v
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Env = upsertEnv(cmd.Env, "GOOS", func(v string) string {
|
cmd.Env = upsertEnv(cmd.Env, "GOOS", func(v string) string {
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/internal/fs"
|
"github.com/wailsapp/wails/v2/internal/fs"
|
||||||
|
|
||||||
@ -209,6 +210,18 @@ func Build(options *Options) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return options.CompiledBinary, nil
|
result := options.CompiledBinary
|
||||||
|
|
||||||
|
if options.Pack && options.Platform == "darwin" {
|
||||||
|
sr := strings.Split(result, "/")
|
||||||
|
for i := len(sr) - 1; i >= 0; i-- {
|
||||||
|
if strings.Contains(sr[i], ".app") {
|
||||||
|
result = strings.Join(sr[:i+1], "/")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
package build
|
package build
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/leaanthony/winicon"
|
"github.com/leaanthony/winicon"
|
||||||
"github.com/tc-hib/winres"
|
"github.com/tc-hib/winres"
|
||||||
@ -113,7 +109,7 @@ func packageApplicationForDarwin(options *Options) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate Icons
|
// Generate Icons
|
||||||
err = processApplicationIcon(resourceDir, options.ProjectData.BuildDir)
|
err = processApplicationIcon(resourceDir, options.ProjectData.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -126,11 +122,11 @@ func packageApplicationForDarwin(options *Options) error {
|
|||||||
func processPList(options *Options, contentsDirectory string) error {
|
func processPList(options *Options, contentsDirectory string) error {
|
||||||
|
|
||||||
// Check if plist already exists in project dir
|
// Check if plist already exists in project dir
|
||||||
plistFile := filepath.Join(options.ProjectData.BuildDir, "darwin", "Info.plist")
|
plistFileDir := filepath.Join(options.ProjectData.Path, "build", "darwin")
|
||||||
|
plistFile := filepath.Join(plistFileDir, "Info.plist")
|
||||||
// If the file doesn't exist, generate it
|
// If the file doesn't exist, generate it
|
||||||
if !fs.FileExists(plistFile) {
|
if !fs.FileExists(plistFile) {
|
||||||
err := generateDefaultPlist(options, plistFile)
|
err := buildassets.RegeneratePlist(plistFileDir, options.ProjectData.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -141,65 +137,6 @@ func processPList(options *Options, contentsDirectory string) error {
|
|||||||
return fs.CopyFile(plistFile, targetFile)
|
return fs.CopyFile(plistFile, targetFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateDefaultPlist(options *Options, targetPlistFile string) error {
|
|
||||||
name := defaultString(options.ProjectData.Name, "WailsTest")
|
|
||||||
exe := defaultString(options.OutputFile, name)
|
|
||||||
version := "1.0.0"
|
|
||||||
author := defaultString(options.ProjectData.Author.Name, "Anonymous")
|
|
||||||
packageID := strings.Join([]string{"wails", name}, ".")
|
|
||||||
plistData := newPlistData(name, exe, packageID, version, author)
|
|
||||||
|
|
||||||
tmpl := template.New("infoPlist")
|
|
||||||
plistTemplate := fs.RelativePath("./internal/packager/darwin/Info.plist")
|
|
||||||
infoPlist, err := ioutil.ReadFile(plistTemplate)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "Cannot open plist template")
|
|
||||||
}
|
|
||||||
_, err = tmpl.Parse(string(infoPlist))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Write the template to a buffer
|
|
||||||
var tpl bytes.Buffer
|
|
||||||
err = tmpl.Execute(&tpl, plistData)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the directory if it doesn't exist
|
|
||||||
err = fs.MkDirs(filepath.Dir(targetPlistFile))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Save the file
|
|
||||||
return ioutil.WriteFile(targetPlistFile, tpl.Bytes(), 0644)
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultString(val string, defaultVal string) string {
|
|
||||||
if val != "" {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
return defaultVal
|
|
||||||
}
|
|
||||||
|
|
||||||
type plistData struct {
|
|
||||||
Title string
|
|
||||||
Exe string
|
|
||||||
PackageID string
|
|
||||||
Version string
|
|
||||||
Author string
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPlistData(title, exe, packageID, version, author string) *plistData {
|
|
||||||
return &plistData{
|
|
||||||
Title: title,
|
|
||||||
Exe: exe,
|
|
||||||
Version: version,
|
|
||||||
PackageID: packageID,
|
|
||||||
Author: author,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func processApplicationIcon(resourceDir string, iconsDir string) (err error) {
|
func processApplicationIcon(resourceDir string, iconsDir string) (err error) {
|
||||||
|
|
||||||
appIcon := filepath.Join(iconsDir, "appicon.png")
|
appIcon := filepath.Join(iconsDir, "appicon.png")
|
||||||
|
@ -2,6 +2,7 @@ package options
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Default options for creating the App
|
// Default options for creating the App
|
||||||
@ -11,3 +12,8 @@ var Default = &App{
|
|||||||
Logger: logger.NewDefaultLogger(),
|
Logger: logger.NewDefaultLogger(),
|
||||||
LogLevel: logger.INFO,
|
LogLevel: logger.INFO,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var defaultMacMenu = menu.NewMenuFromItems(
|
||||||
|
menu.AppMenu(),
|
||||||
|
menu.EditMenu(),
|
||||||
|
)
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"embed"
|
"embed"
|
||||||
"log"
|
"log"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||||||
@ -94,4 +95,11 @@ func MergeDefaults(appoptions *App) {
|
|||||||
appoptions.Height = appoptions.MaxHeight
|
appoptions.Height = appoptions.MaxHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
if appoptions.Menu == nil {
|
||||||
|
appoptions.Menu = defaultMacMenu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
161
website/blog/2021-11-06-v2-beta2-release-notes.mdx
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
---
|
||||||
|
slug: wails-v2-beta-for-mac
|
||||||
|
title: Wails v2 Beta for MacOS
|
||||||
|
authors: [leaanthony]
|
||||||
|
tags: [wails, v2]
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
<div class="text--center">
|
||||||
|
<img src="/img/wails-mac.png" width="60%" style={{"box-shadow": "rgb(255 255 255 / 20%) 0px 4px 8px 0px, rgb(104 104 104) 0px 6px 20px 0px"}}/>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
Today marks the first beta release of Wails v2 for Mac! It's taken quite a while to get to this point and I'm hoping
|
||||||
|
that today's release will give you something that's reasonably useful. There have been a number of twists and turns
|
||||||
|
to get to this point and I'm hoping, with your help, to iron out the crinkles and get the Mac port polished for the
|
||||||
|
final v2 release.
|
||||||
|
|
||||||
|
You mean this isn't ready for production? For your use case, it may well be ready, but there are still a number of
|
||||||
|
known issues so keep your eye on [this project board](https://github.com/wailsapp/wails/projects/7) and if you would
|
||||||
|
like to contribute, you'd be very welcome!
|
||||||
|
|
||||||
|
So what's new for Wails v2 for Mac vs v1? Hint: They're pretty similar to the Windows Beta :wink:
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
<div class="text--center">
|
||||||
|
<img src="/img/wails-menus-mac.png" width="80%" style={{"box-shadow": "rgb(255 255 255 / 20%) 0px 4px 8px 0px, rgb(104 104 104) 0px 6px 20px 0px"}}/>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
There were a lot of requests for native menu support. Wails has finally got you covered. Application menus are now available
|
||||||
|
and include support for most native menu features. This includes standard menu items, checkboxes, radio groups, submenus
|
||||||
|
and separators.
|
||||||
|
|
||||||
|
There were a huge number of requests in v1 for the ability to have greater control of the window itself.
|
||||||
|
I'm happy to announce that there's new runtime APIs specifically for this.
|
||||||
|
It's feature-rich and supports multi-monitor configurations. There is also an improved dialogs API: Now, you can have modern, native
|
||||||
|
dialogs with rich configuration to cater for all your dialog needs.
|
||||||
|
|
||||||
|
### Mac Specific Options
|
||||||
|
|
||||||
|
In addition to the normal application options, Wails v2 for Mac also brings some Mac extras:
|
||||||
|
|
||||||
|
- Make your window all funky and translucent, like all the pretty swift apps!
|
||||||
|
- Highly customisable titlebar
|
||||||
|
- We support the NSAppearance options for the application
|
||||||
|
- Simple config to auto-create an "About" menu
|
||||||
|
|
||||||
|
### No requirement to bundle assets
|
||||||
|
|
||||||
|
A huge pain-point of v1 was the need to condense your entire application down to single JS & CSS files. I'm happy to
|
||||||
|
announce that for v2, there is no requirement to bundle assets, in any way, shape or form. Want to load a local image? Use an
|
||||||
|
`<img>` tag with a local src path. Want to use a cool font? Copy it in and add the path to it in your CSS.
|
||||||
|
|
||||||
|
> Wow, that sounds like a webserver...
|
||||||
|
|
||||||
|
Yes, it works just like a webserver, except it isn't.
|
||||||
|
|
||||||
|
> So how do I include my assets?
|
||||||
|
|
||||||
|
You just pass a single `embed.FS` that contains all your assets into your application configuration.
|
||||||
|
They don't even need to be in the top directory - Wails will just work it out for you.
|
||||||
|
|
||||||
|
### New Development Experience
|
||||||
|
|
||||||
|
Now that assets don't need to be bundled, it's enabled a whole new development experience. The new `wails dev`
|
||||||
|
command will build and run your application, but instead of using the assets in the `embed.FS`, it loads them directly
|
||||||
|
from disk.
|
||||||
|
|
||||||
|
It also provides the additional features:
|
||||||
|
|
||||||
|
- Hot reload - Any changes to frontend assets will trigger and auto reload of the application frontend
|
||||||
|
- Auto rebuild - Any changes to your Go code will rebuild and relaunch your application
|
||||||
|
|
||||||
|
In addition to this, a webserver will start on port 34115. This will serve your application to any browser that
|
||||||
|
connects to it. All connected web browsers will respond to system events like hot reload on asset change.
|
||||||
|
|
||||||
|
In Go, we are used to dealing with structs in our applications. It's often useful to send structs to our frontend
|
||||||
|
and use them as state in our application. In v1, this was a very manual process and a bit of a burden on the
|
||||||
|
developer. I'm happy to announce that in v2, any application run in dev mode will automatically generate Typescript
|
||||||
|
models for all structs that are input or output parameters to bound methods. This enables seamless interchange of data
|
||||||
|
models between the two worlds.
|
||||||
|
|
||||||
|
In addition to this, another JS module is dynamically generated wrapping all your bound methods. This provides
|
||||||
|
JSDoc for your methods, providing code completion and hinting in your IDE. It's really cool when you get data models
|
||||||
|
auto-imported when hitting tab in an auto-generated module wrapping your Go code!
|
||||||
|
|
||||||
|
### Remote Templates
|
||||||
|
|
||||||
|
<div class="text--center">
|
||||||
|
<img src="/img/remote-mac.png" width="80%" style={{"box-shadow": "rgb(255 255 255 / 20%) 0px 4px 8px 0px, rgb(104 104 104) 0px 6px 20px 0px"}}/>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
Getting an application up and running quickly was always a key goal for the Wails project. When we launched, we tried
|
||||||
|
to cover a lot of the modern frameworks at the time: react, vue and angular. The world of frontend development is very
|
||||||
|
opinionated, fast moving and hard to keep on top of! As a result, we found our base templates getting out of date pretty
|
||||||
|
quickly and this caused a maintenance headache. It also meant that we didn't have cool modern templates for the latest
|
||||||
|
and greatest tech stacks.
|
||||||
|
|
||||||
|
With v2, I wanted to empower the community by giving you the ability to create and host templates yourselves, rather
|
||||||
|
than rely on the Wails project. So now you can create projects using community supported templates! I hope this will
|
||||||
|
inspire developers to create a vibrant ecosystem of project templates. I'm really quite excited about what our developer
|
||||||
|
community can create!
|
||||||
|
|
||||||
|
### Native M1 Support
|
||||||
|
|
||||||
|
Thanks to the amazing support of [Mat Ryer](https://github.com/matryer/), the Wails project now supports M1 native
|
||||||
|
builds:
|
||||||
|
|
||||||
|
<div class="text--center">
|
||||||
|
<img src="/img/build-darwin-arm.png" width="80%" style={{"box-shadow": "rgb(255 255 255 / 20%) 0px 4px 8px 0px, rgb(104 104 104) 0px 6px 20px 0px"}}/>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
You can also specify `darwin/amd64` as a target too:
|
||||||
|
|
||||||
|
<div class="text--center">
|
||||||
|
<img src="/img/build-darwin-amd.png" width="80%" style={{"box-shadow": "rgb(255 255 255 / 20%) 0px 4px 8px 0px, rgb(104 104 104) 0px 6px 20px 0px"}}/>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
Oh, I almost forgot.... you can also do `darwin/universal`.... :wink:
|
||||||
|
|
||||||
|
<div class="text--center">
|
||||||
|
<img src="/img/build-darwin-universal.png" width="80%" style={{"box-shadow": "rgb(255 255 255 / 20%) 0px 4px 8px 0px, rgb(104 104 104) 0px 6px 20px 0px"}}/>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
### Cross Compilation to Windows
|
||||||
|
|
||||||
|
Because Wails v2 for Windows is pure Go, you can target Windows builds without docker.
|
||||||
|
|
||||||
|
<div class="text--center">
|
||||||
|
<img src="/img/build-cross-windows.png" width="80%" style={{"box-shadow": "rgb(255 255 255 / 20%) 0px 4px 8px 0px, rgb(104 104 104) 0px 6px 20px 0px"}}/>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
### WKWebView Renderer
|
||||||
|
|
||||||
|
V1 relied on a (now deprecated) WebView component. V2 uses the most recent WKWebKit component so expect the latest and greatest from Apple.
|
||||||
|
|
||||||
|
### In Conclusion
|
||||||
|
|
||||||
|
As I'd said in the Windows release notes, Wails v2 represents a new foundation for the project.
|
||||||
|
The aim of this release is to get feedback on the new approach, and to iron out any bugs before a full release.
|
||||||
|
Your input would be most welcome! Please direct any feedback to the [v2 Beta](https://github.com/wailsapp/wails/discussions/828)
|
||||||
|
discussion board.
|
||||||
|
|
||||||
|
And finally, I'd like to give a special thank you to all the [project sponsors](/docs/credits#sponsors), including [JetBrains](https://www.jetbrains.com?from=Wails),
|
||||||
|
whose support drive the project in many ways behind the scenes.
|
||||||
|
|
||||||
|
I look forward to seeing what people build with Wails in this next exciting phase of the project!
|
||||||
|
|
||||||
|
Lea.
|
||||||
|
|
||||||
|
PS: Linux users, you're next!
|
||||||
|
|
||||||
|
PPS: If you or your company find Wails useful, please consider [sponsoring the project](https://github.com/sponsors/leaanthony). Thanks!
|
@ -7,8 +7,9 @@ sidebar_position: 1
|
|||||||
## Supported Platforms
|
## Supported Platforms
|
||||||
|
|
||||||
- Windows 10
|
- Windows 10
|
||||||
- MacOS x64 & arm64 (due October '21)
|
- MacOS 10.13+ (amd64)
|
||||||
- Linux (due December '21)
|
- MacOS 11.0+ (arm64)
|
||||||
|
- Linux (due Jan '22)
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
@ -47,7 +48,11 @@ import TabItem from "@theme/TabItem";
|
|||||||
{ label: "Linux", value: "Linux" },
|
{ label: "Linux", value: "Linux" },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<TabItem value="MacOS">Coming Soon...</TabItem>
|
<TabItem value="MacOS">
|
||||||
|
Wails requires that the xcode command line tools are installed. This can be done by running:<br/>
|
||||||
|
|
||||||
|
<code>xcode-select --install</code>
|
||||||
|
</TabItem>
|
||||||
<TabItem value="Windows">
|
<TabItem value="Windows">
|
||||||
Wails requires that the <a href="https://developer.microsoft.com/en-us/microsoft-edge/webview2/">WebView2</a>{" "}
|
Wails requires that the <a href="https://developer.microsoft.com/en-us/microsoft-edge/webview2/">WebView2</a>{" "}
|
||||||
runtime is installed. Some Windows installations will already have this installed. You can check using the{" "}
|
runtime is installed. Some Windows installations will already have this installed. You can check using the{" "}
|
||||||
|
@ -199,7 +199,7 @@ The format of the file is slightly different. Here is a comparison:
|
|||||||
| frontend / serve | | Removed |
|
| frontend / serve | | Removed |
|
||||||
| tags | | Removed |
|
| tags | | Removed |
|
||||||
| | wailsjsdir | The directory to generate wailsjs modules |
|
| | wailsjsdir | The directory to generate wailsjs modules |
|
||||||
| | assetdir | The directory of the frontend assets for `dev` mode |
|
| | assetdir | The directory of the compiled frontend assets for `dev` mode |
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -74,6 +74,12 @@ Example:
|
|||||||
|
|
||||||
`wails build -clean -o myproject.exe`
|
`wails build -clean -o myproject.exe`
|
||||||
|
|
||||||
|
:::info UPX on Apple Silicon
|
||||||
|
|
||||||
|
There are [issues](https://github.com/upx/upx/issues/446) with using UPX with Apple Silicon.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
## doctor
|
## doctor
|
||||||
|
|
||||||
`wails doctor` will run diagnostics to ensure that your system is ready for development.
|
`wails doctor` will run diagnostics to ensure that your system is ready for development.
|
||||||
@ -135,6 +141,7 @@ Your system is ready for Wails development!
|
|||||||
| -debounce | The time to wait for reload after an asset change is detected | 100 (milliseconds) |
|
| -debounce | The time to wait for reload after an asset change is detected | 100 (milliseconds) |
|
||||||
| -devserverurl "url" | Use 3rd party dev server url, EG Vite | "http://localhost:34115" |
|
| -devserverurl "url" | Use 3rd party dev server url, EG Vite | "http://localhost:34115" |
|
||||||
| -appargs "args" | Arguments passed to the application in shell style | |
|
| -appargs "args" | Arguments passed to the application in shell style | |
|
||||||
|
| -platform "platform" | Platform/Arch to target | `runtime.GOOS` |
|
||||||
|
|
||||||
If the `assetdir`, `wailsjsdir`, `debounce` or `devserverurl` flags are provided on the command line, they are saved in
|
If the `assetdir`, `wailsjsdir`, `debounce` or `devserverurl` flags are provided on the command line, they are saved in
|
||||||
`wails.json`, and become the defaults for subsequent invocations.
|
`wails.json`, and become the defaults for subsequent invocations.
|
||||||
|
@ -5,7 +5,7 @@ sidebar_position: 4
|
|||||||
# Menus
|
# Menus
|
||||||
|
|
||||||
It is possible to add an application menu to Wails projects. This is achieved by defining a [Menu](#menu) struct and
|
It is possible to add an application menu to Wails projects. This is achieved by defining a [Menu](#menu) struct and
|
||||||
calling the runtime method [MenuSetApplicationMenu](/docs/reference/runtime/menu#menusetapplicationmenu).
|
setting the [`Menu`](/docs/reference/options#menu) option, or by calling the runtime method [MenuSetApplicationMenu](/docs/reference/runtime/menu#menusetapplicationmenu).
|
||||||
|
|
||||||
It is also possible to dynamically update the menu, by updating the menu struct and calling
|
It is also possible to dynamically update the menu, by updating the menu struct and calling
|
||||||
[MenuUpdateApplicationMenu](/docs/reference/runtime/menu#menuupdateapplicationmenu).
|
[MenuUpdateApplicationMenu](/docs/reference/runtime/menu#menuupdateapplicationmenu).
|
||||||
@ -79,6 +79,7 @@ type MenuItem struct {
|
|||||||
| Checked | bool | Adds check to item (Checkbox & Radio types) |
|
| Checked | bool | Adds check to item (Checkbox & Radio types) |
|
||||||
| SubMenu | [\*Menu](#menu) | Sets the submenu |
|
| SubMenu | [\*Menu](#menu) | Sets the submenu |
|
||||||
| Click | [Callback](#callback) | Callback function when menu clicked |
|
| Click | [Callback](#callback) | Callback function when menu clicked |
|
||||||
|
| Role | string | Defines a [role](#roles) for this menu item. Mac only for now. |
|
||||||
|
|
||||||
### Accelerator
|
### Accelerator
|
||||||
|
|
||||||
@ -231,3 +232,19 @@ type CallbackData struct {
|
|||||||
|
|
||||||
The function is given a `CallbackData` struct which indicates which menu item triggered the callback. This is useful when
|
The function is given a `CallbackData` struct which indicates which menu item triggered the callback. This is useful when
|
||||||
using radio groups that may share a callback.
|
using radio groups that may share a callback.
|
||||||
|
|
||||||
|
### Role
|
||||||
|
|
||||||
|
:::info Roles
|
||||||
|
|
||||||
|
Roles are currently supported on Mac only.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
A menu item may have a role, which is essentially a pre-defined menu item. We currently support the following roles:
|
||||||
|
|
||||||
|
| Role | Description |
|
||||||
|
| ---- | ----------- |
|
||||||
|
| AppMenuRole | The standard Mac application menu. Can be created using `menu.AppMenu()` |
|
||||||
|
| EditMenuRole | The standard Mac edit menu. Can be created using `menu.EditMenu()` |
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ func main() {
|
|||||||
StartHidden: false,
|
StartHidden: false,
|
||||||
HideWindowOnClose: false,
|
HideWindowOnClose: false,
|
||||||
RGBA: &options.RGBA{R: 0, G: 0, B: 0, A: 255},
|
RGBA: &options.RGBA{R: 0, G: 0, B: 0, A: 255},
|
||||||
|
AlwaysOnTop: false,
|
||||||
Assets: assets,
|
Assets: assets,
|
||||||
Menu: app.applicationMenu(),
|
Menu: app.applicationMenu(),
|
||||||
Logger: nil,
|
Logger: nil,
|
||||||
@ -43,6 +44,24 @@ func main() {
|
|||||||
WindowIsTranslucent: false,
|
WindowIsTranslucent: false,
|
||||||
DisableWindowIcon: false,
|
DisableWindowIcon: false,
|
||||||
},
|
},
|
||||||
|
Mac: &mac.Options{
|
||||||
|
TitleBar: &mac.TitleBar{
|
||||||
|
TitlebarAppearsTransparent: true,
|
||||||
|
HideTitle: false,
|
||||||
|
HideTitleBar: false,
|
||||||
|
FullSizeContent: false,
|
||||||
|
UseToolbar: false,
|
||||||
|
HideToolbarSeparator: true,
|
||||||
|
},
|
||||||
|
Appearance: mac.NSAppearanceNameDarkAqua,
|
||||||
|
WebviewIsTransparent: true,
|
||||||
|
WindowIsTranslucent: false,
|
||||||
|
About: &mac.AboutInfo{
|
||||||
|
Title: "My Application",
|
||||||
|
Message: "© 2021 Me",
|
||||||
|
Icon: icon,
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -192,6 +211,8 @@ Type: \*menu.Menu
|
|||||||
|
|
||||||
The menu to be used by the application. More details about Menus in the [Menu Reference](/docs/reference/runtime/menu).
|
The menu to be used by the application. More details about Menus in the [Menu Reference](/docs/reference/runtime/menu).
|
||||||
|
|
||||||
|
NOTE: On Mac, if no menu is specified, a default menu will be created.
|
||||||
|
|
||||||
### Logger
|
### Logger
|
||||||
|
|
||||||
Name: Logger
|
Name: Logger
|
||||||
@ -281,3 +302,153 @@ Name: DisableWindowIcon
|
|||||||
Type: bool
|
Type: bool
|
||||||
|
|
||||||
Setting this to true will remove the icon in the top left corner of the title bar.
|
Setting this to true will remove the icon in the top left corner of the title bar.
|
||||||
|
|
||||||
|
|
||||||
|
## Mac Specific Options
|
||||||
|
|
||||||
|
### TitleBar
|
||||||
|
|
||||||
|
Name: TitleBar
|
||||||
|
|
||||||
|
Type: [*mac.TitleBar](#titlebar-struct)
|
||||||
|
|
||||||
|
The TitleBar struct provides the ability to configure the look and feel of the title bar.
|
||||||
|
|
||||||
|
### Appearance
|
||||||
|
|
||||||
|
Name: Appearance
|
||||||
|
|
||||||
|
Type: [AppearanceType](#appearance-type)
|
||||||
|
|
||||||
|
Appearance is used to set the style of your app in accordance with Apple's [NSAppearance](https://developer.apple.com/documentation/appkit/nsappearancename?language=objc) names.
|
||||||
|
|
||||||
|
### WebviewIsTransparent
|
||||||
|
|
||||||
|
Name: WebviewIsTransparent
|
||||||
|
|
||||||
|
Type: bool
|
||||||
|
|
||||||
|
Setting this to `true` will make the webview background transparent when an alpha value of `0` is used.
|
||||||
|
This means that if you use `rgba(0,0,0,0)`, the host window will show through.
|
||||||
|
Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications.
|
||||||
|
|
||||||
|
### WindowIsTranslucent
|
||||||
|
|
||||||
|
Name: WindowIsTranslucent
|
||||||
|
|
||||||
|
Type: bool
|
||||||
|
|
||||||
|
Setting this to `true` will make the window background translucent. Often combined
|
||||||
|
with [WebviewIsTransparent](#WebviewIsTransparent) to make frosty-looking applications.
|
||||||
|
|
||||||
|
### About
|
||||||
|
|
||||||
|
Name: About
|
||||||
|
|
||||||
|
Type: [About](#about-struct)
|
||||||
|
|
||||||
|
This configuration lets you set the title, message and icon for the "About" menu item in the app menu created by the "AppMenu" role.
|
||||||
|
|
||||||
|
#### Titlebar struct
|
||||||
|
|
||||||
|
The titlebar of the application can be customised by using the TitleBar options:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type TitleBar struct {
|
||||||
|
TitlebarAppearsTransparent bool
|
||||||
|
HideTitle bool
|
||||||
|
HideTitleBar bool
|
||||||
|
FullSizeContent bool
|
||||||
|
UseToolbar bool
|
||||||
|
HideToolbarSeparator bool
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| ---- | ----------- |
|
||||||
|
| TitlebarAppearsTransparent | Makes the titlebar transparent. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindow/1419167-titlebarappearstransparent?language=objc) |
|
||||||
|
| HideTitle | Hides the title of the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowtitlevisibility?language=objc) |
|
||||||
|
| HideTitleBar | Removes [NSWindowStyleMaskTitled](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemasktitled/) from the style mask |
|
||||||
|
| FullSizeContent | Makes the webview fill the entire window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemaskfullsizecontentview)|
|
||||||
|
| UseToolbar | Adds a default toolbar to the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nstoolbar?language=objc) |
|
||||||
|
| HideToolbarSeparator | Removes the line beneath the toolbar. [Apple Docs](https://developer.apple.com/documentation/appkit/nstoolbar/1516954-showsbaselineseparator?language=objc) |
|
||||||
|
|
||||||
|
Preconfigured titlebar settings are available:
|
||||||
|
|
||||||
|
| Setting | Example |
|
||||||
|
| ------- | ------- |
|
||||||
|
|`mac.TitleBarDefault()` |  |
|
||||||
|
|`mac.TitleBarHidden()` |  |
|
||||||
|
|`mac.TitleBarHiddenInset()` |  |
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```go
|
||||||
|
Mac: &mac.Options{
|
||||||
|
TitleBar: mac.TitleBarHiddenInset(),
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Click [here](https://github.com/lukakerr/NSWindowStyles) for some inspiration on customising the titlebar.
|
||||||
|
|
||||||
|
#### Appearance type
|
||||||
|
|
||||||
|
You can specify the application's [appearance](https://developer.apple.com/documentation/appkit/nsappearance?language=objc).
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
| --------------- | ------------------ |
|
||||||
|
| DefaultAppearance | DefaultAppearance uses the default system value |
|
||||||
|
| NSAppearanceNameAqua | The standard light system appearance |
|
||||||
|
| NSAppearanceNameDarkAqua | The standard dark system appearance |
|
||||||
|
| NSAppearanceNameVibrantLight | The light vibrant appearance |
|
||||||
|
| NSAppearanceNameAccessibilityHighContrastAqua | A high-contrast version of the standard light system appearance |
|
||||||
|
| NSAppearanceNameAccessibilityHighContrastDarkAqua | A high-contrast version of the standard dark system appearance |
|
||||||
|
| NSAppearanceNameAccessibilityHighContrastVibrantLight | A high-contrast version of the light vibrant appearance |
|
||||||
|
| NSAppearanceNameAccessibilityHighContrastVibrantDark | A high-contrast version of the dark vibrant appearance |
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```go
|
||||||
|
Mac: &mac.Options{
|
||||||
|
Appearance: mac.NSAppearanceNameDarkAqua,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### About struct
|
||||||
|
|
||||||
|
```go
|
||||||
|
type AboutInfo struct {
|
||||||
|
Title string
|
||||||
|
Message string
|
||||||
|
Icon []byte
|
||||||
|
}
|
||||||
|
```
|
||||||
|
If these settings are provided, an "About" menu item will appear in the app menu (when using the `AppMenu` role).
|
||||||
|
Given this configuration:
|
||||||
|
```go
|
||||||
|
//go:embed build/appicon.png
|
||||||
|
var icon []byte
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := wails.Run(&options.App{
|
||||||
|
...
|
||||||
|
Mac: &mac.Options{
|
||||||
|
About: &mac.AboutInfo{
|
||||||
|
Title: "My Application",
|
||||||
|
Message: "© 2021 Me",
|
||||||
|
Icon: icon,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
The "About" menu item will appear in the app menu:
|
||||||
|
|
||||||
|
<div class="text--center">
|
||||||
|
<img src="/img/reference/about-menu.png" style={{"box-shadow": "rgb(255 255 255 / 20%) 0px 4px 8px 0px, rgb(104 104 104) 0px 6px 20px 0px"}}/>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
When clicked, that will open an about message box:
|
||||||
|
|
||||||
|
<div class="text--center">
|
||||||
|
<img src="/img/reference/about-dialog.png" width="40%" style={{"box-shadow": "rgb(255 255 255 / 20%) 0px 4px 8px 0px, rgb(104 104 104) 0px 6px 20px 0px"}}/>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
@ -9,7 +9,7 @@ The project config resides in the `wails.json` file in the project directory. Th
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "[The project name]",
|
"name": "[The project name]",
|
||||||
"assetdir": "[Relative path to your assets directory]",
|
"assetdir": "[Relative path to the directory containing the compiled assets]",
|
||||||
"frontend:install": "[The command to install node dependencies, run in the frontend directory - often `npm install`]",
|
"frontend:install": "[The command to install node dependencies, run in the frontend directory - often `npm install`]",
|
||||||
"frontend:build": "[The command to build the assets, run in the frontend directory - often `npm run build`]",
|
"frontend:build": "[The command to build the assets, run in the frontend directory - often `npm run build`]",
|
||||||
"frontend:dev": "[This command is run in a separate process on `wails dev`. Useful for 3rd party watchers]",
|
"frontend:dev": "[This command is run in a separate process on `wails dev`. Useful for 3rd party watchers]",
|
||||||
|
@ -63,7 +63,7 @@ const darkCodeTheme = require('prism-react-renderer/themes/palenight');
|
|||||||
({
|
({
|
||||||
announcementBar: {
|
announcementBar: {
|
||||||
id: 'beta-message',
|
id: 'beta-message',
|
||||||
content: 'Wails v2 is currently Beta for Windows. Mac & Linux in progress.',
|
content: 'Wails v2 is currently Beta for Windows & Mac. Linux in progress.',
|
||||||
backgroundColor: '#b00',
|
backgroundColor: '#b00',
|
||||||
textColor: '#FFF',
|
textColor: '#FFF',
|
||||||
isCloseable: false,
|
isCloseable: false,
|
||||||
|
BIN
website/static/img/build-cross-windows.png
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
website/static/img/build-darwin-amd.png
Normal file
After Width: | Height: | Size: 128 KiB |
BIN
website/static/img/build-darwin-arm.png
Normal file
After Width: | Height: | Size: 126 KiB |
BIN
website/static/img/build-darwin-universal.png
Normal file
After Width: | Height: | Size: 151 KiB |
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
<svg width="50%" height="50%" viewBox="0 0 150 124" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
<svg width="50%" height="50%" viewBox="0 0 150 150" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
<g transform="matrix(1.2207,0,0,1.21688,0,0)">
|
<g transform="matrix(1.2207,0,0,1.21688,0,0)">
|
||||||
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
<svg width="50%" height="50%" viewBox="0 0 150 125" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
<svg width="50%" height="50%" viewBox="0 0 150 150" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
<g transform="matrix(1.2207,0,0,1.21688,0,0)">
|
<g transform="matrix(1.2207,0,0,1.21688,0,0)">
|
||||||
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
BIN
website/static/img/reference/about-dialog.png
Normal file
After Width: | Height: | Size: 155 KiB |
BIN
website/static/img/reference/about-menu.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
website/static/img/reference/titlebar-default.png
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
website/static/img/reference/titlebar-hidden-inset.png
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
website/static/img/reference/titlebar-hidden.png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
website/static/img/remote-mac.png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
website/static/img/wails-mac.png
Normal file
After Width: | Height: | Size: 514 KiB |
BIN
website/static/img/wails-menus-mac.png
Normal file
After Width: | Height: | Size: 1.5 MiB |