Compare commits

..

2 Commits

Author SHA1 Message Date
Lea Anthony
07c17c9e81 Merge branch 'develop' into 253-fix-runtime-import 2019-10-09 19:32:40 +11:00
Lea Anthony
79c258bbe0 fix: importing runtime 2019-10-09 14:44:53 +11:00
39 changed files with 127 additions and 897 deletions

View File

@@ -19,4 +19,3 @@ Wails is what it is because of the time and effort given by these great people.
* [Nikolai Zimmermann](https://github.com/Chronophylos) * [Nikolai Zimmermann](https://github.com/Chronophylos)
* [Toyam Cox](https://github.com/Vaelatern) * [Toyam Cox](https://github.com/Vaelatern)
* [Robin Eklind](https://github.com/mewmew) * [Robin Eklind](https://github.com/mewmew)
* [Kris Raney](https://github.com/kraney)

60
app.go
View File

@@ -1,12 +1,6 @@
package wails package wails
import ( import (
"fmt"
"os"
"runtime"
"syscall"
"github.com/syossan27/tebata"
"github.com/wailsapp/wails/cmd" "github.com/wailsapp/wails/cmd"
"github.com/wailsapp/wails/lib/binding" "github.com/wailsapp/wails/lib/binding"
"github.com/wailsapp/wails/lib/event" "github.com/wailsapp/wails/lib/event"
@@ -67,31 +61,11 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
result.config.DisableInspector = true result.config.DisableInspector = true
} }
// If running windows, do a hidpi fix
if runtime.GOOS == "windows" {
err := SetProcessDPIAware()
if err != nil {
result.log.Fatalf(err.Error())
}
}
return result return result
} }
// SetProcessDPIAware via user32.dll
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocessdpiaware
// Also, thanks Jack Mordaynt! https://github.com/wailsapp/wails/issues/293
func SetProcessDPIAware() error {
status, r, err := syscall.NewLazyDLL("user32.dll").NewProc("SetProcessDPIAware").Call()
if status == 0 {
return fmt.Errorf("exit status %d: %v %v", status, r, err)
}
return nil
}
// Run the app // Run the app
func (a *App) Run() error { func (a *App) Run() error {
if BuildMode != cmd.BuildModeProd { if BuildMode != cmd.BuildModeProd {
return a.cli.Run() return a.cli.Run()
} }
@@ -123,13 +97,6 @@ func (a *App) start() error {
return err return err
} }
// Start signal handler
t := tebata.New(os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
t.Reserve(func() {
a.log.Debug("SIGNAL CAUGHT! Starting Shutdown")
a.renderer.Close()
})
// Start event manager and give it our renderer // Start event manager and give it our renderer
a.eventManager.Start(a.renderer) a.eventManager.Start(a.renderer)
@@ -145,33 +112,8 @@ func (a *App) start() error {
return err return err
} }
// Defer the shutdown
defer a.shutdown()
// Run the renderer // Run the renderer
err = a.renderer.Run() return a.renderer.Run()
if err != nil {
return err
}
return nil
}
// shutdown the app
func (a *App) shutdown() {
// Make sure this is only called once
a.log.Debug("Shutting down")
// Shutdown Binding Manager
a.bindingManager.Shutdown()
// Shutdown IPC Manager
a.ipc.Shutdown()
// Shutdown Event Manager
a.eventManager.Shutdown()
a.log.Debug("Cleanly Shutdown")
} }
// Bind allows the user to bind the given object // Bind allows the user to bind the given object

File diff suppressed because one or more lines are too long

View File

@@ -7,7 +7,6 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"time" "time"
"github.com/leaanthony/mewn" "github.com/leaanthony/mewn"
@@ -88,17 +87,6 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
buildCommand.Add("build") buildCommand.Add("build")
if binaryName != "" { if binaryName != "" {
// Alter binary name based on OS
switch runtime.GOOS {
case "windows":
if !strings.HasSuffix(binaryName, ".exe") {
binaryName += ".exe"
}
default:
if strings.HasSuffix(binaryName, ".exe") {
binaryName = strings.TrimSuffix(binaryName, ".exe")
}
}
buildCommand.Add("-o") buildCommand.Add("-o")
buildCommand.Add(binaryName) buildCommand.Add(binaryName)
} }
@@ -115,7 +103,7 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
} }
// Add windows flags // Add windows flags
if runtime.GOOS == "windows" && buildMode == BuildModeProd { if runtime.GOOS == "windows" {
ldflags += "-H windowsgui " ldflags += "-H windowsgui "
} }
@@ -231,15 +219,6 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
const md5sumFile = "package.json.md5" const md5sumFile = "package.json.md5"
// If node_modules does not exist, force a rebuild.
nodeModulesPath, err := filepath.Abs(filepath.Join(".", "node_modules"))
if err != nil {
return err
}
if !fs.DirExists(nodeModulesPath) {
forceRebuild = true
}
// If we aren't forcing the install and the md5sum file exists // If we aren't forcing the install and the md5sum file exists
if !forceRebuild && fs.FileExists(md5sumFile) { if !forceRebuild && fs.FileExists(md5sumFile) {
// Yes - read contents // Yes - read contents

View File

@@ -191,15 +191,8 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
// Build syso // Build syso
sysofile := filepath.Join(b.fs.Cwd(), basename+"-res.syso") sysofile := filepath.Join(b.fs.Cwd(), basename+"-res.syso")
windresCommand := []string{"windres", "-o", sysofile, tgtRCFile}
batfile, err := fs.LocalDir(".") err := NewProgramHelper().RunCommandArray(windresCommand)
if err != nil {
return err
}
windresBatFile := filepath.Join(batfile.fullPath, "windres.bat")
windresCommand := []string{windresBatFile, sysofile, tgtRCFile}
err = NewProgramHelper().RunCommandArray(windresCommand)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -100,19 +100,6 @@ func (p *ProgramHelper) InstallGoPackage(packageName string) error {
return err return err
} }
// InstallNPMPackage installs the given npm package
func (p *ProgramHelper) InstallNPMPackage(packageName string, save bool) error {
args := strings.Split("install "+packageName, " ")
if save {
args = append(args, "--save")
}
_, stderr, err := p.shell.Run("npm", args...)
if err != nil {
fmt.Println(stderr)
}
return err
}
// RunCommand runs the given command // RunCommand runs the given command
func (p *ProgramHelper) RunCommand(command string) error { func (p *ProgramHelper) RunCommand(command string) error {
args := strings.Split(command, " ") args := strings.Split(command, " ")
@@ -128,7 +115,6 @@ func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", program) fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", program)
return err return err
} }
args = args[1:] args = args[1:]
var stderr string var stderr string
var stdout string var stdout string

