@ -29,7 +29,7 @@
|
||||
|
||||
- [1. Internationalization](#nav-1)
|
||||
- [2. Table of Contents](#nav-2)
|
||||
- [3. Introductions](#nav-3)
|
||||
- [3. Introduction](#nav-3)
|
||||
- [3.1 Official Website](#nav-3-1)
|
||||
- [4. Features](#nav-4)
|
||||
- [5. Sponsors](#nav-5)
|
||||
|
@ -5,11 +5,15 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"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/leaanthony/clir"
|
||||
@ -129,8 +133,8 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
}
|
||||
}
|
||||
|
||||
if runtime.GOOS == "darwin" && !experimental {
|
||||
return fmt.Errorf("MacOS version coming soon!")
|
||||
if runtime.GOOS == "linux" && !experimental {
|
||||
return fmt.Errorf("Linux version coming soon!")
|
||||
}
|
||||
|
||||
// Webview2 installer strategy (download by default)
|
||||
@ -205,6 +209,11 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
fmt.Fprintf(w, "\n")
|
||||
w.Flush()
|
||||
|
||||
err = checkGoModVersion(logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return doBuild(buildOptions)
|
||||
})
|
||||
}
|
||||
@ -228,3 +237,29 @@ func doBuild(buildOptions *build.Options) error {
|
||||
|
||||
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 {
|
||||
return fmt.Errorf("MacOS version coming soon!")
|
||||
if runtime.GOOS == "linux" && !experimental {
|
||||
return fmt.Errorf("Linux version coming soon!")
|
||||
}
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
|
@ -2,7 +2,7 @@
|
||||
html {
|
||||
text-align: center;
|
||||
color: white;
|
||||
background-color: rgba(0, 0, 0, 255);
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"embed"
|
||||
"log"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
@ -13,6 +15,9 @@ import (
|
||||
//go:embed frontend/dist
|
||||
var assets embed.FS
|
||||
|
||||
//go:embed build/appicon.png
|
||||
var icon []byte
|
||||
|
||||
func main() {
|
||||
// Create an instance of the app structure
|
||||
app := NewApp()
|
||||
@ -31,7 +36,7 @@ func main() {
|
||||
Frameless: false,
|
||||
StartHidden: 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,
|
||||
LogLevel: logger.DEBUG,
|
||||
OnStartup: app.startup,
|
||||
@ -46,6 +51,17 @@ func main() {
|
||||
WindowIsTranslucent: 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 {
|
||||
|
@ -1,5 +1,5 @@
|
||||
html {
|
||||
background-color: rgba(33, 37, 43, 1);
|
||||
background-color: rgba(33, 37, 43, 0);
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"embed"
|
||||
"log"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
@ -13,6 +15,9 @@ import (
|
||||
//go:embed frontend/src
|
||||
var assets embed.FS
|
||||
|
||||
//go:embed build/appicon.png
|
||||
var icon []byte
|
||||
|
||||
func main() {
|
||||
// Create an instance of the app structure
|
||||
app := NewApp()
|
||||
@ -31,7 +36,7 @@ func main() {
|
||||
Frameless: false,
|
||||
StartHidden: 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,
|
||||
LogLevel: logger.DEBUG,
|
||||
OnStartup: app.startup,
|
||||
@ -46,6 +51,16 @@ func main() {
|
||||
WindowIsTranslucent: 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 {
|
||||
|
@ -13,6 +13,7 @@ require (
|
||||
github.com/gofiber/fiber/v2 v2.17.0
|
||||
github.com/gofiber/websocket/v2 v2.0.8
|
||||
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/gorilla/websocket v1.4.1
|
||||
github.com/imdario/mergo v0.3.12
|
||||
@ -56,11 +57,11 @@ require (
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.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/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // 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/mattn/go-runewidth v0.0.7 // 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/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.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
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/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
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/go.mod h1:lHhJedqxCoHN+zMtwGNTXWmF0u9Jt363FYRhV6g0CdY=
|
||||
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/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
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-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/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/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
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/menumanager"
|
||||
"github.com/wailsapp/wails/v2/internal/project"
|
||||
"github.com/wailsapp/wails/v2/internal/signal"
|
||||
pkglogger "github.com/wailsapp/wails/v2/pkg/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
)
|
||||
@ -27,7 +26,6 @@ import (
|
||||
type App struct {
|
||||
frontend frontend.Frontend
|
||||
logger *logger.Logger
|
||||
signal *signal.Manager
|
||||
options *options.App
|
||||
|
||||
menuManager *menumanager.Manager
|
||||
|
@ -5,6 +5,7 @@ package appng
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"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/logger"
|
||||
"github.com/wailsapp/wails/v2/internal/menumanager"
|
||||
"github.com/wailsapp/wails/v2/internal/signal"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
)
|
||||
|
||||
@ -20,7 +20,6 @@ import (
|
||||
type App struct {
|
||||
frontend frontend.Frontend
|
||||
logger *logger.Logger
|
||||
signal *signal.Manager
|
||||
options *options.App
|
||||
|
||||
menuManager *menumanager.Manager
|
||||
@ -36,9 +35,6 @@ type App struct {
|
||||
|
||||
func (a *App) Run() error {
|
||||
err := a.frontend.Run(a.ctx)
|
||||
if a.shutdownCallback != nil {
|
||||
a.shutdownCallback(a.ctx)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,12 @@
|
||||
#define AppDelegate_h
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "WailsContext.h"
|
||||
|
||||
@interface AppDelegate : NSResponder <NSTouchBarProvider>
|
||||
|
||||
@property bool alwaysOnTop;
|
||||
@property (retain) NSWindow* mainWindow;
|
||||
@property (retain) WailsWindow* mainWindow;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -49,6 +49,7 @@ void* NewMenu(const char* name);
|
||||
void AppendSubmenu(void* parent, void* child);
|
||||
void AppendRole(void *inctx, void *inMenu, int role);
|
||||
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* 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) {
|
||||
|
||||
[NSApplication sharedApplication];
|
||||
|
||||
WailsContext *result = [WailsContext new];
|
||||
|
||||
result.debug = debug;
|
||||
@ -256,6 +258,14 @@ void SetAsApplicationMenu(void *inctx, void *inMenu) {
|
||||
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) {
|
||||
WailsContext *ctx = (__bridge WailsContext*) inctx;
|
||||
NSString *_title = safeInit(title);
|
||||
|
@ -13,14 +13,12 @@
|
||||
|
||||
#define ON_MAIN_THREAD(str) dispatch_async(dispatch_get_main_queue(), ^{ str; });
|
||||
#define unicode(input) [NSString stringWithFormat:@"%C", input]
|
||||
#define STREQ(a,b) strcmp(a, b) == 0
|
||||
|
||||
|
||||
@interface WailsWindow : NSWindow
|
||||
- (BOOL)canBecomeKeyWindow;
|
||||
@end
|
||||
|
||||
@interface WailsContext : NSObject <WKURLSchemeHandler,WKScriptMessageHandler>
|
||||
@interface WailsContext : NSObject <WKURLSchemeHandler,WKScriptMessageHandler,WKNavigationDelegate>
|
||||
|
||||
@property (retain) WailsWindow* mainWindow;
|
||||
@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.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];
|
||||
|
||||
NSWindowStyleMask styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
|
||||
NSWindowStyleMask styleMask = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
|
||||
|
||||
if (frameless) {
|
||||
styleMask = NSWindowStyleMaskBorderless;
|
||||
titlebarAppearsTransparent = true;
|
||||
hideTitle = true;
|
||||
} else {
|
||||
if (resizable) {
|
||||
styleMask |= NSWindowStyleMaskResizable;
|
||||
if (!hideTitleBar) {
|
||||
styleMask |= NSWindowStyleMaskTitled;
|
||||
}
|
||||
|
||||
if (fullscreen) {
|
||||
styleMask |= NSWindowStyleMaskFullScreen;
|
||||
}
|
||||
|
||||
if( fullSizeContent || frameless || titlebarAppearsTransparent ) {
|
||||
styleMask |= NSWindowStyleMaskFullSizeContentView;
|
||||
}
|
||||
}
|
||||
if (fullscreen) {
|
||||
styleMask |= NSWindowStyleMaskFullScreen;
|
||||
}
|
||||
|
||||
if( fullSizeContent || frameless || titlebarAppearsTransparent ) {
|
||||
styleMask |= NSWindowStyleMaskFullSizeContentView;
|
||||
if (resizable) {
|
||||
styleMask |= NSWindowStyleMaskResizable;
|
||||
}
|
||||
|
||||
self.mainWindow = [[[WailsWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height)
|
||||
styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]
|
||||
autorelease];
|
||||
|
||||
if (frameless) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (useToolbar) {
|
||||
|
||||
if (!frameless && useToolbar) {
|
||||
id toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"];
|
||||
[toolbar autorelease];
|
||||
[toolbar setShowsBaselineSeparator:!hideToolbarSeparator];
|
||||
[self.mainWindow setToolbar:toolbar];
|
||||
|
||||
}
|
||||
|
||||
[self.mainWindow setTitleVisibility:hideTitle];
|
||||
[self.mainWindow setTitlebarAppearsTransparent:titlebarAppearsTransparent];
|
||||
[self.mainWindow canBecomeKeyWindow];
|
||||
|
||||
// [self.mainWindow canBecomeKeyWindow];
|
||||
|
||||
id contentView = [self.mainWindow contentView];
|
||||
if (windowIsTranslucent) {
|
||||
@ -203,7 +208,7 @@
|
||||
config.suppressesIncrementalRendering = true;
|
||||
[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];
|
||||
[userContentController addScriptMessageHandler:self name:@"external"];
|
||||
@ -233,6 +238,8 @@
|
||||
[self.webview setValue:[NSNumber numberWithBool:!webviewIsTransparent] forKey:@"drawsBackground"];
|
||||
}
|
||||
|
||||
[self.webview setNavigationDelegate:self];
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[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 {
|
||||
NSString *m = message.body;
|
||||
|
||||
|
@ -60,7 +60,10 @@
|
||||
switch(role) {
|
||||
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];
|
||||
id quitTitle = [@"Quit " stringByAppendingString:appName];
|
||||
NSMenuItem* quitMenuItem = [self newMenuItem:quitTitle :@selector(Quit) :@"q" :NSEventModifierFlagCommand];
|
||||
|
@ -9,10 +9,11 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "WindowDelegate.h"
|
||||
#import "message.h"
|
||||
#import "WailsContext.h"
|
||||
|
||||
@implementation WindowDelegate
|
||||
|
||||
- (BOOL)windowShouldClose:(NSWindow *)sender {
|
||||
- (BOOL)windowShouldClose:(WailsWindow *)sender {
|
||||
[sender orderOut:nil];
|
||||
if( self.hideOnClose == false ) {
|
||||
processMessage("Q");
|
||||
|
@ -214,6 +214,9 @@ func (f *Frontend) WindowSetRGBA(col *options.RGBA) {
|
||||
|
||||
func (f *Frontend) Quit() {
|
||||
f.mainWindow.Quit()
|
||||
if f.frontendOptions.OnShutdown != nil {
|
||||
f.frontendOptions.OnShutdown(f.ctx)
|
||||
}
|
||||
}
|
||||
|
||||
type EventNotify struct {
|
||||
@ -235,6 +238,14 @@ func (f *Frontend) Notify(name string, data ...interface{}) {
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
f.logger.Error(err.Error())
|
||||
|
@ -32,7 +32,7 @@ void processCallback(int callbackID) {
|
||||
void processURLRequest(void *ctx, const char* url) {
|
||||
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 };
|
||||
ProcessURLResponse(ctx, url, "text/html", myByteArray, 21);
|
||||
ProcessURLResponse(ctx, url, "text/html", (void*)myByteArray, 21);
|
||||
}
|
||||
|
||||
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[]) {
|
||||
// insert code here...
|
||||
int frameless = 0;
|
||||
int resizable = 1;
|
||||
int frameless = 1;
|
||||
int resizable = 0;
|
||||
int fullscreen = 0;
|
||||
int fullSizeContent = 1;
|
||||
int hideTitleBar = 0;
|
||||
int titlebarAppearsTransparent = 1;
|
||||
int titlebarAppearsTransparent = 0;
|
||||
int hideTitle = 0;
|
||||
int useToolbar = 1;
|
||||
int hideToolbarSeparator = 1;
|
||||
int webviewIsTransparent = 0;
|
||||
int alwaysOnTop = 1;
|
||||
int useToolbar = 0;
|
||||
int hideToolbarSeparator = 0;
|
||||
int webviewIsTransparent = 1;
|
||||
int alwaysOnTop = 0;
|
||||
int hideWindowOnClose = 0;
|
||||
const char* appearance = "NSAppearanceNameDarkAqua";
|
||||
int windowIsTranslucent = 1;
|
||||
|
@ -130,5 +130,6 @@ func (f *Frontend) MenuSetApplicationMenu(menu *menu.Menu) {
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
//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) {
|
||||
mainMenu := NewNSMenu(w.context, "")
|
||||
processMenu(mainMenu, inMenu)
|
||||
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{
|
||||
bus: bus,
|
||||
logger: logger.CustomLogger("Event Manager"),
|
||||
logger: logger.CustomLogger("Signal Manager"),
|
||||
signalchannel: make(chan os.Signal, 2),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
@ -49,7 +49,7 @@ func NewManager(ctx context.Context, cancel context.CancelFunc, bus *servicebus.
|
||||
func (m *Manager) Start() {
|
||||
|
||||
// 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)
|
||||
|
||||
|
@ -2,10 +2,11 @@ package buildassets
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"github.com/leaanthony/debme"
|
||||
"github.com/leaanthony/gosod"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/leaanthony/debme"
|
||||
"github.com/leaanthony/gosod"
|
||||
)
|
||||
|
||||
//go:embed build
|
||||
@ -50,3 +51,17 @@ func RegenerateAppIcon(target string) error {
|
||||
}
|
||||
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 != "" {
|
||||
v += " "
|
||||
}
|
||||
v += "-I" + buildBaseDir
|
||||
v += "-mmacosx-version-min=10.13"
|
||||
return v
|
||||
})
|
||||
// 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 {
|
||||
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 {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/fs"
|
||||
|
||||
@ -209,6 +210,18 @@ func Build(options *Options) (string, error) {
|
||||
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
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/leaanthony/winicon"
|
||||
"github.com/tc-hib/winres"
|
||||
@ -113,7 +109,7 @@ func packageApplicationForDarwin(options *Options) error {
|
||||
}
|
||||
|
||||
// Generate Icons
|
||||
err = processApplicationIcon(resourceDir, options.ProjectData.BuildDir)
|
||||
err = processApplicationIcon(resourceDir, options.ProjectData.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -126,11 +122,11 @@ func packageApplicationForDarwin(options *Options) error {
|
||||
func processPList(options *Options, contentsDirectory string) error {
|
||||
|
||||
// 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 !fs.FileExists(plistFile) {
|
||||
err := generateDefaultPlist(options, plistFile)
|
||||
err := buildassets.RegeneratePlist(plistFileDir, options.ProjectData.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -141,65 +137,6 @@ func processPList(options *Options, contentsDirectory string) error {
|
||||
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) {
|
||||
|
||||
appIcon := filepath.Join(iconsDir, "appicon.png")
|
||||
|
@ -2,6 +2,7 @@ package options
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
)
|
||||
|
||||
// Default options for creating the App
|
||||
@ -11,3 +12,8 @@ var Default = &App{
|
||||
Logger: logger.NewDefaultLogger(),
|
||||
LogLevel: logger.INFO,
|
||||
}
|
||||
|
||||
var defaultMacMenu = menu.NewMenuFromItems(
|
||||
menu.AppMenu(),
|
||||
menu.EditMenu(),
|
||||
)
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"embed"
|
||||
"log"
|
||||
"runtime"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||||
@ -94,4 +95,11 @@ func MergeDefaults(appoptions *App) {
|
||||
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
|
||||
|
||||
- Windows 10
|
||||
- MacOS x64 & arm64 (due October '21)
|
||||
- Linux (due December '21)
|
||||
- MacOS 10.13+ (amd64)
|
||||
- MacOS 11.0+ (arm64)
|
||||
- Linux (due Jan '22)
|
||||
|
||||
## Dependencies
|
||||
|
||||
@ -47,7 +48,11 @@ import TabItem from "@theme/TabItem";
|
||||
{ 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">
|
||||
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{" "}
|
||||
|
@ -199,7 +199,7 @@ The format of the file is slightly different. Here is a comparison:
|
||||
| frontend / serve | | Removed |
|
||||
| tags | | Removed |
|
||||
| | 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>
|
||||
|
||||
|
@ -74,6 +74,12 @@ Example:
|
||||
|
||||
`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
|
||||
|
||||
`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) |
|
||||
| -devserverurl "url" | Use 3rd party dev server url, EG Vite | "http://localhost:34115" |
|
||||
| -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
|
||||
`wails.json`, and become the defaults for subsequent invocations.
|
||||
|
@ -5,7 +5,7 @@ sidebar_position: 4
|
||||
# Menus
|
||||
|
||||
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
|
||||
[MenuUpdateApplicationMenu](/docs/reference/runtime/menu#menuupdateapplicationmenu).
|
||||
@ -79,6 +79,7 @@ type MenuItem struct {
|
||||
| Checked | bool | Adds check to item (Checkbox & Radio types) |
|
||||
| SubMenu | [\*Menu](#menu) | Sets the submenu |
|
||||
| Click | [Callback](#callback) | Callback function when menu clicked |
|
||||
| Role | string | Defines a [role](#roles) for this menu item. Mac only for now. |
|
||||
|
||||
### 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
|
||||
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,
|
||||
HideWindowOnClose: false,
|
||||
RGBA: &options.RGBA{R: 0, G: 0, B: 0, A: 255},
|
||||
AlwaysOnTop: false,
|
||||
Assets: assets,
|
||||
Menu: app.applicationMenu(),
|
||||
Logger: nil,
|
||||
@ -43,6 +44,24 @@ func main() {
|
||||
WindowIsTranslucent: 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 {
|
||||
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).
|
||||
|
||||
NOTE: On Mac, if no menu is specified, a default menu will be created.
|
||||
|
||||
### Logger
|
||||
|
||||
Name: Logger
|
||||
@ -281,3 +302,153 @@ Name: DisableWindowIcon
|
||||
Type: bool
|
||||
|
||||
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
|
||||
{
|
||||
"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: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]",
|
||||
|
@ -63,7 +63,7 @@ const darkCodeTheme = require('prism-react-renderer/themes/palenight');
|
||||
({
|
||||
announcementBar: {
|
||||
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',
|
||||
textColor: '#FFF',
|
||||
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"?>
|
||||
<!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"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<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"?>
|
||||
<!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"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<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 |