diff --git a/v3/cmd/wails3/main.go b/v3/cmd/wails3/main.go index 3d54d62ff5e..642a8c2b0b6 100644 --- a/v3/cmd/wails3/main.go +++ b/v3/cmd/wails3/main.go @@ -78,23 +78,27 @@ func main() { } func printFooter() { - pterm.Println(pterm.LightGreen("\nNeed documentation? Run: ") + pterm.LightYellow("wails3 docs\n")) - // Check if we're in a teminal - printer := pterm.PrefixPrinter{ - MessageStyle: pterm.NewStyle(pterm.FgLightGreen), - Prefix: pterm.Prefix{ - Style: pterm.NewStyle(pterm.FgRed, pterm.BgLightWhite), - Text: "♥ ", - }, - } + if !commands.DisableFooter { + pterm.Println(pterm.LightGreen("\nNeed documentation? Run: ") + pterm.LightYellow("wails3 docs\n")) + // Check if we're in a teminal + printer := pterm.PrefixPrinter{ + MessageStyle: pterm.NewStyle(pterm.FgLightGreen), + Prefix: pterm.Prefix{ + Style: pterm.NewStyle(pterm.FgRed, pterm.BgLightWhite), + Text: "♥ ", + }, + } - printer.Println("If Wails is useful to you or your company, please consider sponsoring the project: " + pterm.LightYellow("wails3 sponsor")) + printer.Println("If Wails is useful to you or your company, please consider sponsoring the project: " + pterm.LightYellow("wails3 sponsor")) + } } func openDocs() error { + commands.DisableFooter = true return browser.OpenURL("https://v3alpha.wails.io/getting-started/your-first-app/") } func openSponsor() error { + commands.DisableFooter = true return browser.OpenURL("https://github.com/sponsors/leaanthony") } diff --git a/v3/examples/events-bug/main.go b/v3/examples/events-bug/main.go new file mode 100644 index 00000000000..02af2385678 --- /dev/null +++ b/v3/examples/events-bug/main.go @@ -0,0 +1,58 @@ +package main + +import ( + _ "embed" + "github.com/wailsapp/wails/v3/pkg/application" + "log" +) + +func main() { + app := application.New(application.Options{ + Name: "Key Bindings Demo", + Description: "A demo of the Key Bindings Options", + Mac: application.MacOptions{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + KeyBindings: map[string]func(window *application.WebviewWindow){ + "shift+ctrl+c": func(window *application.WebviewWindow) { + selection, err := application.OpenFileDialog(). + CanChooseFiles(true). + CanCreateDirectories(true). + ShowHiddenFiles(true). + PromptForMultipleSelection() + if err != nil { + println(err.Error()) + } + println(selection) + }, + }, + }) + + app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Name: "Window 1", + Title: "Window 1", + URL: "https://wails.io", + KeyBindings: map[string]func(window *application.WebviewWindow){ + "F12": func(window *application.WebviewWindow) { + window.OpenDevTools() + }, + }, + }) + + app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Name: "Window 2", + Title: "Window 2", + URL: "https://google.com", + KeyBindings: map[string]func(window *application.WebviewWindow){ + "F12": func(window *application.WebviewWindow) { + println("Window 2: Toggle Dev Tools") + }, + }, + }) + + err := app.Run() + if err != nil { + log.Fatal(err) + } + +} diff --git a/v3/internal/commands/appimage.go b/v3/internal/commands/appimage.go index f3238da0132..62bc59acbad 100644 --- a/v3/internal/commands/appimage.go +++ b/v3/internal/commands/appimage.go @@ -31,9 +31,10 @@ type GenerateAppImageOptions struct { } func GenerateAppImage(options *GenerateAppImageOptions) error { + DisableFooter = true defer func() { - pterm.DefaultSpinner.Stop() + _ = pterm.DefaultSpinner.Stop() }() if options.Binary == "" { @@ -179,46 +180,46 @@ func generateAppImage(options *GenerateAppImageOptions) error { } func findGTKFiles(files []string) ([]string, error) { - notFound := []string{} - found := []string{} - err := filepath.Walk("/usr/", func(path string, info os.FileInfo, err error) error { - if err != nil { + notFound := []string{} + found := []string{} + err := filepath.Walk("/usr/", func(path string, info os.FileInfo, err error) error { + if err != nil { if os.IsPermission(err) { return nil } - return err - } - - if info.IsDir() { - return nil - } - - for _, fileName := range files { - if strings.HasSuffix(path, fileName) { - found = append(found, path) - break - } - } - - return nil - }) - if err != nil { - return nil, err - } - for _, fileName := range files { - fileFound := false - for _, foundPath := range found { - if strings.HasSuffix(foundPath, fileName) { - fileFound = true - break - } - } - if !fileFound { - notFound = append(notFound, fileName) - } - } - if len(notFound) > 0 { - return nil, errors.New("Unable to locate all required files: " + strings.Join(notFound, ", ")) - } - return found, nil + return err + } + + if info.IsDir() { + return nil + } + + for _, fileName := range files { + if strings.HasSuffix(path, fileName) { + found = append(found, path) + break + } + } + + return nil + }) + if err != nil { + return nil, err + } + for _, fileName := range files { + fileFound := false + for _, foundPath := range found { + if strings.HasSuffix(foundPath, fileName) { + fileFound = true + break + } + } + if !fileFound { + notFound = append(notFound, fileName) + } + } + if len(notFound) > 0 { + return nil, errors.New("Unable to locate all required files: " + strings.Join(notFound, ", ")) + } + return found, nil } diff --git a/v3/internal/commands/bindings.go b/v3/internal/commands/bindings.go index 8dc66fc005c..94833f88127 100644 --- a/v3/internal/commands/bindings.go +++ b/v3/internal/commands/bindings.go @@ -15,6 +15,8 @@ import ( ) func GenerateBindings(options *flags.GenerateBindingsOptions, patterns []string) error { + DisableFooter = true + if options.Silent { pterm.DisableOutput() defer pterm.EnableOutput() diff --git a/v3/internal/commands/build-assets.go b/v3/internal/commands/build-assets.go index be0e2002bfd..9b422595d44 100644 --- a/v3/internal/commands/build-assets.go +++ b/v3/internal/commands/build-assets.go @@ -31,6 +31,7 @@ type BuildAssetsOptions struct { } func GenerateBuildAssets(options *BuildAssetsOptions) error { + DisableFooter = true var err error options.Dir, err = filepath.Abs(options.Dir) diff --git a/v3/internal/commands/constants.go b/v3/internal/commands/constants.go index f2004d0f67b..729d7e02755 100644 --- a/v3/internal/commands/constants.go +++ b/v3/internal/commands/constants.go @@ -12,6 +12,7 @@ type GenerateConstantsOptions struct { } func GenerateConstants(options *GenerateConstantsOptions) error { + DisableFooter = true goData, err := os.ReadFile(options.ConstantsFilename) if err != nil { return err diff --git a/v3/internal/commands/dot_desktop.go b/v3/internal/commands/dot_desktop.go index 1e76163a733..de3ed6c0153 100644 --- a/v3/internal/commands/dot_desktop.go +++ b/v3/internal/commands/dot_desktop.go @@ -57,6 +57,7 @@ func (d *DotDesktopOptions) asBytes() []byte { } func GenerateDotDesktop(options *DotDesktopOptions) error { + DisableFooter = true if options.Name == "" { return fmt.Errorf("name is required") diff --git a/v3/internal/commands/icons.go b/v3/internal/commands/icons.go index ef6ce197135..cd852671ebc 100644 --- a/v3/internal/commands/icons.go +++ b/v3/internal/commands/icons.go @@ -23,6 +23,7 @@ type IconsOptions struct { } func GenerateIcons(options *IconsOptions) error { + DisableFooter = true if options.Example { return generateExampleIcon() @@ -131,10 +132,11 @@ func generateWindowsIcon(iconData []byte, sizes []int, options *IconsOptions) er return nil } -func GenerateTemplateIcon(data []byte, outputFilename string) error { +func GenerateTemplateIcon(data []byte, outputFilename string) (err error) { // Decode the input file as a PNG buffer := bytes.NewBuffer(data) - img, err := png.Decode(buffer) + var img image.Image + img, err = png.Decode(buffer) if err != nil { return fmt.Errorf("failed to decode input file as PNG: %w", err) } @@ -153,14 +155,17 @@ func GenerateTemplateIcon(data []byte, outputFilename string) error { } // Create the output file - outFile, err := os.Create(outputFilename) + var outFile *os.File + outFile, err = os.Create(outputFilename) if err != nil { return fmt.Errorf("failed to create output file: %w", err) } - defer outFile.Close() + defer func() { + err = outFile.Close() + }() // Encode the template icon image as a PNG and write it to the output file - if err := png.Encode(outFile, iconImg); err != nil { + if err = png.Encode(outFile, iconImg); err != nil { return fmt.Errorf("failed to encode output image as PNG: %w", err) } diff --git a/v3/internal/commands/init.go b/v3/internal/commands/init.go index cfab7e3e379..41a38b2f311 100644 --- a/v3/internal/commands/init.go +++ b/v3/internal/commands/init.go @@ -11,6 +11,8 @@ import ( "github.com/pterm/pterm" ) +var DisableFooter bool + func Init(options *flags.Init) error { if options.List { diff --git a/v3/internal/commands/syso.go b/v3/internal/commands/syso.go index 63a9b6186f0..d892d59f4ea 100644 --- a/v3/internal/commands/syso.go +++ b/v3/internal/commands/syso.go @@ -23,7 +23,9 @@ func (i *SysoOptions) Default() *SysoOptions { } } -func GenerateSyso(options *SysoOptions) error { +func GenerateSyso(options *SysoOptions) (err error) { + + DisableFooter = true if options.Manifest == "" { return fmt.Errorf("manifest is required") @@ -39,7 +41,9 @@ func GenerateSyso(options *SysoOptions) error { if err != nil { return err } - defer iconFile.Close() + defer func() { + err = iconFile.Close() + }() ico, err := winres.LoadICO(iconFile) if err != nil { return fmt.Errorf("couldn't load icon '%s': %v", options.Icon, err) @@ -62,7 +66,8 @@ func GenerateSyso(options *SysoOptions) error { rs.SetManifest(xmlData) if options.Info != "" { - infoData, err := os.ReadFile(options.Info) + var infoData []byte + infoData, err = os.ReadFile(options.Info) if err != nil { return err } @@ -79,23 +84,26 @@ func GenerateSyso(options *SysoOptions) error { if targetFile == "" { targetFile = "rsrc_windows_" + options.Arch + ".syso" } - fout, err := os.Create(targetFile) + var outputFile *os.File + outputFile, err = os.Create(targetFile) if err != nil { return err } - defer fout.Close() + defer func() { + err = outputFile.Close() + }() - archs := map[string]winres.Arch{ + architecture := map[string]winres.Arch{ "amd64": winres.ArchAMD64, "arm64": winres.ArchARM64, "386": winres.ArchI386, } - targetArch, supported := archs[options.Arch] + targetArch, supported := architecture[options.Arch] if !supported { return fmt.Errorf("arch '%s' not supported", options.Arch) } - err = rs.WriteObject(fout, targetArch) + err = rs.WriteObject(outputFile, targetArch) if err != nil { return err } diff --git a/v3/internal/commands/tool_checkport.go b/v3/internal/commands/tool_checkport.go index db56d31710d..f0ba75bc48f 100644 --- a/v3/internal/commands/tool_checkport.go +++ b/v3/internal/commands/tool_checkport.go @@ -29,6 +29,8 @@ func isPortOpen(ip string, port int) bool { } func ToolCheckPort(options *ToolCheckPortOptions) error { + DisableFooter = true + if options.URL != "" { // Parse URL u, err := url.Parse(options.URL) diff --git a/v3/internal/commands/tool_cp.go b/v3/internal/commands/tool_cp.go index c904467bff4..5e0a1526a43 100644 --- a/v3/internal/commands/tool_cp.go +++ b/v3/internal/commands/tool_cp.go @@ -8,7 +8,9 @@ import ( type CpOptions struct{} -func Cp(options *CpOptions) error { +func Cp(_ *CpOptions) error { + DisableFooter = true + // extract the source and destination from os.Args if len(os.Args) != 5 { return fmt.Errorf("cp requires a source and destination") diff --git a/v3/internal/commands/version.go b/v3/internal/commands/version.go index e4f9cb02881..6ff58879bd9 100644 --- a/v3/internal/commands/version.go +++ b/v3/internal/commands/version.go @@ -8,6 +8,7 @@ import ( type VersionOptions struct{} func Version(_ *VersionOptions) error { + DisableFooter = true println(version.VersionString) return nil } diff --git a/v3/pkg/application/menuitem_darwin.go b/v3/pkg/application/menuitem_darwin.go index 8b1217e1543..69855542aaa 100644 --- a/v3/pkg/application/menuitem_darwin.go +++ b/v3/pkg/application/menuitem_darwin.go @@ -284,9 +284,16 @@ static void cut(void) { [NSApp sendAction:@selector(cut:) to:nil from:nil]; } +void performSelectorOnMainThreadForFirstResponder(SEL selector) { + NSWindow *activeWindow = [[NSApplication sharedApplication] keyWindow]; + if (activeWindow) { + [activeWindow performSelectorOnMainThread:selector withObject:nil waitUntilDone:YES]; + } +} + // Call selectAll selector to select all text static void selectAll(void) { - [NSApp sendAction:@selector(selectAll:) to:nil from:nil]; + performSelectorOnMainThreadForFirstResponder(@selector(selectAll:)); } // Call delete selector to delete text