View File

@@ -13,18 +13,6 @@ import (
"github.com/leaanthony/slicer" "github.com/leaanthony/slicer"
) )
// PackageManager indicates different package managers
type PackageManager int
const (
// UNKNOWN package manager
UNKNOWN PackageManager = iota
// NPM package manager
NPM
// YARN package manager
YARN
)
type author struct { type author struct {
Name string `json:"name"` Name string `json:"name"`
Email string `json:"email"` Email string `json:"email"`
@@ -165,23 +153,6 @@ func (po *ProjectOptions) Defaults() {
po.WailsVersion = Version po.WailsVersion = Version
} }
// GetNPMBinaryName returns the type of package manager used by the project
func (po *ProjectOptions) GetNPMBinaryName() (PackageManager, error) {
if po.FrontEnd == nil {
return UNKNOWN, fmt.Errorf("No frontend specified in project options")
}
if strings.Index(po.FrontEnd.Install, "npm") > -1 {
return NPM, nil
}
if strings.Index(po.FrontEnd.Install, "yarn") > -1 {
return YARN, nil
}
return UNKNOWN, nil
}
// PromptForInputs asks the user to input project details // PromptForInputs asks the user to input project details
func (po *ProjectOptions) PromptForInputs() error { func (po *ProjectOptions) PromptForInputs() error {

View File

@@ -0,0 +1,17 @@
/*
Wails Bridge (c) 2019-present Lea Anthony
This prod version is to get around having to rewrite your code
for production. When doing a release build, this file will be used
instead of the full version.
*/
export default {
// The main function
// Passes the main Wails object to the callback if given.
Start: function(callback) {
if (callback) {
window.wails.events.on("wails:ready", callback);
}
}
};

View File

@@ -0,0 +1,17 @@
/*
Wails Bridge (c) 2019-present Lea Anthony
This prod version is to get around having to rewrite your code
for production. When doing a release build, this file will be used
instead of the full version.
*/
export default {
// The main function
// Passes the main Wails object to the callback if given.
Start: function (callback) {
if (callback) {
window.wails.Events.On("wails:ready", callback);
}
}
};

View File

@@ -1,4 +1,4 @@
package cmd package cmd
// Version - Wails version // Version - Wails version
const Version = "v0.19.0" const Version = "v0.18.3"

View File

@@ -1,408 +0,0 @@
package main
import (
"bufio"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/Masterminds/semver"
"github.com/leaanthony/spinner"
"github.com/wailsapp/wails/cmd"
)
// Constants
var checkSpinner = spinner.NewSpinner()
var migrateProjectOptions = &cmd.ProjectOptions{}
var migrateFS = cmd.NewFSHelper()
var migrateGithub = cmd.NewGitHubHelper()
var programHelper = cmd.NewProgramHelper()
var lessThanV1 *semver.Constraints
// The user's go.mod
var goMod string
var goModFile string
// The user's main.js
var mainJSFile string
var mainJSContents string
// Frontend directory
var frontEndDir string
func init() {
var dryrun bool
var err error
lessThanV1, err = semver.NewConstraint("< v1.0.0")
if err != nil {
log.Fatal(err)
}
// var forceRebuild = false
checkSpinner.SetSpinSpeed(50)
commandDescription := `EXPERIMENTAL - This command attempts to migrate projects to the latest Wails version.`
updateCmd := app.Command("migrate", "Migrate projects to latest Wails release").
LongDescription(commandDescription).
BoolFlag("dryrun", "Only display what would be done", &dryrun)
updateCmd.Action(func() error {
message := "Migrate Project"
logger.PrintSmallBanner(message)
logger.Red("WARNING: This is an experimental command. Ensure you have backups of your project!")
logger.Red("It currently only supports npm based projects.")
fmt.Println()
// Check project directory
err := checkProjectDirectory()
if err != nil {
return err
}
// Find Wails version from go.mod
wailsVersion, err := getWailsVersion()
if err != nil {
return err
}
// Get latest stable version
var latestVersion *semver.Version
latestVersion, err = getLatestWailsVersion()
if err != nil {
return err
}
var canMigrate bool
canMigrate, err = canMigrateVersion(wailsVersion, latestVersion)
if err != nil {
return err
}
if !canMigrate {
return nil
}
// Check for wailsbridge
wailsBridge, err := checkWailsBridge()
if err != nil {
return err
}
// Is main.js using bridge.Init()
canUpdateMainJS, err := checkMainJS()
if err != nil {
return err
}
// TODO: Check if we are using legacy js runtime
// Operations
logger.Yellow("Operations to perform:")
logger.Yellowf(" - Update to Wails v%s\n", latestVersion)
if len(wailsBridge) > 0 {
logger.Yellow(" - Delete wailsbridge.js")
}
if canUpdateMainJS {
logger.Yellow(" - Patch main.js")
}
logger.Yellow(" - Ensure '@wailsapp/runtime` module is installed")
if dryrun {
logger.White("Exiting: Dry Run")
return nil
}
logger.Red("*WARNING* About to modify your project!")
logger.Red("Type 'YES' to continue: ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
input := scanner.Text()
if input != "YES" {
logger.Red("ABORTED!")
return nil
}
logger.Yellow("Let's do this!")
err = updateWailsVersion(wailsVersion, latestVersion)
if err != nil {
return err
}
if len(wailsBridge) > 0 {
err = deleteWailsBridge(wailsBridge)
if err != nil {
return err
}
}
if canUpdateMainJS {
err = patchMainJS()
if err != nil {
return err
}
}
// Install runtime
err = installWailsRuntime()
if err != nil {
return err
}
fmt.Println()
logger.Yellow("Migration complete! Check project by running `wails build`.")
return nil
})
}
func checkProjectDirectory() error {
// Get versions
checkSpinner.Start("Check Project Directory")
// Check we are in project directory
err := migrateProjectOptions.LoadConfig(migrateFS.Cwd())
if err != nil {
checkSpinner.Error()
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
}
checkSpinner.Success()
return nil
}
func getWailsVersion() (*semver.Version, error) {
checkSpinner.Start("Get Wails Version")
var result *semver.Version
// Load file
var err error
goModFile, err = filepath.Abs(filepath.Join(".", "go.mod"))
if err != nil {
checkSpinner.Error()
return nil, fmt.Errorf("Unable to load go.mod at %s", goModFile)
}
goMod, err = migrateFS.LoadAsString(goModFile)
if err != nil {
checkSpinner.Error()
return nil, fmt.Errorf("Unable to load go.mod")
}
// Find wails version
versionRegexp := regexp.MustCompile(`.*github.com/wailsapp/wails.*(v\d+.\d+.\d+)`)
versions := versionRegexp.FindStringSubmatch(goMod)
if len(versions) != 2 {
return nil, fmt.Errorf("Unable to determine Wails version")
}
version := versions[1]
result, err = semver.NewVersion(version)
if err != nil {
return nil, fmt.Errorf("Unable to parse Wails version: %s", version)
}
checkSpinner.Success("Found Wails Version: " + version)
return result, nil
}
func canMigrateVersion(wailsVersion *semver.Version, latestVersion *semver.Version) (bool, error) {
checkSpinner.Start("Checking ability to Migrate")
// Check if we are at the latest version!!!!
if wailsVersion.Equal(latestVersion) || wailsVersion.GreaterThan(latestVersion) {
checkSpinner.Errorf("Checking ability to Migrate: No! (v%s >= v%s)", wailsVersion, latestVersion)
return false, nil
}
// Check for < v1.0.0
if lessThanV1.Check(wailsVersion) {
checkSpinner.Successf("Checking ability to Migrate: Yes! (v%s < v1.0.0)", wailsVersion)
return true, nil
}
checkSpinner.Error("Unable to migrate")
return false, fmt.Errorf("No migration rules for version %s", wailsVersion)
}
func checkWailsBridge() (string, error) {
checkSpinner.Start("Checking if legacy Wails Bridge present")
// Check frontend dir is available
if migrateProjectOptions.FrontEnd == nil ||
len(migrateProjectOptions.FrontEnd.Dir) == 0 ||
!migrateFS.DirExists(migrateProjectOptions.FrontEnd.Dir) {
checkSpinner.Error("Unable to determine frontend directory")
return "", fmt.Errorf("Unable to determine frontend directory")
}
frontEndDir = migrateProjectOptions.FrontEnd.Dir
wailsBridgePath, err := filepath.Abs(filepath.Join(".", frontEndDir, "src", "wailsbridge.js"))
if err != nil {
checkSpinner.Error(err.Error())
return "", err
}
// If it doesn't exist, return blank string
if !migrateFS.FileExists(wailsBridgePath) {
checkSpinner.Success("Checking if legacy Wails Bridge present: No")
return "", nil
}
checkSpinner.Success("Checking if legacy Wails Bridge present: Yes")
return wailsBridgePath, nil
}
// This function determines if the main.js file using wailsbridge can be auto-updated
func checkMainJS() (bool, error) {
checkSpinner.Start("Checking if main.js can be migrated")
var err error
// Check main.js is there
if migrateProjectOptions.FrontEnd == nil ||
len(migrateProjectOptions.FrontEnd.Dir) == 0 ||
!migrateFS.DirExists(migrateProjectOptions.FrontEnd.Dir) {
checkSpinner.Error("Unable to determine frontend directory")
return false, fmt.Errorf("Unable to determine frontend directory")
}
frontEndDir = migrateProjectOptions.FrontEnd.Dir
mainJSFile, err = filepath.Abs(filepath.Join(".", frontEndDir, "src", "main.js"))
if err != nil {
checkSpinner.Error("Unable to find main.js")
return false, err
}
mainJSContents, err = migrateFS.LoadAsString(mainJSFile)
if err != nil {
checkSpinner.Error("Unable to load main.js")
return false, err
}
// Check we have a line like: import Bridge from "./wailsbridge";
if strings.Index(mainJSContents, `import Bridge from "./wailsbridge";`) == -1 {
checkSpinner.Success("Checking if main.js can be migrated: No - Cannot find `import Bridge`")
return false, nil
}
// Check we have a line like: Bridge.Start(() => {
if strings.Index(mainJSContents, `Bridge.Start(`) == -1 {
checkSpinner.Success("Checking if main.js can be migrated: No - Cannot find `Bridge.Start`")
return false, nil
}
checkSpinner.Success("Checking if main.js can be migrated: Yes")
return true, nil
}
func getLatestWailsVersion() (*semver.Version, error) {
checkSpinner.Start("Checking GitHub for latest Wails version")
version, err := migrateGithub.GetLatestStableRelease()
if err != nil {
checkSpinner.Error("Checking GitHub for latest Wails version: Failed")
return nil, err
}
checkSpinner.Successf("Checking GitHub for latest Wails version: v%s", version)
return version.Version, nil
}
func updateWailsVersion(currentVersion, latestVersion *semver.Version) error {
// Patch go.mod
checkSpinner.Start("Patching go.mod")
wailsModule := "github.com/wailsapp/wails"
old := fmt.Sprintf("%s v%s", wailsModule, currentVersion)
new := fmt.Sprintf("%s v%s", wailsModule, latestVersion)
goMod = strings.Replace(goMod, old, new, -1)
err := ioutil.WriteFile(goModFile, []byte(goMod), 0600)
if err != nil {
checkSpinner.Error()
return err
}
checkSpinner.Success()
return nil
}
func deleteWailsBridge(bridgeFilename string) error {
// Patch go.mod
checkSpinner.Start("Delete legacy wailsbridge.js")
err := migrateFS.RemoveFile(bridgeFilename)
if err != nil {
checkSpinner.Error()
return err
}
checkSpinner.Success()
return nil
}
func patchMainJS() error {
// Patch main.js
checkSpinner.Start("Patching main.js")
// Patch import line
oldImportLine := `import Bridge from "./wailsbridge";`
newImportLine := `import * as Wails from "@wailsapp/runtime";`
mainJSContents = strings.Replace(mainJSContents, oldImportLine, newImportLine, -1)
// Patch Start line
oldStartLine := `Bridge.Start`
newStartLine := `Wails.Init`
mainJSContents = strings.Replace(mainJSContents, oldStartLine, newStartLine, -1)
err := ioutil.WriteFile(mainJSFile, []byte(mainJSContents), 0600)
if err != nil {
checkSpinner.Error()
return err
}
checkSpinner.Success()
return nil
}
func installWailsRuntime() error {
checkSpinner.Start("Installing @wailsapp/runtime module")
// Change to the frontend directory
err := os.Chdir(frontEndDir)
if err != nil {
checkSpinner.Error()
return nil
}
// Determine package manager
packageManager, err := migrateProjectOptions.GetNPMBinaryName()
if err != nil {
checkSpinner.Error()
return nil
}
switch packageManager {
case cmd.NPM:
// npm install --save @wailsapp/runtime
programHelper.InstallNPMPackage("@wailsapp/runtime", true)
default:
checkSpinner.Error()
return fmt.Errorf("Unknown package manager")
}
checkSpinner.Success()
return nil
}

View File

@@ -80,16 +80,15 @@ To help you in this process, we will ask for some information, add Go/Wails deta
npm := program.FindProgram("npm") npm := program.FindProgram("npm")
if npm != nil { if npm != nil {
stdout, _, _, _ := npm.Run("--version") stdout, _, _, _ := npm.Run("--version")
npmVersion = stdout nodeVersion = stdout
npmVersion = npmVersion[:len(npmVersion)-1] nodeVersion = nodeVersion[:len(nodeVersion)-1]
npmVersion = strings.TrimSpace(npmVersion)
} }
node := program.FindProgram("node") node := program.FindProgram("node")
if node != nil { if node != nil {
stdout, _, _, _ := node.Run("--version") stdout, _, _, _ := node.Run("--version")
nodeVersion = stdout npmVersion = stdout
nodeVersion = nodeVersion[:len(nodeVersion)-1] npmVersion = npmVersion[:len(npmVersion)-1]
} }
str.WriteString("\n| Name | Value |\n| ----- | ----- |\n") str.WriteString("\n| Name | Value |\n| ----- | ----- |\n")

View File

@@ -1 +0,0 @@
windres.exe -o %1 %2

View File

@@ -1,9 +1,6 @@
package wails package wails
import ( import "github.com/leaanthony/mewn"
"github.com/leaanthony/mewn"
"github.com/wailsapp/wails/runtime"
)
// AppConfig is the configuration structure used when creating a Wails App object // AppConfig is the configuration structure used when creating a Wails App object
type AppConfig struct { type AppConfig struct {
@@ -68,7 +65,7 @@ func (a *AppConfig) merge(in *AppConfig) error {
a.CSS = in.CSS a.CSS = in.CSS
} }
if in.Title != "" { if in.Title != "" {
a.Title = runtime.ProcessEncoding(in.Title) a.Title = in.Title
} }
if in.Colour != "" { if in.Colour != "" {

3
go.mod
View File

@@ -2,7 +2,6 @@ module github.com/wailsapp/wails
require ( require (
github.com/Masterminds/semver v1.4.2 github.com/Masterminds/semver v1.4.2
github.com/abadojack/whatlanggo v1.0.1
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect
@@ -23,11 +22,9 @@ require (
github.com/pkg/errors v0.8.1 // indirect github.com/pkg/errors v0.8.1 // indirect
github.com/sirupsen/logrus v1.4.1 github.com/sirupsen/logrus v1.4.1
github.com/stretchr/testify v1.3.0 // indirect github.com/stretchr/testify v1.3.0 // indirect
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862
golang.org/x/text v0.3.0
gopkg.in/AlecAivazis/survey.v1 v1.8.4 gopkg.in/AlecAivazis/survey.v1 v1.8.4
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22 gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
) )

5
go.sum
View File

@@ -2,8 +2,6 @@ github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITg
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
github.com/abadojack/whatlanggo v1.0.1 h1:19N6YogDnf71CTHm3Mp2qhYfkRdyvbgwWdd2EPxJRG4=
github.com/abadojack/whatlanggo v1.0.1/go.mod h1:66WiQbSbJBIlOZMsvbKe5m6pzQovxCH9B/K8tQB2uoc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -70,8 +68,6 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba h1:2DHfQOxcpWdGf5q5IzCUFPNvRX9Icf+09RvQK2VnJq0=
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba/go.mod h1:iLnlXG2Pakcii2CU0cbY07DRCSvpWNa7nFxtevhOChk=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
@@ -87,7 +83,6 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug= golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/AlecAivazis/survey.v1 v1.8.4 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc= gopkg.in/AlecAivazis/survey.v1 v1.8.4 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc=
gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=

View File

@@ -16,7 +16,6 @@ type Manager struct {
functions map[string]*boundFunction functions map[string]*boundFunction
internalMethods *internalMethods internalMethods *internalMethods
initMethods []*boundMethod initMethods []*boundMethod
shutdownMethods []*boundMethod
log *logger.CustomLogger log *logger.CustomLogger
renderer interfaces.Renderer renderer interfaces.Renderer
runtime interfaces.Runtime // The runtime object to pass to bound structs runtime interfaces.Runtime // The runtime object to pass to bound structs
@@ -128,9 +127,6 @@ func (b *Manager) bindMethod(object interface{}) error {
if newMethod.isWailsInit { if newMethod.isWailsInit {
b.log.Debugf("Detected WailsInit function: %s", fullMethodName) b.log.Debugf("Detected WailsInit function: %s", fullMethodName)
b.initMethods = append(b.initMethods, newMethod) b.initMethods = append(b.initMethods, newMethod)
} else if newMethod.isWailsShutdown {
b.log.Debugf("Detected WailsShutdown function: %s", fullMethodName)
b.shutdownMethods = append(b.shutdownMethods, newMethod)
} else { } else {
// Save boundMethod // Save boundMethod
b.log.Infof("Bound Method: %s()", fullMethodName) b.log.Infof("Bound Method: %s()", fullMethodName)
@@ -296,13 +292,3 @@ func (b *Manager) callWailsInitMethods() error {
} }
return nil return nil
} }
// Shutdown the binding manager
func (b *Manager) Shutdown() {
b.log.Debug("Shutdown called")
for _, method := range b.shutdownMethods {
b.log.Debugf("Calling Shutdown for method: %s", method.fullName)
method.call("[]")
}
b.log.Debug("Shutdown complete")
}

View File

@@ -18,7 +18,6 @@ type boundMethod struct {
log *logger.CustomLogger log *logger.CustomLogger
hasErrorReturnType bool // Indicates if there is an error return type hasErrorReturnType bool // Indicates if there is an error return type
isWailsInit bool isWailsInit bool
isWailsShutdown bool
} }
// Creates a new bound method based on the given method + type // Creates a new bound method based on the given method + type
@@ -40,11 +39,6 @@ func newBoundMethod(name string, fullName string, method reflect.Value, objectTy
err = result.processWailsInit() err = result.processWailsInit()
} }
// Are we a WailsShutdown method?
if result.Name == "WailsShutdown" {
err = result.processWailsShutdown()
}
return result, err return result, err
} }
@@ -217,20 +211,3 @@ func (b *boundMethod) processWailsInit() error {
return nil return nil
} }
func (b *boundMethod) processWailsShutdown() error {
// We must have only 1 input, it must be *wails.Runtime
if len(b.inputs) != 0 {
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 inputs, but got %d", len(b.inputs))
}
// We must have only 1 output, it must be error
if len(b.returnTypes) != 0 {
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 return types, but got %d", len(b.returnTypes))
}
// We are indeed a wails Shutdown method
b.isWailsShutdown = true
return nil
}

View File

@@ -3,21 +3,18 @@ package event
import ( import (
"fmt" "fmt"
"sync" "sync"
"time"
"github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger" "github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/messages" "github.com/wailsapp/wails/lib/messages"
"github.com/wailsapp/wails/lib/interfaces"
) )
// Manager handles and processes events // Manager handles and processes events
type Manager struct { type Manager struct {
incomingEvents chan *messages.EventData incomingEvents chan *messages.EventData
listeners map[string][]*eventListener listeners map[string][]*eventListener
running bool exit bool
log *logger.CustomLogger log *logger.CustomLogger
renderer interfaces.Renderer // Messages will be dispatched to the frontend renderer interfaces.Renderer // Messages will be dispatched to the frontend
wg sync.WaitGroup
} }
// NewManager creates a new event manager with a 100 event buffer // NewManager creates a new event manager with a 100 event buffer
@@ -25,7 +22,7 @@ func NewManager() interfaces.EventManager {
return &Manager{ return &Manager{
incomingEvents: make(chan *messages.EventData, 100), incomingEvents: make(chan *messages.EventData, 100),
listeners: make(map[string][]*eventListener), listeners: make(map[string][]*eventListener),
running: false, exit: false,
log: logger.NewCustomLogger("Events"), log: logger.NewCustomLogger("Events"),
} }
} }
@@ -90,14 +87,15 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
// Store renderer // Store renderer
e.renderer = renderer e.renderer = renderer
// Set up waitgroup so we can wait for goroutine to quit // Set up waitgroup so we can wait for goroutine to start
e.running = true var wg sync.WaitGroup
e.wg.Add(1) wg.Add(1)
// Run main loop in separate goroutine // Run main loop in separate goroutine
go func() { go func() {
wg.Done()
e.log.Info("Listening") e.log.Info("Listening")
for e.running { for e.exit == false {
// TODO: Listen for application exit // TODO: Listen for application exit
select { select {
case event := <-e.incomingEvents: case event := <-e.incomingEvents:
@@ -141,18 +139,14 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
} }
} }
} }
default:
time.Sleep(1 * time.Millisecond)
} }
} }
e.wg.Done()
}() }()
// Wait for goroutine to start
wg.Wait()
} }
// Shutdown is called when exiting the Application func (e *Manager) stop() {
func (e *Manager) Shutdown() { e.exit = true
e.log.Debug("Shutting Down")
e.running = false
e.log.Debug("Waiting for main loop to exit")
e.wg.Wait()
} }

View File

@@ -7,5 +7,4 @@ type BindingManager interface {
Bind(object interface{}) Bind(object interface{})
Start(renderer Renderer, runtime Runtime) error Start(renderer Renderer, runtime Runtime) error
ProcessCall(callData *messages.CallData) (result interface{}, err error) ProcessCall(callData *messages.CallData) (result interface{}, err error)
Shutdown()
} }

View File

@@ -8,5 +8,4 @@ type EventManager interface {
Emit(eventName string, optionalData ...interface{}) Emit(eventName string, optionalData ...interface{})
On(eventName string, callback func(...interface{})) On(eventName string, callback func(...interface{}))
Start(Renderer) Start(Renderer)
Shutdown()
} }

View File

@@ -5,5 +5,4 @@ type IPCManager interface {
BindRenderer(Renderer) BindRenderer(Renderer)
Dispatch(message string) Dispatch(message string)
Start(eventManager EventManager, bindingManager BindingManager) Start(eventManager EventManager, bindingManager BindingManager)
Shutdown()
} }

View File

@@ -2,8 +2,6 @@ package ipc
import ( import (
"fmt" "fmt"
"sync"
"time"
"github.com/wailsapp/wails/lib/interfaces" "github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger" "github.com/wailsapp/wails/lib/logger"
@@ -14,20 +12,18 @@ import (
type Manager struct { type Manager struct {
renderer interfaces.Renderer // The renderer renderer interfaces.Renderer // The renderer
messageQueue chan *ipcMessage messageQueue chan *ipcMessage
quitChannel chan struct{} // quitChannel chan struct{}
// signals chan os.Signal // signals chan os.Signal
log *logger.CustomLogger log *logger.CustomLogger
eventManager interfaces.EventManager eventManager interfaces.EventManager
bindingManager interfaces.BindingManager bindingManager interfaces.BindingManager
running bool
wg sync.WaitGroup
} }
// NewManager creates a new IPC Manager // NewManager creates a new IPC Manager
func NewManager() interfaces.IPCManager { func NewManager() interfaces.IPCManager {
result := &Manager{ result := &Manager{
messageQueue: make(chan *ipcMessage, 100), messageQueue: make(chan *ipcMessage, 100),
quitChannel: make(chan struct{}), // quitChannel: make(chan struct{}),
// signals: make(chan os.Signal, 1), // signals: make(chan os.Signal, 1),
log: logger.NewCustomLogger("IPC"), log: logger.NewCustomLogger("IPC"),
} }
@@ -48,12 +44,9 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
i.log.Info("Starting") i.log.Info("Starting")
// signal.Notify(manager.signals, os.Interrupt) // signal.Notify(manager.signals, os.Interrupt)
i.running = true
// Keep track of this goroutine
i.wg.Add(1)
go func() { go func() {
for i.running { running := true
for running {
select { select {
case incomingMessage := <-i.messageQueue: case incomingMessage := <-i.messageQueue:
i.log.DebugFields("Processing message", logger.Fields{ i.log.DebugFields("Processing message", logger.Fields{
@@ -124,12 +117,15 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
i.log.DebugFields("Finished processing message", logger.Fields{ i.log.DebugFields("Finished processing message", logger.Fields{
"1D": &incomingMessage, "1D": &incomingMessage,
}) })
default: // case <-manager.quitChannel:
time.Sleep(1 * time.Millisecond) // Debug("[MessageQueue] Quit caught")
// running = false
// case <-manager.signals:
// Debug("[MessageQueue] Signal caught")
// running = false
} }
} }
i.log.Debug("Stopping") i.log.Debug("Stopping")
i.wg.Done()
}() }()
} }
@@ -171,11 +167,3 @@ func (i *Manager) SendResponse(response *ipcResponse) error {
// Call back to the front end // Call back to the front end
return i.renderer.Callback(data) return i.renderer.Callback(data)
} }
// Shutdown is called when exiting the Application
func (i *Manager) Shutdown() {
i.log.Debug("Shutdown called")
i.running = false
i.log.Debug("Waiting of main loop shutdown")
i.wg.Wait()
}

View File

@@ -156,7 +156,7 @@ func (h *Bridge) Run() error {
h.log.Info("The frontend will connect automatically.") h.log.Info("The frontend will connect automatically.")
err := h.server.ListenAndServe() err := h.server.ListenAndServe()
if err != nil && err != http.ErrServerClosed { if err != nil {
h.log.Fatal(err.Error()) h.log.Fatal(err.Error())
} }
return err return err
@@ -250,9 +250,5 @@ func (h *Bridge) SetTitle(title string) {
// Close is unsupported for Bridge but required // Close is unsupported for Bridge but required
// for the Renderer interface // for the Renderer interface
func (h *Bridge) Close() { func (h *Bridge) Close() {
h.log.Debug("Shutting down") h.log.Warn("Close() unsupported in bridge mode")
err := h.server.Close()
if err != nil {
h.log.Errorf(err.Error())
}
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,6 @@
// Package webview implements Go bindings to https://github.com/zserge/webview C library. // Package wails implements Go bindings to https://github.com/zserge/webview C library.
// It is a modified version of webview.go from that repository // It is a modified version of webview.go from that repository
// Bindings closely repeat the C APIs and include both, a simplified // Bindings closely repeat the C APIs and include both, a simplified
// single-function API to just open a full-screen webview window, and a more // single-function API to just open a full-screen webview window, and a more
// advanced and featureful set of APIs, including Go-to-JavaScript bindings. // advanced and featureful set of APIs, including Go-to-JavaScript bindings.
@@ -10,10 +11,10 @@
package webview package webview
/* /*
#cgo linux openbsd freebsd CFLAGS: -DWEBVIEW_GTK=1 -Wno-deprecated-declarations #cgo linux openbsd freebsd CFLAGS: -DWEBVIEW_GTK=1
#cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0 #cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0
#cgo windows CFLAGS: -DWEBVIEW_WINAPI=1 -std=c99 #cgo windows CFLAGS: -DWEBVIEW_WINAPI=1
#cgo windows LDFLAGS: -lole32 -lcomctl32 -loleaut32 -luuid -lgdi32 #cgo windows LDFLAGS: -lole32 -lcomctl32 -loleaut32 -luuid -lgdi32
#cgo darwin CFLAGS: -DWEBVIEW_COCOA=1 -x objective-c #cgo darwin CFLAGS: -DWEBVIEW_COCOA=1 -x objective-c

View File

@@ -86,7 +86,7 @@ struct webview_priv
NSAutoreleasePool *pool; NSAutoreleasePool *pool;
NSWindow *window; NSWindow *window;
WebView *webview; WebView *webview;
id delegate; id windowDelegate;
int should_exit; int should_exit;
}; };
#else #else
@@ -1038,7 +1038,7 @@ struct webview_priv
return S_FALSE; return S_FALSE;
} }
static const TCHAR *classname = TEXT("WebView"); static const TCHAR *classname = "WebView";
static const SAFEARRAYBOUND ArrayBound = {1, 0}; static const SAFEARRAYBOUND ArrayBound = {1, 0};
static IOleClientSiteVtbl MyIOleClientSiteTable = { static IOleClientSiteVtbl MyIOleClientSiteTable = {
@@ -1227,7 +1227,7 @@ struct webview_priv
} }
VariantInit(&myURL); VariantInit(&myURL);
myURL.vt = VT_BSTR; myURL.vt = VT_BSTR;
// #ifndef UNICODE #ifndef UNICODE
{ {
wchar_t *buffer = webview_to_utf16(webPageName); wchar_t *buffer = webview_to_utf16(webPageName);
if (buffer == NULL) if (buffer == NULL)
@@ -1237,9 +1237,9 @@ struct webview_priv
myURL.bstrVal = SysAllocString(buffer); myURL.bstrVal = SysAllocString(buffer);
GlobalFree(buffer); GlobalFree(buffer);
} }
// #else #else
// myURL.bstrVal = SysAllocString(webPageName); myURL.bstrVal = SysAllocString(webPageName);
// #endif #endif
if (!myURL.bstrVal) if (!myURL.bstrVal)
{ {
badalloc: badalloc:
@@ -1277,7 +1277,7 @@ struct webview_priv
if (!SafeArrayAccessData(sfArray, (void **)&pVar)) if (!SafeArrayAccessData(sfArray, (void **)&pVar))
{ {
pVar->vt = VT_BSTR; pVar->vt = VT_BSTR;
// #ifndef UNICODE #ifndef UNICODE
{ {
wchar_t *buffer = webview_to_utf16(url); wchar_t *buffer = webview_to_utf16(url);
if (buffer == NULL) if (buffer == NULL)
@@ -1287,9 +1287,9 @@ struct webview_priv
bstr = SysAllocString(buffer); bstr = SysAllocString(buffer);
GlobalFree(buffer); GlobalFree(buffer);
} }
// #else #else
// bstr = SysAllocString(url); bstr = SysAllocString(string);
// #endif #endif
if ((pVar->bstrVal = bstr)) if ((pVar->bstrVal = bstr))
{ {
htmlDoc2->lpVtbl->write(htmlDoc2, sfArray); htmlDoc2->lpVtbl->write(htmlDoc2, sfArray);
@@ -1404,7 +1404,6 @@ struct webview_priv
{ {
return -1; return -1;
} }
ZeroMemory(&wc, sizeof(WNDCLASSEX)); ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX); wc.cbSize = sizeof(WNDCLASSEX);
wc.hInstance = hInstance; wc.hInstance = hInstance;
@@ -1432,24 +1431,10 @@ struct webview_priv
rect.bottom = rect.bottom - rect.top + top; rect.bottom = rect.bottom - rect.top + top;
rect.top = top; rect.top = top;
#ifdef UNICODE
wchar_t *u16title = webview_to_utf16(w->title);
if (u16title == NULL)
{
return -1;
}
w->priv.hwnd = w->priv.hwnd =
CreateWindowEx(0, classname, u16title, style, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
HWND_DESKTOP, NULL, hInstance, (void *)w);
#else
w->priv.hwnd =
CreateWindowEx(0, classname, w->title, style, rect.left, rect.top, CreateWindowEx(0, classname, w->title, style, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, rect.right - rect.left, rect.bottom - rect.top,
HWND_DESKTOP, NULL, hInstance, (void *)w); HWND_DESKTOP, NULL, hInstance, (void *)w);
#endif
if (w->priv.hwnd == 0) if (w->priv.hwnd == 0)
{ {
OleUninitialize(); OleUninitialize();
@@ -1460,14 +1445,7 @@ struct webview_priv
DisplayHTMLPage(w); DisplayHTMLPage(w);
#ifdef UNICODE
SetWindowText(w->priv.hwnd, u16title);
GlobalFree(u16title);
#else
SetWindowText(w->priv.hwnd, w->title); SetWindowText(w->priv.hwnd, w->title);
#endif
ShowWindow(w->priv.hwnd, SW_SHOWDEFAULT); ShowWindow(w->priv.hwnd, SW_SHOWDEFAULT);
UpdateWindow(w->priv.hwnd); UpdateWindow(w->priv.hwnd);
SetFocus(w->priv.hwnd); SetFocus(w->priv.hwnd);
@@ -1603,20 +1581,9 @@ struct webview_priv
WEBVIEW_API void webview_set_title(struct webview *w, const char *title) WEBVIEW_API void webview_set_title(struct webview *w, const char *title)
{ {
#ifdef UNICODE
wchar_t *u16title = webview_to_utf16(title);
if (u16title == NULL)
{
return;
}
SetWindowText(w->priv.hwnd, u16title);
GlobalFree(u16title);
#else
SetWindowText(w->priv.hwnd, title); SetWindowText(w->priv.hwnd, title);
#endif
} }
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen) WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
{ {
if (w->priv.is_fullscreen == !!fullscreen) if (w->priv.is_fullscreen == !!fullscreen)
@@ -1927,22 +1894,6 @@ struct webview_priv
[script setValue:self forKey:@"external"]; [script setValue:self forKey:@"external"];
} }
static void webview_run_input_open_panel(id self, SEL cmd, id webview,
id listener, BOOL allowMultiple) {
char filename[256] = "";
struct webview *w =
(struct webview *)objc_getAssociatedObject(self, "webview");
webview_dialog(w, WEBVIEW_DIALOG_TYPE_OPEN, WEBVIEW_DIALOG_FLAG_FILE, "", "",
filename, 255);
if (strlen(filename)) {
[listener chooseFilename:[NSString stringWithUTF8String:filename]];
} else {
[listener cancel];
}
}
static void webview_external_invoke(id self, SEL cmd, id arg) static void webview_external_invoke(id self, SEL cmd, id arg)
{ {
struct webview *w = struct webview *w =
@@ -1976,17 +1927,12 @@ static void webview_run_input_open_panel(id self, SEL cmd, id webview,
class_addMethod(webViewDelegateClass, class_addMethod(webViewDelegateClass,
sel_registerName("webView:didClearWindowObject:forFrame:"), sel_registerName("webView:didClearWindowObject:forFrame:"),
(IMP)webview_did_clear_window_object, "v@:@@@"); (IMP)webview_did_clear_window_object, "v@:@@@");
class_addMethod(
webViewDelegateClass,
sel_registerName("webView:runOpenPanelForFileButtonWithResultListener:"
"allowMultipleFiles:"),
(IMP)webview_run_input_open_panel, "v@:@@c");
class_addMethod(webViewDelegateClass, sel_registerName("invoke:"), class_addMethod(webViewDelegateClass, sel_registerName("invoke:"),
(IMP)webview_external_invoke, "v@:@"); (IMP)webview_external_invoke, "v@:@");
objc_registerClassPair(webViewDelegateClass); objc_registerClassPair(webViewDelegateClass);
w->priv.delegate = [[webViewDelegateClass alloc] init]; w->priv.windowDelegate = [[webViewDelegateClass alloc] init];
objc_setAssociatedObject(w->priv.delegate, "webview", (id)(w), objc_setAssociatedObject(w->priv.windowDelegate, "webview", (id)(w),
OBJC_ASSOCIATION_ASSIGN); OBJC_ASSOCIATION_ASSIGN);
NSRect r = NSMakeRect(0, 0, w->width, w->height); NSRect r = NSMakeRect(0, 0, w->width, w->height);
@@ -2014,7 +1960,7 @@ static void webview_run_input_open_panel(id self, SEL cmd, id webview,
NSString *nsTitle = [NSString stringWithUTF8String:w->title]; NSString *nsTitle = [NSString stringWithUTF8String:w->title];
[w->priv.window setTitle:nsTitle]; [w->priv.window setTitle:nsTitle];
[w->priv.window setDelegate:w->priv.delegate]; [w->priv.window setDelegate:w->priv.windowDelegate];
[w->priv.window center]; [w->priv.window center];
// NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wat"]; // NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wat"];
@@ -2043,8 +1989,7 @@ static void webview_run_input_open_panel(id self, SEL cmd, id webview,
[w->priv.webview setAutoresizesSubviews:YES]; [w->priv.webview setAutoresizesSubviews:YES];
[w->priv.webview [w->priv.webview
setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
w->priv.webview.frameLoadDelegate = w->priv.delegate; w->priv.webview.frameLoadDelegate = w->priv.windowDelegate;
w->priv.webview.UIDelegate = w->priv.delegate;
[[w->priv.window contentView] addSubview:w->priv.webview]; [[w->priv.window contentView] addSubview:w->priv.webview];
[w->priv.window orderFrontRegardless]; [w->priv.window orderFrontRegardless];

View File

@@ -95,6 +95,13 @@ function startBridge() {
window.wailsbridge.reconnectOverlay.style.display = 'none'; window.wailsbridge.reconnectOverlay.style.display = 'none';
} }
// Bridge external.invoke
window.external = {
invoke: function (msg) {
window.wailsbridge.websocket.send(msg);
}
};
// Adds a script to the Dom. // Adds a script to the Dom.
// Removes it if second parameter is true. // Removes it if second parameter is true.
function addScript(script, remove) { function addScript(script, remove) {
@@ -207,4 +214,4 @@ function Init(callback) {
start(callback); start(callback);
} }
module.exports = Init; module.exports = Init;

File diff suppressed because one or more lines are too long

View File

@@ -15,7 +15,10 @@
"error", "error",
"tab" "tab"
], ],
"linebreak-style": 0, "linebreak-style": [
"error",
"unix"
],
"quotes": [ "quotes": [
"error", "error",
"single" "single"
@@ -25,4 +28,4 @@
"always" "always"
] ]
} }
} }

View File

@@ -15,11 +15,7 @@ The lightweight framework for web-like apps
* @param {string} message * @param {string} message
*/ */
function Invoke(message) { function Invoke(message) {
if ( window.wailsbridge ) { window.external.invoke(message);
window.wailsbridge.websocket.send(message);
} else {
window.external.invoke(message);
}
} }
/** /**

View File

@@ -46,16 +46,6 @@ var runtime = {
// Augment global // Augment global
Object.assign(window.wails, runtime); Object.assign(window.wails, runtime);
// Setup global error handler
window.onerror = function (msg, url, lineNo, columnNo, error) {
window.wails.Log.Error('**** Caught Unhandled Error ****');
window.wails.Log.Error('Message: ' + msg);
window.wails.Log.Error('URL: ' + url);
window.wails.Log.Error('Line No: ' + lineNo);
window.wails.Log.Error('Column No: ' + columnNo);
window.wails.Log.Error('error: ' + error);
};
// Emit loaded event // Emit loaded event
Emit('wails:loaded'); Emit('wails:loaded');

View File

@@ -32,6 +32,6 @@ function OpenFile(filename) {
} }
module.exports = { module.exports = {
OpenURL: OpenURL, OpenURL,
OpenFile: OpenFile OpenFile
}; };

View File

@@ -80,10 +80,10 @@ function Acknowledge(eventName) {
} }
module.exports = { module.exports = {
OnMultiple: OnMultiple, OnMultiple,
On: On, On,
Once: Once, Once,
Emit: Emit, Emit,
Heartbeat: Heartbeat, Heartbeat,
Acknowledge: Acknowledge Acknowledge
}; };

View File

@@ -62,9 +62,9 @@ function Fatal(message) {
} }
module.exports = { module.exports = {
Debug: Debug, Debug,
Info: Info, Info,
Warning: Warning, Warning,
Error: Error, Error,
Fatal: Fatal Fatal
}; };

View File

@@ -15,8 +15,8 @@ const Events = require('./events');
const Init = require('./init'); const Init = require('./init');
module.exports = { module.exports = {
Log: Log, Log,
Browser: Browser, Browser,
Events: Events, Events,
Init: Init Init
}; };

View File

@@ -1,6 +1,6 @@
{ {
"name": "@wailsapp/runtime", "name": "@wailsapp/runtime",
"version": "1.0.9", "version": "1.0.6",
"description": "Wails Javascript runtime library", "description": "Wails Javascript runtime library",
"main": "main.js", "main": "main.js",
"types": "runtime.d.ts", "types": "runtime.d.ts",

View File

@@ -1,54 +1,6 @@
package runtime package runtime
import ( import "github.com/wailsapp/wails/lib/interfaces"
"bytes"
"runtime"
"github.com/abadojack/whatlanggo"
"github.com/wailsapp/wails/lib/interfaces"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/encoding/korean"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)
func detectEncoding(text string) (encoding.Encoding, string) {
// korean
var enc encoding.Encoding
info := whatlanggo.Detect(text)
//fmt.Println("Language:", info.Lang.String(), " Script:", whatlanggo.Scripts[info.Script], " Confidence: ", info.Confidence)
switch info.Lang.String() {
case "Korean":
enc = korean.EUCKR
case "Mandarin":
enc = simplifiedchinese.GBK
case "Japanese":
enc = japanese.EUCJP
}
return enc, info.Lang.String()
}
// ProcessEncoding attempts to convert CKJ strings to UTF-8
func ProcessEncoding(text string) string {
if runtime.GOOS != "windows" {
return text
}
encoding, _ := detectEncoding(text)
if encoding != nil {
var bufs bytes.Buffer
wr := transform.NewWriter(&bufs, encoding.NewEncoder())
_, err := wr.Write([]byte(text))
defer wr.Close()
if err != nil {
return ""
}
return bufs.String()
}
return text
}
// Window exposes an interface for manipulating the window // Window exposes an interface for manipulating the window
type Window struct { type Window struct {
@@ -79,7 +31,6 @@ func (r *Window) UnFullscreen() {
// SetTitle sets the the window title // SetTitle sets the the window title
func (r *Window) SetTitle(title string) { func (r *Window) SetTitle(title string) {
title = ProcessEncoding(title)
r.renderer.SetTitle(title) r.renderer.SetTitle(title)
} }

View File

@@ -1,84 +0,0 @@
package main
import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
)
// Default target to run when none is specified
// If not set, running mage will list available targets
// var Default = Build
/*
# Build runtime
echo "**** Building Runtime ****"
cd runtime/js
npm install
npm run build
cd ../..
echo "**** Packing Assets ****"
cd cmd
mewn
cd ..
cd lib/renderer
mewn
cd ../..
echo "**** Installing Wails locally ****"
cd cmd/wails
go install
cd ../..
echo "**** Tidying the mods! ****"
go mod tidy
echo "**** WE ARE DONE! ****"
*/
func runCommand(command string, args ...string) {
cmd := exec.Command(command, args...)
output, err := cmd.CombinedOutput()
if err != nil {
log.Println(string(output))
log.Fatal(err)
}
cmd.Run()
fmt.Println(string(output))
}
// A build step that requires additional params, or platform specific steps for example
func main() {
dir, _ := os.Getwd()
// Build Runtime
fmt.Println("**** Building Runtime ****")
runtimeDir, _ := filepath.Abs(filepath.Join(dir, "..", "runtime", "js"))
os.Chdir(runtimeDir)
runCommand("npm", "install")
runCommand("npm", "run", "build")
// Pack assets
fmt.Println("**** Packing Assets ****")
rendererDir, _ := filepath.Abs(filepath.Join(dir, "..", "lib", "renderer"))
os.Chdir(rendererDir)
runCommand("mewn")
cmdDir, _ := filepath.Abs(filepath.Join(dir, "..", "cmd"))
os.Chdir(cmdDir)
runCommand("mewn")
// Install Wails
fmt.Println("**** Installing Wails locally ****")
execDir, _ := filepath.Abs(filepath.Join(dir, "..", "cmd", "wails"))
os.Chdir(execDir)
runCommand("go", "install")
baseDir, _ := filepath.Abs(filepath.Join(dir, ".."))
os.Chdir(baseDir)
runCommand("go", "mod", "tidy")
}