Compare commits

..

2 Commits

Author SHA1 Message Date
Lea Anthony
a3a13e5a0a Tidy go modules 2020-02-22 14:34:26 +11:00
Lea Anthony
5ea8287f1b Implement verbose output
Works for build and serve
2020-02-22 14:33:27 +11:00
50 changed files with 1699 additions and 2564 deletions

View File

@@ -13,10 +13,10 @@ jobs:
os: [ubuntu-latest, windows-latest, macOS-latest] os: [ubuntu-latest, windows-latest, macOS-latest]
steps: steps:
- name: Set up Go 1.13 - name: Set up Go 1.12
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: 1.13 go-version: 1.12
id: go id: go
- name: Check out code into the Go module directory - name: Check out code into the Go module directory
@@ -27,6 +27,6 @@ jobs:
go get -v -d ./... go get -v -d ./...
- name: Build - name: Build
run: go build -v ./cmd/wails run: go build -v ./cmd/wails
- name: Test - name: Test
run: ./wails version run: ./wails version

View File

@@ -13,10 +13,10 @@ jobs:
os: [ubuntu-latest, windows-latest, macOS-latest] os: [ubuntu-latest, windows-latest, macOS-latest]
steps: steps:
- name: Set up Go 1.13 - name: Set up Go 1.12
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: 1.13 go-version: 1.12
id: go id: go
- name: Check out code into the Go module directory - name: Check out code into the Go module directory
@@ -27,6 +27,6 @@ jobs:
go get -v -d ./... go get -v -d ./...
- name: Build - name: Build
run: go build -v ./cmd/wails run: go build -v ./cmd/wails
- name: Test - name: Test
run: ./wails version run: ./wails version

View File

@@ -4,7 +4,7 @@ on:
branches: branches:
- master - master
tags: tags:
- '!**pre**' - '!**pre**'
jobs: jobs:
build: build:
@@ -15,10 +15,10 @@ jobs:
os: [ubuntu-latest, windows-latest, macOS-latest] os: [ubuntu-latest, windows-latest, macOS-latest]
steps: steps:
- name: Set up Go 1.13 - name: Set up Go 1.12
uses: actions/setup-go@v1 uses: actions/setup-go@v1
with: with:
go-version: 1.13 go-version: 1.12
id: go id: go
- name: Check out code into the Go module directory - name: Check out code into the Go module directory
@@ -29,6 +29,6 @@ jobs:
go get -v -d ./... go get -v -d ./...
- name: Build - name: Build
run: go build -v ./cmd/wails run: go build -v ./cmd/wails
- name: Test - name: Test
run: ./wails version run: ./wails version

View File

@@ -15,19 +15,11 @@ Wails is what it is because of the time and effort given by these great people.
* [admin_3.exe](https://github.com/bh90210) * [admin_3.exe](https://github.com/bh90210)
* [iceleo-com](https://github.com/iceleo-com) * [iceleo-com](https://github.com/iceleo-com)
* [fallendusk](https://github.com/fallendusk) * [fallendusk](https://github.com/fallendusk)
* [Florian Didran](https://github.com/fdidron)
* [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) * [Kris Raney](https://github.com/kraney)
* [Jack Mordaunt](https://github.com/JackMordaunt) * [Jack Mordaunt](https://github.com/JackMordaunt)
* [Michael Hipp](https://github.com/MichaelHipp) * [Michael Hipp](https://github.com/MichaelHipp)
* [Travis McLane](https://github.com/tmclane) * [Travis McLane](https://github.com/tmclane)
* [Reuben Thomas-Davis](https://github.com/Rested)
* [Jarek](https://github.com/Jarek-SRT)
* [Konez2k](https://github.com/konez2k)
* [msms](https://github.com/sayuthisobri)
* [dedo1911](https://github.com/dedo1911)
* [Florian Didron](https://github.com/fdidron)
* [Christopher Murphy](https://github.com/Splode)
* [Zámbó, Levente](https://github.com/Lyimmi)
* [artem](https://github.com/Unix4ever)

View File

@@ -36,7 +36,7 @@ The official docs can be found at [https://wails.app](https://wails.app).
Wails uses cgo to bind to the native rendering engines so a number of platform dependent libraries are needed as well as an installation of Go. The basic requirements are: Wails uses cgo to bind to the native rendering engines so a number of platform dependent libraries are needed as well as an installation of Go. The basic requirements are:
- Go 1.13 - Go 1.12
- npm - npm
### MacOS ### MacOS
@@ -55,9 +55,9 @@ _Debian: 8, 9, 10_
_Ubuntu: 16.04, 18.04, 19.04_ _Ubuntu: 16.04, 18.04, 19.04_
_Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_, Pop!_OS _Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_
#### Arch Linux / ArchLabs #### Arch Linux
`sudo pacman -S webkit2gtk gtk3` `sudo pacman -S webkit2gtk gtk3`

View File

@@ -1,4 +1,4 @@
// +build linux darwin !windows // +build +linux +darwin !windows
package wails package wails

File diff suppressed because one or more lines are too long

View File

@@ -12,7 +12,6 @@ import (
"path" "path"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"github.com/leaanthony/slicer" "github.com/leaanthony/slicer"
) )
@@ -48,22 +47,6 @@ func (fs *FSHelper) FileExists(path string) bool {
return fi.Mode().IsRegular() return fi.Mode().IsRegular()
} }
// FindFile returns the first occurrence of match inside path.
func (fs *FSHelper) FindFile(path, match string) (string, error) {
files, err := ioutil.ReadDir(path)
if err != nil {
return "", err
}
for _, f := range files {
if !f.IsDir() && strings.Contains(f.Name(), match) {
return f.Name(), nil
}
}
return "", fmt.Errorf("file not found")
}
// CreateFile creates a file at the given filename location with the contents // CreateFile creates a file at the given filename location with the contents
// set to the given data. It will create intermediary directories if needed. // set to the given data. It will create intermediary directories if needed.
func (fs *FSHelper) CreateFile(filename string, data []byte) error { func (fs *FSHelper) CreateFile(filename string, data []byte) error {
@@ -117,10 +100,10 @@ func (fs *FSHelper) RemoveFile(filename string) error {
} }
// RemoveFiles removes the given filenames // RemoveFiles removes the given filenames
func (fs *FSHelper) RemoveFiles(files []string, continueOnError bool) error { func (fs *FSHelper) RemoveFiles(files []string) error {
for _, filename := range files { for _, filename := range files {
err := os.Remove(filename) err := os.Remove(filename)
if err != nil && !continueOnError { if err != nil {
return err return err
} }
} }

View File

@@ -5,15 +5,12 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
"os/user"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv"
"strings" "strings"
"time" "time"
"github.com/leaanthony/mewn" "github.com/leaanthony/mewn"
"github.com/leaanthony/mewn/lib"
"github.com/leaanthony/slicer" "github.com/leaanthony/slicer"
"github.com/leaanthony/spinner" "github.com/leaanthony/spinner"
) )
@@ -59,141 +56,21 @@ func InstallGoDependencies(verbose bool) error {
return nil return nil
} }
// EmbedAssets will embed the built frontend assets via mewn. // BuildApplication will attempt to build the project based on the given inputs
func EmbedAssets() ([]string, error) { func BuildApplication(binaryName string, forceRebuild bool, buildMode string, packageApp bool, projectOptions *ProjectOptions) error {
mewnFiles := lib.GetMewnFiles([]string{}, false)
referencedAssets, err := lib.GetReferencedAssets(mewnFiles) // Generate Windows assets if needed
if err != nil { if runtime.GOOS == "windows" {
return []string{}, err cleanUp := !packageApp
} err := NewPackageHelper().PackageWindows(projectOptions, cleanUp)
targetFiles := []string{}
for _, referencedAsset := range referencedAssets {
packfileData, err := lib.GeneratePackFileString(referencedAsset, false)
if err != nil { if err != nil {
return []string{}, err return err
} }
targetFile := filepath.Join(referencedAsset.BaseDir, referencedAsset.PackageName+"-mewn.go")
targetFiles = append(targetFiles, targetFile)
ioutil.WriteFile(targetFile, []byte(packfileData), 0644)
} }
return targetFiles, nil
}
func InitializeCrossCompilation(verbose bool) error {
// Check Docker
if err := CheckIfInstalled("docker"); err != nil {
return err
}
var packSpinner *spinner.Spinner
if !verbose {
packSpinner = spinner.New("Pulling wailsapp/xgo:latest docker image... (may take a while)")
packSpinner.SetSpinSpeed(50)
packSpinner.Start()
} else {
println("Pulling wailsapp/xgo:latest docker image... (may take a while)")
}
err := NewProgramHelper(verbose).RunCommandArray([]string{"docker",
"pull", "wailsapp/xgo:latest"})
if err != nil {
if packSpinner != nil {
packSpinner.Error()
}
return err
}
if packSpinner != nil {
packSpinner.Success()
}
return nil
}
// BuildDocker builds the project using the cross compiling wailsapp/xgo:latest container
func BuildDocker(binaryName string, buildMode string, projectOptions *ProjectOptions) error {
var packSpinner *spinner.Spinner
if buildMode == BuildModeBridge {
return fmt.Errorf("you cant serve the application in cross-compilation")
}
// Check build directory
buildDirectory := filepath.Join(fs.Cwd(), "build")
if !fs.DirExists(buildDirectory) {
fs.MkDir(buildDirectory)
}
buildCommand := slicer.String()
userid := 1000
user, _ := user.Current()
if i, err := strconv.Atoi(user.Uid); err == nil {
userid = i
}
for _, arg := range []string{
"docker",
"run",
"--rm",
"-v", fmt.Sprintf("%s:/build", filepath.Join(fs.Cwd(), "build")),
"-v", fmt.Sprintf("%s:/source", fs.Cwd()),
"-e", fmt.Sprintf("LOCAL_USER_ID=%v", userid),
"-e", fmt.Sprintf("FLAG_LDFLAGS=%s", ldFlags(projectOptions, buildMode)),
"-e", "FLAG_V=false",
"-e", "FLAG_X=false",
"-e", "FLAG_RACE=false",
"-e", "FLAG_BUILDMODE=default",
"-e", "FLAG_TRIMPATH=false",
"-e", fmt.Sprintf("TARGETS=%s", projectOptions.Platform+"/"+projectOptions.Architecture),
"-e", "GOPROXY=",
"-e", "GO111MODULE=on",
"wailsapp/xgo:latest",
".",
} {
buildCommand.Add(arg)
}
compileMessage := fmt.Sprintf(
"Packing + Compiling project for %s/%s using docker image wailsapp/xgo:latest",
projectOptions.Platform, projectOptions.Architecture)
if buildMode == BuildModeDebug {
compileMessage += " (Debug Mode)"
}
if !projectOptions.Verbose {
packSpinner = spinner.New(compileMessage + "...")
packSpinner.SetSpinSpeed(50)
packSpinner.Start()
} else {
println(compileMessage)
}
err := NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
if err != nil {
if packSpinner != nil {
packSpinner.Error()
}
return err
}
if packSpinner != nil {
packSpinner.Success()
}
return nil
}
// BuildNative builds on the target platform itself.
func BuildNative(binaryName string, forceRebuild bool, buildMode string, projectOptions *ProjectOptions) error {
// Check Mewn is installed // Check Mewn is installed
if err := CheckMewn(projectOptions.Verbose); err != nil { err := CheckMewn(projectOptions.Verbose)
return err if err != nil {
}
if err := CheckWindres(); err != nil {
return err return err
} }
@@ -213,17 +90,18 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
} }
buildCommand := slicer.String() buildCommand := slicer.String()
buildCommand.Add("go") buildCommand.Add("mewn")
buildCommand.Add("build")
if buildMode == BuildModeBridge { if buildMode == BuildModeBridge {
// Ignore errors // Ignore errors
buildCommand.Add("-i") buildCommand.Add("-i")
} }
buildCommand.Add("build")
if binaryName != "" { if binaryName != "" {
// Alter binary name based on OS // Alter binary name based on OS
switch projectOptions.Platform { switch runtime.GOOS {
case "windows": case "windows":
if !strings.HasSuffix(binaryName, ".exe") { if !strings.HasSuffix(binaryName, ".exe") {
binaryName += ".exe" binaryName += ".exe"
@@ -233,7 +111,7 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
binaryName = strings.TrimSuffix(binaryName, ".exe") binaryName = strings.TrimSuffix(binaryName, ".exe")
} }
} }
buildCommand.Add("-o", filepath.Join("build", binaryName)) buildCommand.Add("-o", binaryName)
} }
// If we are forcing a rebuild // If we are forcing a rebuild
@@ -241,13 +119,31 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
buildCommand.Add("-a") buildCommand.Add("-a")
} }
buildCommand.AddSlice([]string{"-ldflags", ldFlags(projectOptions, buildMode)}) // Setup ld flags
ldflags := "-w -s "
if projectOptions.Verbose { if buildMode == BuildModeDebug {
fmt.Printf("Command: %v\n", buildCommand.AsSlice()) ldflags = ""
} }
err := NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice()) // Add windows flags
if runtime.GOOS == "windows" && buildMode == BuildModeProd {
ldflags += "-H windowsgui "
}
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
// If we wish to generate typescript
if projectOptions.typescriptDefsFilename != "" {
cwd, err := os.Getwd()
if err != nil {
return err
}
filename := filepath.Join(cwd, projectOptions.FrontEnd.Dir, projectOptions.typescriptDefsFilename)
ldflags += " -X github.com/wailsapp/wails/lib/binding.typescriptDefinitionFilename=" + filename
}
buildCommand.AddSlice([]string{"-ldflags", ldflags})
err = NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
if err != nil { if err != nil {
if packSpinner != nil { if packSpinner != nil {
packSpinner.Error() packSpinner.Error()
@@ -258,57 +154,7 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
packSpinner.Success() packSpinner.Success()
} }
return nil // packageApp
}
// BuildApplication will attempt to build the project based on the given inputs
func BuildApplication(binaryName string, forceRebuild bool, buildMode string, packageApp bool, projectOptions *ProjectOptions) error {
var err error
// embed resources
targetFiles, err := EmbedAssets()
if err != nil {
return err
}
if projectOptions.CrossCompile {
if err := InitializeCrossCompilation(projectOptions.Verbose); err != nil {
return err
}
}
helper := NewPackageHelper(projectOptions.Platform)
// Generate windows resources
if projectOptions.Platform == "windows" {
if err := helper.PackageWindows(projectOptions, false); err != nil {
return err
}
}
// cleanup temporary embedded assets
defer func() {
for _, filename := range targetFiles {
if err := os.Remove(filename); err != nil {
fmt.Println(err)
}
}
// Removed by popular demand
// TODO: Potentially add a flag to cleanup
// if projectOptions.Platform == "windows" {
// helper.CleanWindows(projectOptions)
// }
}()
if projectOptions.CrossCompile {
err = BuildDocker(binaryName, buildMode, projectOptions)
} else {
err = BuildNative(binaryName, forceRebuild, buildMode, projectOptions)
}
if err != nil {
return err
}
if packageApp { if packageApp {
err = PackageApplication(projectOptions) err = PackageApplication(projectOptions)
if err != nil { if err != nil {
@@ -321,14 +167,22 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
// PackageApplication will attempt to package the application in a platform dependent way // PackageApplication will attempt to package the application in a platform dependent way
func PackageApplication(projectOptions *ProjectOptions) error { func PackageApplication(projectOptions *ProjectOptions) error {
// Package app
message := "Generating .app"
if runtime.GOOS == "windows" {
err := CheckWindres()
if err != nil {
return err
}
message = "Generating resource bundle"
}
var packageSpinner *spinner.Spinner var packageSpinner *spinner.Spinner
if projectOptions.Verbose { if projectOptions.Verbose {
packageSpinner = spinner.New("Packaging application...") packageSpinner = spinner.New(message)
packageSpinner.SetSpinSpeed(50) packageSpinner.SetSpinSpeed(50)
packageSpinner.Start() packageSpinner.Start()
} }
err := NewPackageHelper().Package(projectOptions)
err := NewPackageHelper(projectOptions.Platform).Package(projectOptions)
if err != nil { if err != nil {
if packageSpinner != nil { if packageSpinner != nil {
packageSpinner.Error() packageSpinner.Error()
@@ -390,7 +244,7 @@ func CheckMewn(verbose bool) (err error) {
// CheckWindres checks if Windres is installed and if not, aborts // CheckWindres checks if Windres is installed and if not, aborts
func CheckWindres() (err error) { func CheckWindres() (err error) {
if runtime.GOOS != "windows" { // FIXME: Handle windows cross-compile for windows! if runtime.GOOS != "windows" {
return nil return nil
} }
programHelper := NewProgramHelper() programHelper := NewProgramHelper()
@@ -400,15 +254,6 @@ func CheckWindres() (err error) {
return nil return nil
} }
// CheckIfInstalled returns if application is installed
func CheckIfInstalled(application string) (err error) {
programHelper := NewProgramHelper()
if !programHelper.IsInstalled(application) {
return fmt.Errorf("%s not installed. Ensure you have installed %s correctly", application, application)
}
return nil
}
// InstallFrontendDeps attempts to install the frontend dependencies based on the given options // InstallFrontendDeps attempts to install the frontend dependencies based on the given options
func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forceRebuild bool, caller string) error { func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forceRebuild bool, caller string) error {
@@ -532,7 +377,7 @@ func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
logger.Green(">>>>> To connect, you will need to run '" + projectOptions.FrontEnd.Serve + "' in the '" + projectOptions.FrontEnd.Dir + "' directory <<<<<") logger.Green(">>>>> To connect, you will need to run '" + projectOptions.FrontEnd.Serve + "' in the '" + projectOptions.FrontEnd.Dir + "' directory <<<<<")
}() }()
location, err := filepath.Abs(filepath.Join("build", projectOptions.BinaryName)) location, err := filepath.Abs(projectOptions.BinaryName)
if err != nil { if err != nil {
return err return err
} }
@@ -548,33 +393,3 @@ func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
return nil return nil
} }
func ldFlags(po *ProjectOptions, buildMode string) string {
// Setup ld flags
ldflags := "-w -s "
if buildMode == BuildModeDebug {
ldflags = ""
}
// Add windows flags
if po.Platform == "windows" && buildMode == BuildModeProd {
ldflags += "-H windowsgui "
}
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
// Add additional ldflags passed in via the `ldflags` cli flag
if len(po.LdFlags) > 0 {
ldflags += " " + po.LdFlags
}
// If we wish to generate typescript
if po.typescriptDefsFilename != "" {
cwd, err := os.Getwd()
if err == nil {
filename := filepath.Join(cwd, po.FrontEnd.Dir, po.typescriptDefsFilename)
ldflags += " -X github.com/wailsapp/wails/lib/binding.typescriptDefinitionFilename=" + filename
}
}
return ldflags
}

View File

@@ -53,16 +53,6 @@ const (
Deepin Deepin
// Raspbian distribution // Raspbian distribution
Raspbian Raspbian
// Tumbleweed (OpenSUSE) distribution
Tumbleweed
// Leap (OpenSUSE) distribution
Leap
// ArchLabs distribution
ArchLabs
// PopOS distribution
PopOS
// Solus distribution
Solus
) )
// DistroInfo contains all the information relating to a linux distribution // DistroInfo contains all the information relating to a linux distribution
@@ -111,7 +101,7 @@ func parseOsRelease(osRelease string) *DistroInfo {
} }
switch splitLine[0] { switch splitLine[0] {
case "ID": case "ID":
osID = strings.ToLower(strings.Trim(splitLine[1], "\"")) osID = strings.Trim(splitLine[1], "\"")
case "NAME": case "NAME":
osNAME = strings.Trim(splitLine[1], "\"") osNAME = strings.Trim(splitLine[1], "\"")
case "VERSION_ID": case "VERSION_ID":
@@ -127,8 +117,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
result.Distribution = CentOS result.Distribution = CentOS
case "arch": case "arch":
result.Distribution = Arch result.Distribution = Arch
case "archlabs":
result.Distribution = ArchLabs
case "debian": case "debian":
result.Distribution = Debian result.Distribution = Debian
case "ubuntu": case "ubuntu":
@@ -159,14 +147,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
result.Distribution = Deepin result.Distribution = Deepin
case "raspbian": case "raspbian":
result.Distribution = Raspbian result.Distribution = Raspbian
case "opensuse-tumbleweed":
result.Distribution = Tumbleweed
case "opensuse-leap":
result.Distribution = Leap
case "pop":
result.Distribution = PopOS
case "solus":
result.Distribution = Solus
default: default:
result.Distribution = Unknown result.Distribution = Unknown
} }
@@ -203,17 +183,6 @@ func DpkgInstalled(packageName string) (bool, error) {
return exitCode == 0, nil return exitCode == 0, nil
} }
// EOpkgInstalled uses dpkg to see if a package is installed
func EOpkgInstalled(packageName string) (bool, error) {
program := NewProgramHelper()
eopkg := program.FindProgram("eopkg")
if eopkg == nil {
return false, fmt.Errorf("cannot check dependencies: eopkg not found")
}
stdout, _, _, _ := eopkg.Run("info", packageName)
return strings.HasPrefix(stdout, "Installed"), nil
}
// PacmanInstalled uses pacman to see if a package is installed. // PacmanInstalled uses pacman to see if a package is installed.
func PacmanInstalled(packageName string) (bool, error) { func PacmanInstalled(packageName string) (bool, error) {
program := NewProgramHelper() program := NewProgramHelper()
@@ -285,9 +254,5 @@ func RequestSupportForDistribution(distroInfo *DistroInfo) error {
fmt.Println("Opening browser to file request.") fmt.Println("Opening browser to file request.")
browser.OpenURL(fullURL + url.PathEscape(params)) browser.OpenURL(fullURL + url.PathEscape(params))
result = Prompt("We have a guide for adding support for your distribution. Would you like to view it?", "yes")
if strings.ToLower(result) == "yes" {
browser.OpenURL("https://wails.app/guides/distro/")
}
return nil return nil
} }

View File

@@ -22,25 +22,5 @@ UBUNTU_CODENAME=bionic
if result.Distribution != Ubuntu { if result.Distribution != Ubuntu {
t.Errorf("expected 'Ubuntu' ID but got '%d'", result.Distribution) t.Errorf("expected 'Ubuntu' ID but got '%d'", result.Distribution)
} }
}
func TestTumbleweedDetection(t *testing.T) {
osrelease := `
NAME="openSUSE Tumbleweed"
# VERSION="20200414"
ID="opensuse-tumbleweed"
ID_LIKE="opensuse suse"
VERSION_ID="20200414"
PRETTY_NAME="openSUSE Tumbleweed"
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:opensuse:tumbleweed:20200414"
BUG_REPORT_URL="https://bugs.opensuse.org"
HOME_URL="https://www.opensuse.org/"
LOGO="distributor-logo"
`
result := parseOsRelease(osrelease)
if result.Distribution != Tumbleweed {
t.Errorf("expected 'Tumbleweed' ID but got '%d'", result.Distribution)
}
} }

View File

@@ -28,15 +28,6 @@ distributions:
gccversioncommand: &gccdumpfullversion -dumpfullversion gccversioncommand: &gccdumpfullversion -dumpfullversion
programs: *debiandefaultprograms programs: *debiandefaultprograms
libraries: *debiandefaultlibraries libraries: *debiandefaultlibraries
pop:
id: pop
releases:
default:
version: default
name: Pop!_OS
gccversioncommand: &gccdumpfullversion -dumpfullversion
programs: *debiandefaultprograms
libraries: *debiandefaultlibraries
kali: kali:
id: kali id: kali
releases: releases:
@@ -185,15 +176,6 @@ distributions:
gccversioncommand: *gccdumpversion gccversioncommand: *gccdumpversion
programs: *archdefaultprograms programs: *archdefaultprograms
libraries: *archdefaultlibraries libraries: *archdefaultlibraries
archlabs:
id: archlabs
releases:
default:
version: default
name: ArchLabs
gccversioncommand: *gccdumpversion
programs: *archdefaultprograms
libraries: *archdefaultlibraries
manjaro: manjaro:
id: manjaro id: manjaro
releases: releases:
@@ -241,51 +223,3 @@ distributions:
gccversioncommand: *gccdumpfullversion gccversioncommand: *gccdumpfullversion
programs: *debiandefaultprograms programs: *debiandefaultprograms
libraries: *debiandefaultlibraries libraries: *debiandefaultlibraries
solus:
id: solus
releases:
default:
version: default
name: Solus
gccversioncommand: *gccdumpfullversion
programs: &solusdefaultprograms
- name: gcc
help: Please install with `sudo eopkg it -c system.devel` and try again
- name: pkg-config
help: Please install with `sudo eopkg it -c system.devel` and try again
- name: npm
help: Please install with `sudo eopkg it nodejs` and try again
libraries: &solusdefaultlibraries
- name: libgtk-3-devel
help: Please install with `sudo eopkg it libgtk-3-devel` and try again
- name: libwebkit-gtk-devel
help: Please install with `sudo eopkg it libwebkit-gtk-devel` and try again
opensuse-tumbleweed:
id: opensuse-tumbleweed
releases:
default:
version: default
name: openSUSE Tumbleweed
gccversioncommand: *gccdumpfullversion
programs: &opensusedefaultprograms
- name: gcc
help: Please install with `sudo zypper in gcc-c++` and try again
- name: pkg-config
help: Please install with `sudo zypper in pkgconf-pkg-config` and try again
- name: npm
help: Please install `sudo zypper in nodejs` and try again
libraries: &opensusedefaultlibraries
- name: gtk3-devel
help: Please install with `sudo zypper in gtk3-devel` and try again
- name: webkit2gtk3-devel
help: Please install with `sudo zypper in webkit2gtk3-devel` and try again
opensuse-leap:
id: opensuse-leap
releases:
default:
version: default
name: openSUSE Leap
gccversioncommand: *gccdumpfullversion
programs: *opensusedefaultprograms
libraries: *opensusedefaultlibraries

View File

@@ -1,12 +1,9 @@
package cmd package cmd
import ( import (
"bufio"
"bytes" "bytes"
"encoding/binary"
"fmt" "fmt"
"image" "image"
"image/png"
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
@@ -17,24 +14,21 @@ import (
"time" "time"
"github.com/jackmordaunt/icns" "github.com/jackmordaunt/icns"
"golang.org/x/image/draw"
) )
// PackageHelper helps with the 'wails package' command // PackageHelper helps with the 'wails package' command
type PackageHelper struct { type PackageHelper struct {
platform string fs *FSHelper
fs *FSHelper log *Logger
log *Logger system *SystemHelper
system *SystemHelper
} }
// NewPackageHelper creates a new PackageHelper! // NewPackageHelper creates a new PackageHelper!
func NewPackageHelper(platform string) *PackageHelper { func NewPackageHelper() *PackageHelper {
return &PackageHelper{ return &PackageHelper{
platform: platform, fs: NewFSHelper(),
fs: NewFSHelper(), log: NewLogger(),
log: NewLogger(), system: NewSystemHelper(),
system: NewSystemHelper(),
} }
} }
@@ -59,111 +53,6 @@ func newPlistData(title, exe, packageID, version, author string) *plistData {
} }
} }
type windowsIcoHeader struct {
_ uint16
imageType uint16
imageCount uint16
}
type windowsIcoDescriptor struct {
width uint8
height uint8
colours uint8
_ uint8
planes uint16
bpp uint16
size uint32
offset uint32
}
type windowsIcoContainer struct {
Header windowsIcoDescriptor
Data []byte
}
func generateWindowsIcon(pngFilename string, iconfile string) error {
sizes := []int{256, 128, 64, 48, 32, 16}
pngfile, err := os.Open(pngFilename)
if err != nil {
return err
}
defer pngfile.Close()
pngdata, err := png.Decode(pngfile)
if err != nil {
return err
}
icons := []windowsIcoContainer{}
for _, size := range sizes {
rect := image.Rect(0, 0, int(size), int(size))
rawdata := image.NewRGBA(rect)
scale := draw.CatmullRom
scale.Scale(rawdata, rect, pngdata, pngdata.Bounds(), draw.Over, nil)
icondata := new(bytes.Buffer)
writer := bufio.NewWriter(icondata)
err = png.Encode(writer, rawdata)
if err != nil {
return err
}
writer.Flush()
imgSize := size
if imgSize >= 256 {
imgSize = 0
}
data := icondata.Bytes()
icn := windowsIcoContainer{
Header: windowsIcoDescriptor{
width: uint8(imgSize),
height: uint8(imgSize),
planes: 1,
bpp: 32,
size: uint32(len(data)),
},
Data: data,
}
icons = append(icons, icn)
}
outfile, err := os.Create(iconfile)
if err != nil {
return err
}
defer outfile.Close()
ico := windowsIcoHeader{
imageType: 1,
imageCount: uint16(len(sizes)),
}
err = binary.Write(outfile, binary.LittleEndian, ico)
if err != nil {
return err
}
offset := uint32(6 + 16*len(sizes))
for _, icon := range icons {
icon.Header.offset = offset
err = binary.Write(outfile, binary.LittleEndian, icon.Header)
if err != nil {
return err
}
offset += icon.Header.size
}
for _, icon := range icons {
_, err = outfile.Write(icon.Data)
if err != nil {
return err
}
}
return nil
}
func defaultString(val string, defaultVal string) string { func defaultString(val string, defaultVal string) string {
if val != "" { if val != "" {
return val return val
@@ -174,30 +63,29 @@ func defaultString(val string, defaultVal string) string {
func (b *PackageHelper) getPackageFileBaseDir() string { func (b *PackageHelper) getPackageFileBaseDir() string {
// Calculate template base dir // Calculate template base dir
_, filename, _, _ := runtime.Caller(1) _, filename, _, _ := runtime.Caller(1)
return filepath.Join(path.Dir(filename), "packages", b.platform) return filepath.Join(path.Dir(filename), "packages", runtime.GOOS)
} }
// Package the application into a platform specific package // Package the application into a platform specific package
func (b *PackageHelper) Package(po *ProjectOptions) error { func (b *PackageHelper) Package(po *ProjectOptions) error {
switch b.platform { switch runtime.GOOS {
case "darwin": case "darwin":
// Check we have the exe
if !b.fs.FileExists(po.BinaryName) {
return fmt.Errorf("cannot bundle non-existent binary file '%s'. Please build with 'wails build' first", po.BinaryName)
}
return b.packageOSX(po) return b.packageOSX(po)
case "windows": case "windows":
return b.PackageWindows(po, true) return b.PackageWindows(po, false)
case "linux": case "linux":
return b.packageLinux(po) return fmt.Errorf("linux is not supported at this time. Please see https://github.com/wailsapp/wails/issues/2")
default: default:
return fmt.Errorf("platform '%s' not supported for bundling yet", b.platform) return fmt.Errorf("platform '%s' not supported for bundling yet", runtime.GOOS)
} }
} }
func (b *PackageHelper) packageLinux(po *ProjectOptions) error {
return nil
}
// Package the application for OSX // Package the application for OSX
func (b *PackageHelper) packageOSX(po *ProjectOptions) error { func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
build := path.Join(b.fs.Cwd(), "build")
system := NewSystemHelper() system := NewSystemHelper()
config, err := system.LoadConfig() config, err := system.LoadConfig()
@@ -214,25 +102,18 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
appname := po.Name + ".app" appname := po.Name + ".app"
// Check binary exists // Check binary exists
source := path.Join(build, exe) source := path.Join(b.fs.Cwd(), exe)
if po.CrossCompile == true {
file, err := b.fs.FindFile(build, "darwin")
if err != nil {
return err
}
source = path.Join(build, file)
}
if !b.fs.FileExists(source) { if !b.fs.FileExists(source) {
// We need to build! // We need to build!
return fmt.Errorf("Target '%s' not available. Has it been compiled yet?", source) return fmt.Errorf("Target '%s' not available. Has it been compiled yet?", exe)
} }
// Remove the existing package // Remove the existing package
os.RemoveAll(appname) os.RemoveAll(appname)
exeDir := path.Join(build, appname, "/Contents/MacOS") exeDir := path.Join(b.fs.Cwd(), appname, "/Contents/MacOS")
b.fs.MkDirs(exeDir, 0755) b.fs.MkDirs(exeDir, 0755)
resourceDir := path.Join(build, appname, "/Contents/Resources") resourceDir := path.Join(b.fs.Cwd(), appname, "/Contents/Resources")
b.fs.MkDirs(resourceDir, 0755) b.fs.MkDirs(resourceDir, 0755)
tmpl := template.New("infoPlist") tmpl := template.New("infoPlist")
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist") plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
@@ -248,7 +129,7 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
if err != nil { if err != nil {
return err return err
} }
filename := path.Join(build, appname, "Contents", "Info.plist") filename := path.Join(b.fs.Cwd(), appname, "Contents", "Info.plist")
err = ioutil.WriteFile(filename, tpl.Bytes(), 0644) err = ioutil.WriteFile(filename, tpl.Bytes(), 0644)
if err != nil { if err != nil {
return err return err
@@ -269,37 +150,22 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
return err return err
} }
// CleanWindows removes any windows related files found in the directory
func (b *PackageHelper) CleanWindows(po *ProjectOptions) {
pdir := b.fs.Cwd()
basename := strings.TrimSuffix(po.BinaryName, ".exe")
exts := []string{".ico", ".exe.manifest", ".rc", "-res.syso"}
rsrcs := []string{}
for _, ext := range exts {
rsrcs = append(rsrcs, filepath.Join(pdir, basename+ext))
}
b.fs.RemoveFiles(rsrcs, true)
}
// PackageWindows packages the application for windows platforms // PackageWindows packages the application for windows platforms
func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error { func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
outputDir := b.fs.Cwd()
basename := strings.TrimSuffix(po.BinaryName, ".exe") basename := strings.TrimSuffix(po.BinaryName, ".exe")
// Copy default icon if needed // Copy icon
icon, err := b.copyIcon() tgtIconFile := filepath.Join(b.fs.Cwd(), basename+".ico")
if err != nil { if !b.fs.FileExists(tgtIconFile) {
return err srcIconfile := filepath.Join(b.getPackageFileBaseDir(), "wails.ico")
} err := b.fs.CopyFile(srcIconfile, tgtIconFile)
if err != nil {
// Generate icon from PNG return err
err = generateWindowsIcon(icon, basename+".ico") }
if err != nil {
return err
} }
// Copy manifest // Copy manifest
tgtManifestFile := filepath.Join(outputDir, basename+".exe.manifest") tgtManifestFile := filepath.Join(b.fs.Cwd(), basename+".exe.manifest")
if !b.fs.FileExists(tgtManifestFile) { if !b.fs.FileExists(tgtManifestFile) {
srcManifestfile := filepath.Join(b.getPackageFileBaseDir(), "wails.exe.manifest") srcManifestfile := filepath.Join(b.getPackageFileBaseDir(), "wails.exe.manifest")
err := b.fs.CopyFile(srcManifestfile, tgtManifestFile) err := b.fs.CopyFile(srcManifestfile, tgtManifestFile)
@@ -309,7 +175,7 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
} }
// Copy rc file // Copy rc file
tgtRCFile := filepath.Join(outputDir, basename+".rc") tgtRCFile := filepath.Join(b.fs.Cwd(), basename+".rc")
if !b.fs.FileExists(tgtRCFile) { if !b.fs.FileExists(tgtRCFile) {
srcRCfile := filepath.Join(b.getPackageFileBaseDir(), "wails.rc") srcRCfile := filepath.Join(b.getPackageFileBaseDir(), "wails.rc")
rcfilebytes, err := ioutil.ReadFile(srcRCfile) rcfilebytes, err := ioutil.ReadFile(srcRCfile)
@@ -324,37 +190,33 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
} }
// Build syso // Build syso
sysofile := filepath.Join(outputDir, basename+"-res.syso") sysofile := filepath.Join(b.fs.Cwd(), basename+"-res.syso")
// cross-compile batfile, err := fs.LocalDir(".")
if b.platform != runtime.GOOS { if err != nil {
args := []string{ return err
"docker", "run", "--rm", }
"-v", outputDir + ":/build",
"--entrypoint", "/bin/sh",
"wailsapp/xgo:latest",
"-c", "/usr/bin/x86_64-w64-mingw32-windres -o /build/" + basename + "-res.syso /build/" + basename + ".rc",
}
if err := NewProgramHelper().RunCommandArray(args); err != nil {
return err
}
} else {
batfile, err := fs.LocalDir(".")
if err != nil {
return err
}
windresBatFile := filepath.Join(batfile.fullPath, "windres.bat") windresBatFile := filepath.Join(batfile.fullPath, "windres.bat")
windresCommand := []string{windresBatFile, sysofile, tgtRCFile} windresCommand := []string{windresBatFile, sysofile, tgtRCFile}
err = NewProgramHelper().RunCommandArray(windresCommand) err = NewProgramHelper().RunCommandArray(windresCommand)
if err != nil {
return err
}
// clean up
if cleanUp {
filesToDelete := []string{tgtIconFile, tgtManifestFile, tgtRCFile, sysofile}
err := b.fs.RemoveFiles(filesToDelete)
if err != nil { if err != nil {
return err return err
} }
} }
return nil return nil
} }
func (b *PackageHelper) copyIcon() (string, error) { func (b *PackageHelper) copyIcon(resourceDir string) (string, error) {
// TODO: Read this from project.json // TODO: Read this from project.json
const appIconFilename = "appicon.png" const appIconFilename = "appicon.png"
@@ -379,7 +241,7 @@ func (b *PackageHelper) copyIcon() (string, error) {
func (b *PackageHelper) packageIconOSX(resourceDir string) error { func (b *PackageHelper) packageIconOSX(resourceDir string) error {
srcIcon, err := b.copyIcon() srcIcon, err := b.copyIcon(resourceDir)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -1,6 +1,5 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict> <plist version="1.0"><dict>
<key>CFBundlePackageType</key><string>APPL</string>
<key>CFBundleName</key><string>{{.Title}}</string> <key>CFBundleName</key><string>{{.Title}}</string>
<key>CFBundleExecutable</key><string>{{.Exe}}</string> <key>CFBundleExecutable</key><string>{{.Exe}}</string>
<key>CFBundleIdentifier</key><string>{{.PackageID}}</string> <key>CFBundleIdentifier</key><string>{{.PackageID}}</string>

View File

@@ -1,2 +1,2 @@
100 ICON "$NAME$.ico" 100 ICON "$NAME$.ico"
110 24 "$NAME$.exe.manifest" 100 24 "$NAME$.exe.manifest"

View File

@@ -138,11 +138,11 @@ func (p *ProgramHelper) RunCommand(command string) error {
// RunCommandArray runs the command specified in the array // RunCommandArray runs the command specified in the array
func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error { func (p *ProgramHelper) RunCommandArray(args []string, dir ...string) error {
programCommand := args[0] program := args[0]
// TODO: Run FindProgram here and get the full path to the exe // TODO: Run FindProgram here and get the full path to the exe
program, err := exec.LookPath(programCommand) program, err := exec.LookPath(program)
if err != nil { if err != nil {
fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", programCommand) fmt.Printf("ERROR: Looks like '%s' isn't installed. Please install and try again.", program)
return err return err
} }

View File

@@ -6,6 +6,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"sort" "sort"
"strings" "strings"
@@ -158,10 +159,6 @@ type ProjectOptions struct {
WailsVersion string WailsVersion string
typescriptDefsFilename string typescriptDefsFilename string
Verbose bool `json:"-"` Verbose bool `json:"-"`
CrossCompile bool
Platform string
Architecture string
LdFlags string
} }
// Defaults sets the default project template // Defaults sets the default project template
@@ -336,6 +333,11 @@ func processBinaryName(po *ProjectOptions) {
if po.BinaryName == "" { if po.BinaryName == "" {
var binaryNameComputed = computeBinaryName(po.Name) var binaryNameComputed = computeBinaryName(po.Name)
po.BinaryName = Prompt("The output binary name", binaryNameComputed) po.BinaryName = Prompt("The output binary name", binaryNameComputed)
if runtime.GOOS == "windows" {
if !strings.HasSuffix(po.BinaryName, ".exe") {
po.BinaryName += ".exe"
}
}
} }
fmt.Println("Output binary Name: " + po.BinaryName) fmt.Println("Output binary Name: " + po.BinaryName)
} }

View File

@@ -5,11 +5,12 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv" "strconv"
"time" "time"
homedir "github.com/mitchellh/go-homedir"
) )
// SystemHelper - Defines everything related to the system // SystemHelper - Defines everything related to the system
@@ -37,13 +38,12 @@ func NewSystemHelper() *SystemHelper {
// setSystemDirs calculates the system directories it is interested in // setSystemDirs calculates the system directories it is interested in
func (s *SystemHelper) setSystemDirs() { func (s *SystemHelper) setSystemDirs() {
var err error var err error
s.homeDir, err = os.UserConfigDir() s.homeDir, err = homedir.Dir()
if err != nil { if err != nil {
log.Fatal("Cannot find home directory! Please file a bug report!") log.Fatal("Cannot find home directory! Please file a bug report!")
} }
// TODO: A better config system // TODO: A better config system
s.wailsSystemDir = filepath.Join(s.homeDir, "wails") s.wailsSystemDir = filepath.Join(s.homeDir, ".wails")
s.wailsSystemConfig = filepath.Join(s.wailsSystemDir, s.configFilename) s.wailsSystemConfig = filepath.Join(s.wailsSystemDir, s.configFilename)
} }
@@ -132,7 +132,7 @@ func (s *SystemHelper) setup() error {
} }
const introText = ` const introText = `
Wails is a lightweight framework for creating web-like desktop apps in Go. Wails is a lightweight framework for creating web-like desktop apps in Go.
I'll need to ask you a few questions so I can fill in your project templates and then I will try and see if you have the correct dependencies installed. If you don't have the right tools installed, I'll try and suggest how to install them. I'll need to ask you a few questions so I can fill in your project templates and then I will try and see if you have the correct dependencies installed. If you don't have the right tools installed, I'll try and suggest how to install them.
` `
@@ -274,18 +274,16 @@ func CheckDependencies(logger *Logger) (bool, error) {
distroInfo := GetLinuxDistroInfo() distroInfo := GetLinuxDistroInfo()
switch distroInfo.Distribution { switch distroInfo.Distribution {
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian, PopOS: case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian:
libraryChecker = DpkgInstalled libraryChecker = DpkgInstalled
case Arch, ArcoLinux, ArchLabs, Manjaro, ManjaroARM: case Arch, ArcoLinux, Manjaro, ManjaroARM:
libraryChecker = PacmanInstalled libraryChecker = PacmanInstalled
case CentOS, Fedora, Tumbleweed, Leap: case CentOS, Fedora:
libraryChecker = RpmInstalled libraryChecker = RpmInstalled
case Gentoo: case Gentoo:
libraryChecker = EqueryInstalled libraryChecker = EqueryInstalled
case VoidLinux: case VoidLinux:
libraryChecker = XbpsInstalled libraryChecker = XbpsInstalled
case Solus:
libraryChecker = EOpkgInstalled
default: default:
return false, RequestSupportForDistribution(distroInfo) return false, RequestSupportForDistribution(distroInfo)
} }

View File

@@ -4,12 +4,12 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"core-js": "^3.6.4", "core-js": "^3.1.4",
"react": "^16.13.0", "react": "^16.8.6",
"react-dom": "^16.13.0", "react-dom": "^16.8.6",
"wails-react-scripts": "3.0.1-2", "wails-react-scripts": "3.0.1-2",
"react-modal": "3.11.2", "react-modal": "3.8.1",
"@wailsapp/runtime": "^1.0.10" "@wailsapp/runtime": "^1.0.0"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",

View File

@@ -1,5 +0,0 @@
# README
This is an experimental template for vanilla HTML/JS/CSS.
The webpack rules may need to be adjusted to correctly embed all assets. Babel may also need to be setup correctly.

View File

@@ -1,42 +0,0 @@
{
"name": "vanilla",
"author": "Lea<l>",
"private": true,
"scripts": {
"serve": "webpack-dev-server",
"build": "npx webpack"
},
"dependencies": {
"core-js": "^3.6.4",
"regenerator-runtime": "^0.13.3",
"@wailsapp/runtime": "^1.0.10"
},
"devDependencies": {
"babel-eslint": "^10.1.0",
"copy-webpack-plugin": "^6.0.2",
"eslint": "^6.8.0",
"eventsource-polyfill": "^0.9.6",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0",
"webpack-hot-middleware": "^2.25.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

View File

@@ -1,9 +0,0 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="main.css">
</head>
<body>
<div id="app"></div>
<script src="main.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -1,30 +0,0 @@
import 'core-js/stable';
const runtime = require('@wailsapp/runtime');
// Main entry point
function start() {
// Ensure the default app div is 100% wide/high
var app = document.getElementById('app');
app.style.width = '100%';
app.style.height = '100%';
// Inject html
app.innerHTML = `
<div class='logo'></div>
<div class='container'>
<button id='button'>Click Me!</button>
<div id='result'/>
</div>
`;
// Connect button to Go method
document.getElementById('button').onclick = function() {
window.backend.basic().then( function(result) {
document.getElementById('result').innerText = result;
});
};
};
// We provide our entrypoint as a callback for runtime.Init
runtime.Init(start);

View File

@@ -1,56 +0,0 @@
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
let imageSizeLimit = 9007199254740991; // Number.MAX_SAFE_INTEGER
let sourceDir = path.resolve(__dirname, 'src');
let buildDir = path.resolve(__dirname, 'build');
module.exports = {
entry: {
index: path.resolve(sourceDir, 'main.js')
},
output: {
path: buildDir,
filename: 'main.js'
},
optimization: {
splitChunks: false
},
devServer: {
disableHostCheck: true,
contentBase: path.join(__dirname, 'src'),
compress: true,
open: true,
port: 8090
},
mode: 'production',
module: {
rules: [
{
test: /\.(png|gif|jpg|woff2?|eot|ttf|otf|svg)(\?.*)?$/i,
use: [
{
loader: 'url-loader',
options: {
limit: imageSizeLimit
}
}
],
}
]
},
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(sourceDir, 'main.css'),
to: path.resolve(buildDir, 'main.css')
},
{
from: path.resolve(sourceDir, 'index.html'),
to: path.resolve(buildDir, 'index.html')
},
]
})
]
};

View File

@@ -1,5 +0,0 @@
module {{.BinaryName}}
require (
github.com/wailsapp/wails {{.WailsVersion}}
)

View File

@@ -1,27 +0,0 @@
package main
import (
"github.com/leaanthony/mewn"
"github.com/wailsapp/wails"
)
func basic() string {
return "Hello World!"
}
func main() {
js := mewn.String("./frontend/build/main.js")
css := mewn.String("./frontend/build/main.css")
app := wails.CreateApp(&wails.AppConfig{
Width: 1024,
Height: 768,
Title: "{{.Name}}",
JS: js,
CSS: css,
Colour: "#131313",
})
app.Bind(basic)
app.Run()
}

View File

@@ -1,12 +0,0 @@
{
"name": "Vanilla",
"shortdescription": "A Vanilla HTML/JS template",
"description": "A basic template using plain html/js and bundled using Webpack 4",
"author": "Lea Anthony<lea.anthony@gmail.com>",
"created": "2020-06-14",
"frontenddir": "frontend",
"install": "npm install",
"build": "npm run build",
"serve": "npm run serve",
"bridge": "src"
}

View File

@@ -8,21 +8,21 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"core-js": "^3.6.4", "core-js": "^3.6.1",
"regenerator-runtime": "^0.13.3", "regenerator-runtime": "^0.13.3",
"vue": "^2.6.11", "vue": "^2.5.22",
"@wailsapp/runtime": "^1.0.10" "@wailsapp/runtime": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^4.2.3", "@vue/cli-plugin-babel": "^3.4.0",
"@vue/cli-plugin-eslint": "^4.2.3", "@vue/cli-plugin-eslint": "^3.4.0",
"@vue/cli-service": "^4.2.3", "@vue/cli-service": "^3.4.0",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.0.1",
"eslint": "^6.8.0", "eslint": "^5.8.0",
"eslint-plugin-vue": "^6.2.1", "eslint-plugin-vue": "^5.0.0",
"eventsource-polyfill": "^0.9.6", "eventsource-polyfill": "^0.9.6",
"vue-template-compiler": "^2.6.11", "vue-template-compiler": "^2.5.21",
"webpack-hot-middleware": "^2.25.0" "webpack-hot-middleware": "^2.24.3"
}, },
"eslintConfig": { "eslintConfig": {
"root": true, "root": true,

View File

@@ -7,24 +7,24 @@
"build": "vue-cli-service build", "build": "vue-cli-service build",
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"core-js": "^3.6.4", "core-js": "^3.6.1",
"regenerator-runtime": "^0.13.3", "regenerator-runtime": "^0.13.3",
"material-design-icons-iconfont": "^5.0.1", "material-design-icons-iconfont": "^5.0.1",
"vue": "^2.5.22", "vue": "^2.5.22",
"vuetify": "^1.5.14", "vuetify": "^1.5.14",
"@wailsapp/runtime": "^1.0.10" "@wailsapp/runtime": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^4.2.3", "@vue/cli-plugin-babel": "^3.4.0",
"@vue/cli-plugin-eslint": "^4.2.3", "@vue/cli-plugin-eslint": "^3.4.0",
"@vue/cli-service": "^4.2.3", "@vue/cli-service": "^3.4.0",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.0.1",
"eslint": "^6.8.0", "eslint": "^5.8.0",
"eslint-plugin-vue": "^6.2.1", "eslint-plugin-vue": "^5.0.0",
"eventsource-polyfill": "^0.9.6", "eventsource-polyfill": "^0.9.6",
"vue-template-compiler": "^2.6.11", "vue-template-compiler": "^2.5.21",
"webpack-hot-middleware": "^2.25.0" "webpack-hot-middleware": "^2.24.3"
}, },
"eslintConfig": { "eslintConfig": {
"root": true, "root": true,

View File

@@ -8,23 +8,23 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"core-js": "^3.6.4", "core-js": "^3.6.1",
"regenerator-runtime": "^0.13.3", "regenerator-runtime": "^0.13.3",
"vue": "^2.6.11", "vue": "^2.5.22",
"vuetify": "^2.2.15", "vuetify": "^2.0.15",
"@wailsapp/runtime": "^1.0.10" "@wailsapp/runtime": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@mdi/font": "^4.9.95", "@mdi/font": "^4.3.95",
"@vue/cli-plugin-babel": "^4.2.3", "@vue/cli-plugin-babel": "^3.4.0",
"@vue/cli-plugin-eslint": "^4.2.3", "@vue/cli-plugin-eslint": "^3.4.0",
"@vue/cli-service": "^4.2.3", "@vue/cli-service": "^3.4.0",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.0.1",
"eslint": "^6.8.0", "eslint": "^5.8.0",
"eslint-plugin-vue": "^6.2.1", "eslint-plugin-vue": "^5.0.0",
"eventsource-polyfill": "^0.9.6", "eventsource-polyfill": "^0.9.6",
"vue-template-compiler": "^2.6.11", "vue-template-compiler": "^2.5.21",
"webpack-hot-middleware": "^2.25.0" "webpack-hot-middleware": "^2.24.3"
}, },
"eslintConfig": { "eslintConfig": {
"root": true, "root": true,

View File

@@ -1,4 +1,4 @@
package cmd package cmd
// Version - Wails version // Version - Wails version
const Version = "v1.7.2-pre2" const Version = "v1.0.2"

View File

@@ -3,24 +3,11 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"runtime"
"strings"
"github.com/leaanthony/spinner" "github.com/leaanthony/spinner"
"github.com/wailsapp/wails/cmd" "github.com/wailsapp/wails/cmd"
) )
// getSupportedPlatforms returns a slice of platform/architecture
// targets that are buildable using the cross-platform 'x' option.
func getSupportedPlatforms() []string {
return []string{
"darwin/amd64",
"linux/amd64",
"linux/arm-7",
"windows/amd64",
}
}
func init() { func init() {
var packageApp = false var packageApp = false
@@ -28,8 +15,6 @@ func init() {
var debugMode = false var debugMode = false
var typescriptFilename = "" var typescriptFilename = ""
var verbose = false var verbose = false
var platform = ""
var ldflags = ""
buildSpinner := spinner.NewSpinner() buildSpinner := spinner.NewSpinner()
buildSpinner.SetSpinSpeed(50) buildSpinner.SetSpinSpeed(50)
@@ -41,16 +26,7 @@ func init() {
BoolFlag("f", "Force rebuild of application components", &forceRebuild). BoolFlag("f", "Force rebuild of application components", &forceRebuild).
BoolFlag("d", "Build in Debug mode", &debugMode). BoolFlag("d", "Build in Debug mode", &debugMode).
BoolFlag("verbose", "Verbose output", &verbose). BoolFlag("verbose", "Verbose output", &verbose).
StringFlag("t", "Generate Typescript definitions to given file (at runtime)", &typescriptFilename). StringFlag("t", "Generate Typescript definitions to given file (at runtime)", &typescriptFilename)
StringFlag("ldflags", "Extra options for -ldflags", &ldflags)
var b strings.Builder
for _, plat := range getSupportedPlatforms() {
fmt.Fprintf(&b, " - %s\n", plat)
}
initCmd.StringFlag("x",
fmt.Sprintf("Cross-compile application to specified platform via xgo\n%s", b.String()),
&platform)
initCmd.Action(func() error { initCmd.Action(func() error {
@@ -76,28 +52,6 @@ func init() {
return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory") return fmt.Errorf("Unable to find 'project.json'. Please check you are in a Wails project directory")
} }
// Set cross-compile
projectOptions.Platform = runtime.GOOS
if len(platform) > 0 {
supported := false
for _, plat := range getSupportedPlatforms() {
if plat == platform {
supported = true
}
}
if !supported {
return fmt.Errorf("unsupported platform '%s' specified.\nPlease run `wails build -h` to see the supported platform/architecture options", platform)
}
projectOptions.CrossCompile = true
plat := strings.Split(platform, "/")
projectOptions.Platform = plat[0]
projectOptions.Architecture = plat[1]
}
// Add ldflags
projectOptions.LdFlags = ldflags
// Validate config // Validate config
// Check if we have a frontend // Check if we have a frontend
err = cmd.ValidateFrontendConfig(projectOptions) err = cmd.ValidateFrontendConfig(projectOptions)

View File

@@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"runtime"
"github.com/leaanthony/spinner" "github.com/leaanthony/spinner"
"github.com/wailsapp/wails/cmd" "github.com/wailsapp/wails/cmd"
@@ -35,6 +34,7 @@ func init() {
// Project options // Project options
projectOptions := &cmd.ProjectOptions{} projectOptions := &cmd.ProjectOptions{}
projectOptions.Verbose = verbose
// Check we are in project directory // Check we are in project directory
// Check project.json loads correctly // Check project.json loads correctly
@@ -44,10 +44,6 @@ func init() {
return err return err
} }
// Set project options
projectOptions.Verbose = verbose
projectOptions.Platform = runtime.GOOS
// Save project directory // Save project directory
projectDir := fs.Cwd() projectDir := fs.Cwd()

View File

@@ -3,9 +3,9 @@ package main
import ( import (
"fmt" "fmt"
"log" "log"
"os"
"github.com/leaanthony/spinner" "github.com/leaanthony/spinner"
"github.com/mitchellh/go-homedir"
"github.com/wailsapp/wails/cmd" "github.com/wailsapp/wails/cmd"
) )
@@ -146,7 +146,7 @@ func updateToVersion(targetVersion *cmd.SemanticVersion, force bool) error {
updateSpinner.Start("Installing Wails " + desiredVersion) updateSpinner.Start("Installing Wails " + desiredVersion)
// Run command in non module directory // Run command in non module directory
homeDir, err := os.UserHomeDir() homeDir, err := homedir.Dir()
if err != nil { if err != nil {
log.Fatal("Cannot find home directory! Please file a bug report!") log.Fatal("Cannot find home directory! Please file a bug report!")
} }

9
go.mod
View File

@@ -14,18 +14,19 @@ require (
github.com/leaanthony/spinner v0.5.3 github.com/leaanthony/spinner v0.5.3
github.com/mattn/go-colorable v0.1.1 // indirect github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect github.com/mattn/go-isatty v0.0.7 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
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 github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862
golang.org/x/text v0.3.0 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
) )
go 1.13 go 1.12

16
go.sum
View File

@@ -46,6 +46,8 @@ github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98=
@@ -66,21 +68,19 @@ github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba h1:2DHfQOxcpWdGf5
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba/go.mod h1:iLnlXG2Pakcii2CU0cbY07DRCSvpWNa7nFxtevhOChk= 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-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR170vGqDhJDOmpVd4Hjak=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/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 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=

View File

@@ -17,9 +17,9 @@ type Renderer interface {
NotifyEvent(eventData *messages.EventData) error NotifyEvent(eventData *messages.EventData) error
// Dialog Runtime // Dialog Runtime
SelectFile(title string, filter string) string SelectFile() string
SelectDirectory() string SelectDirectory() string
SelectSaveFile(title string, filter string) string SelectSaveFile() string
// Window Runtime // Window Runtime
SetColour(string) error SetColour(string) error

View File

@@ -42,12 +42,12 @@ type Bridge struct {
server *http.Server server *http.Server
lock sync.Mutex lock sync.Mutex
sessions map[string]*session sessions map[string]session
} }
// Initialise the Bridge Renderer // Initialise the Bridge Renderer
func (h *Bridge) Initialise(appConfig interfaces.AppConfig, ipcManager interfaces.IPCManager, eventManager interfaces.EventManager) error { func (h *Bridge) Initialise(appConfig interfaces.AppConfig, ipcManager interfaces.IPCManager, eventManager interfaces.EventManager) error {
h.sessions = map[string]*session{} h.sessions = map[string]session{}
h.ipcManager = ipcManager h.ipcManager = ipcManager
h.appConfig = appConfig h.appConfig = appConfig
h.eventManager = eventManager h.eventManager = eventManager
@@ -70,11 +70,13 @@ func (h *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
} }
func (h *Bridge) startSession(conn *websocket.Conn) { func (h *Bridge) startSession(conn *websocket.Conn) {
s := newSession(conn, s := session{
h.bindingCache, conn: conn,
h.ipcManager, bindingCache: h.bindingCache,
logger.NewCustomLogger("BridgeSession"), ipc: h.ipcManager,
h.eventManager) log: h.log,
eventManager: h.eventManager,
}
conn.SetCloseHandler(func(int, string) error { conn.SetCloseHandler(func(int, string) error {
h.log.Infof("Connection dropped [%s].", s.Identifier()) h.log.Infof("Connection dropped [%s].", s.Identifier())
@@ -114,7 +116,7 @@ func (h *Bridge) NewBinding(methodName string) error {
// SelectFile is unsupported for Bridge but required // SelectFile is unsupported for Bridge but required
// for the Renderer interface // for the Renderer interface
func (h *Bridge) SelectFile(title string, filter string) string { func (h *Bridge) SelectFile() string {
h.log.Warn("SelectFile() unsupported in bridge mode") h.log.Warn("SelectFile() unsupported in bridge mode")
return "" return ""
} }
@@ -128,7 +130,7 @@ func (h *Bridge) SelectDirectory() string {
// SelectSaveFile is unsupported for Bridge but required // SelectSaveFile is unsupported for Bridge but required
// for the Renderer interface // for the Renderer interface
func (h *Bridge) SelectSaveFile(title string, filter string) string { func (h *Bridge) SelectSaveFile() string {
h.log.Warn("SelectSaveFile() unsupported in bridge mode") h.log.Warn("SelectSaveFile() unsupported in bridge mode")
return "" return ""
} }
@@ -152,20 +154,13 @@ func (h *Bridge) NotifyEvent(event *messages.EventData) error {
// Marshall the data // Marshall the data
data, err = json.Marshal(event.Data) data, err = json.Marshal(event.Data)
if err != nil { if err != nil {
h.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error()) h.log.Errorf("Cannot unmarshall JSON data in event: %s ", err.Error())
return err return err
} }
} }
// Double encode data to ensure everything is escaped correctly. message := fmt.Sprintf("window.wails._.Notify('%s','%s')", event.Name, data)
data, err = json.Marshal(string(data)) dead := []session{}
if err != nil {
h.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
return err
}
message := "window.wails._.Notify('" + event.Name + "'," + string(data) + ")"
dead := []*session{}
for _, session := range h.sessions { for _, session := range h.sessions {
err := session.evalJS(message, notifyMessage) err := session.evalJS(message, notifyMessage)
if err != nil { if err != nil {
@@ -212,9 +207,6 @@ func (h *Bridge) SetTitle(title string) {
// for the Renderer interface // for the Renderer interface
func (h *Bridge) Close() { func (h *Bridge) Close() {
h.log.Debug("Shutting down") h.log.Debug("Shutting down")
for _, session := range h.sessions {
session.Shutdown()
}
err := h.server.Close() err := h.server.Close()
if err != nil { if err != nil {
h.log.Errorf(err.Error()) h.log.Errorf(err.Error())

View File

@@ -1,8 +1,7 @@
package renderer package renderer
import ( import (
"time" "sync"
"unsafe"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/leaanthony/mewn" "github.com/leaanthony/mewn"
@@ -21,22 +20,7 @@ type session struct {
ipc interfaces.IPCManager ipc interfaces.IPCManager
// Mutex for writing to the socket // Mutex for writing to the socket
shutdown chan bool lock sync.Mutex
writeChan chan []byte
done bool
}
func newSession(conn *websocket.Conn, bindingCache []string, ipc interfaces.IPCManager, logger *logger.CustomLogger, eventMgr interfaces.EventManager) *session {
return &session{
conn: conn,
bindingCache: bindingCache,
ipc: ipc,
log: logger,
eventManager: eventMgr,
shutdown: make(chan bool),
writeChan: make(chan []byte, 100),
}
} }
// Identifier returns a string identifier for the remote connection. // Identifier returns a string identifier for the remote connection.
@@ -49,15 +33,19 @@ func (s *session) Identifier() string {
} }
func (s *session) sendMessage(msg string) error { func (s *session) sendMessage(msg string) error {
if !s.done { s.lock.Lock()
s.writeChan <- *(*[]byte)(unsafe.Pointer(&msg)) defer s.lock.Unlock()
if err := s.conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
s.log.Debug(err.Error())
return err
} }
return nil return nil
} }
func (s *session) start(firstSession bool) { func (s *session) start(firstSession bool) {
s.log.Infof("Connected to frontend.") s.log.Infof("Connected to frontend.")
go s.writePump()
wailsRuntime := mewn.String("../../runtime/assets/wails.js") wailsRuntime := mewn.String("../../runtime/assets/wails.js")
s.evalJS(wailsRuntime, wailsRuntimeMessage) s.evalJS(wailsRuntime, wailsRuntimeMessage)
@@ -86,10 +74,6 @@ func (s *session) start(firstSession bool) {
s.log.Debugf("Got message: %#v\n", string(buffer)) s.log.Debugf("Got message: %#v\n", string(buffer))
s.ipc.Dispatch(string(buffer), s.Callback) s.ipc.Dispatch(string(buffer), s.Callback)
if s.done {
break
}
} }
} }
@@ -99,38 +83,8 @@ func (s *session) Callback(data string) error {
} }
func (s *session) evalJS(js string, mtype messageType) error { func (s *session) evalJS(js string, mtype messageType) error {
// Prepend message type to message // Prepend message type to message
return s.sendMessage(mtype.toString() + js) return s.sendMessage(mtype.toString() + js)
}
// Shutdown
func (s *session) Shutdown() {
s.done = true
s.shutdown <- true
s.log.Debugf("session %v exit", s.Identifier())
}
// writePump pulls messages from the writeChan and sends them to the client
// since it uses a channel to read the messages the socket is protected without locks
func (s *session) writePump() {
s.log.Debugf("Session %v - writePump start", s.Identifier())
for {
select {
case msg, ok := <-s.writeChan:
s.conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
if !ok {
s.log.Debug("writeChan was closed!")
s.conn.WriteMessage(websocket.CloseMessage, []byte{})
return
}
if err := s.conn.WriteMessage(websocket.TextMessage, msg); err != nil {
s.log.Debug(err.Error())
return
}
case <-s.shutdown:
break
}
}
s.log.Debug("writePump exiting...")
} }

File diff suppressed because one or more lines are too long

View File

@@ -245,7 +245,7 @@ func (w *WebView) NewBinding(methodName string) error {
} }
// SelectFile opens a dialog that allows the user to select a file // SelectFile opens a dialog that allows the user to select a file
func (w *WebView) SelectFile(title string, filter string) string { func (w *WebView) SelectFile() string {
var result string var result string
// We need to run this on the main thread, however Dispatch is // We need to run this on the main thread, however Dispatch is
@@ -255,7 +255,7 @@ func (w *WebView) SelectFile(title string, filter string) string {
wg.Add(1) wg.Add(1)
go func() { go func() {
w.window.Dispatch(func() { w.window.Dispatch(func() {
result = w.window.Dialog(wv.DialogTypeOpen, 0, title, "", filter) result = w.window.Dialog(wv.DialogTypeOpen, 0, "Select File", "")
wg.Done() wg.Done()
}) })
}() }()
@@ -273,7 +273,7 @@ func (w *WebView) SelectDirectory() string {
wg.Add(1) wg.Add(1)
go func() { go func() {
w.window.Dispatch(func() { w.window.Dispatch(func() {
result = w.window.Dialog(wv.DialogTypeOpen, wv.DialogFlagDirectory, "Select Directory", "", "") result = w.window.Dialog(wv.DialogTypeOpen, wv.DialogFlagDirectory, "Select Directory", "")
wg.Done() wg.Done()
}) })
}() }()
@@ -282,7 +282,7 @@ func (w *WebView) SelectDirectory() string {
} }
// SelectSaveFile opens a dialog that allows the user to select a file to save // SelectSaveFile opens a dialog that allows the user to select a file to save
func (w *WebView) SelectSaveFile(title string, filter string) string { func (w *WebView) SelectSaveFile() string {
var result string var result string
// We need to run this on the main thread, however Dispatch is // We need to run this on the main thread, however Dispatch is
// non-blocking so we launch this in a goroutine and wait for // non-blocking so we launch this in a goroutine and wait for
@@ -291,7 +291,7 @@ func (w *WebView) SelectSaveFile(title string, filter string) string {
wg.Add(1) wg.Add(1)
go func() { go func() {
w.window.Dispatch(func() { w.window.Dispatch(func() {
result = w.window.Dialog(wv.DialogTypeSave, 0, title, "", filter) result = w.window.Dialog(wv.DialogTypeSave, 0, "Save file", "")
wg.Done() wg.Done()
}) })
}() }()
@@ -329,14 +329,7 @@ func (w *WebView) NotifyEvent(event *messages.EventData) error {
} }
} }
// Double encode data to ensure everything is escaped correctly. message := fmt.Sprintf("wails._.Notify('%s','%s')", event.Name, data)
data, err = json.Marshal(string(data))
if err != nil {
w.log.Errorf("Cannot marshal JSON data in event: %s ", err.Error())
return err
}
message := "window.wails._.Notify('" + event.Name + "'," + string(data) + ")"
return w.evalJS(message) return w.evalJS(message)
} }

View File

@@ -74,9 +74,9 @@ static inline void CgoWebViewSetColor(void *w, uint8_t r, uint8_t g, uint8_t b,
} }
static inline void CgoDialog(void *w, int dlgtype, int flags, static inline void CgoDialog(void *w, int dlgtype, int flags,
char *title, char *arg, char *res, size_t ressz, char *filter) { char *title, char *arg, char *res, size_t ressz) {
webview_dialog(w, dlgtype, flags, webview_dialog(w, dlgtype, flags,
(const char*)title, (const char*) arg, res, ressz, filter); (const char*)title, (const char*) arg, res, ressz);
} }
static inline int CgoWebViewEval(void *w, char *js) { static inline int CgoWebViewEval(void *w, char *js) {
@@ -186,7 +186,7 @@ type WebView interface {
// Dialog() opens a system dialog of the given type and title. String // Dialog() opens a system dialog of the given type and title. String
// argument can be provided for certain dialogs, such as alert boxes. For // argument can be provided for certain dialogs, such as alert boxes. For
// alert boxes argument is a message inside the dialog box. // alert boxes argument is a message inside the dialog box.
Dialog(dlgType DialogType, flags int, title string, arg string, filter string) string Dialog(dlgType DialogType, flags int, title string, arg string) string
// Terminate() breaks the main UI loop. This method must be called from the main thread // Terminate() breaks the main UI loop. This method must be called from the main thread
// only. See Dispatch() for more details. // only. See Dispatch() for more details.
Terminate() Terminate()
@@ -311,7 +311,7 @@ func (w *webview) SetFullscreen(fullscreen bool) {
C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen))) C.CgoWebViewSetFullscreen(w.w, C.int(boolToInt(fullscreen)))
} }
func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string, filter string) string { func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string) string {
const maxPath = 4096 const maxPath = 4096
titlePtr := C.CString(title) titlePtr := C.CString(title)
defer C.free(unsafe.Pointer(titlePtr)) defer C.free(unsafe.Pointer(titlePtr))
@@ -319,10 +319,8 @@ func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string
defer C.free(unsafe.Pointer(argPtr)) defer C.free(unsafe.Pointer(argPtr))
resultPtr := (*C.char)(C.calloc((C.size_t)(unsafe.Sizeof((*C.char)(nil))), (C.size_t)(maxPath))) resultPtr := (*C.char)(C.calloc((C.size_t)(unsafe.Sizeof((*C.char)(nil))), (C.size_t)(maxPath)))
defer C.free(unsafe.Pointer(resultPtr)) defer C.free(unsafe.Pointer(resultPtr))
filterPtr := C.CString(filter)
defer C.free(unsafe.Pointer(filterPtr))
C.CgoDialog(w.w, C.int(dlgType), C.int(flags), titlePtr, C.CgoDialog(w.w, C.int(dlgType), C.int(flags), titlePtr,
argPtr, resultPtr, C.size_t(maxPath), filterPtr) argPtr, resultPtr, C.size_t(maxPath))
return C.GoString(resultPtr) return C.GoString(resultPtr)
} }

View File

@@ -139,7 +139,7 @@ struct webview_priv
#define DEFAULT_URL \ #define DEFAULT_URL \
"data:text/" \ "data:text/" \
"html,%3C%21DOCTYPE%20html%3E%0A%3Chtml%20lang=%22en%22%3E%0A%3Chead%3E%" \ "html,%3C%21DOCTYPE%20html%3E%0A%3Chtml%20lang=%22en%22%3E%0A%3Chead%3E%" \
"3Cmeta%20charset=%22utf-8%22%3E%3Cmeta%20http-equiv=%22IE=edge%22%" \ "3Cmeta%20charset=%22utf-8%22%3E%3Cmeta%20http-equiv=%22IE=edge%22%" \
"20content=%22IE=edge%22%3E%3C%2Fhead%3E%0A%3Cbody%3E%3Cdiv%20id=%22app%22%" \ "20content=%22IE=edge%22%3E%3C%2Fhead%3E%0A%3Cbody%3E%3Cdiv%20id=%22app%22%" \
"3E%3C%2Fdiv%3E%3Cscript%20type=%22text%2Fjavascript%22%3E%3C%2Fscript%3E%" \ "3E%3C%2Fdiv%3E%3Cscript%20type=%22text%2Fjavascript%22%3E%3C%2Fscript%3E%" \
"3C%2Fbody%3E%0A%3C%2Fhtml%3E" "3C%2Fbody%3E%0A%3C%2Fhtml%3E"
@@ -174,7 +174,7 @@ struct webview_priv
WEBVIEW_API void webview_dialog(struct webview *w, WEBVIEW_API void webview_dialog(struct webview *w,
enum webview_dialog_type dlgtype, int flags, enum webview_dialog_type dlgtype, int flags,
const char *title, const char *arg, const char *title, const char *arg,
char *result, size_t resultsz, char *filter); char *result, size_t resultsz);
WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn, WEBVIEW_API void webview_dispatch(struct webview *w, webview_dispatch_fn fn,
void *arg); void *arg);
WEBVIEW_API void webview_terminate(struct webview *w); WEBVIEW_API void webview_terminate(struct webview *w);
@@ -418,7 +418,7 @@ struct webview_priv
WEBVIEW_API void webview_dialog(struct webview *w, WEBVIEW_API void webview_dialog(struct webview *w,
enum webview_dialog_type dlgtype, int flags, enum webview_dialog_type dlgtype, int flags,
const char *title, const char *arg, const char *title, const char *arg,
char *result, size_t resultsz, char *filter) char *result, size_t resultsz)
{ {
GtkWidget *dlg; GtkWidget *dlg;
if (result != NULL) if (result != NULL)
@@ -438,17 +438,6 @@ struct webview_priv
"_Cancel", GTK_RESPONSE_CANCEL, "_Cancel", GTK_RESPONSE_CANCEL,
(dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ? "_Open" : "_Save"), (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ? "_Open" : "_Save"),
GTK_RESPONSE_ACCEPT, NULL); GTK_RESPONSE_ACCEPT, NULL);
if (filter[0] != '\0') {
GtkFileFilter *file_filter = gtk_file_filter_new();
gchar **filters = g_strsplit(filter, ",", -1);
gint i;
for(i = 0; filters && filters[i]; i++) {
gtk_file_filter_add_pattern(file_filter, filters[i]);
}
gtk_file_filter_set_name(file_filter, filter);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dlg), file_filter);
g_strfreev(filters);
}
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dlg), FALSE); gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dlg), FALSE);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dlg), FALSE); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dlg), FALSE);
gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dlg), TRUE); gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dlg), TRUE);
@@ -1238,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)
@@ -1248,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:
@@ -1288,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)
@@ -1298,9 +1287,9 @@ struct webview_priv
bstr = SysAllocString(buffer); bstr = SysAllocString(buffer);
GlobalFree(buffer); GlobalFree(buffer);
} }
// #else // #else
// bstr = SysAllocString(url); // bstr = SysAllocString(url);
// #endif // #endif
if ((pVar->bstrVal = bstr)) if ((pVar->bstrVal = bstr))
{ {
htmlDoc2->lpVtbl->write(htmlDoc2, sfArray); htmlDoc2->lpVtbl->write(htmlDoc2, sfArray);
@@ -1421,8 +1410,6 @@ struct webview_priv
wc.hInstance = hInstance; wc.hInstance = hInstance;
wc.lpfnWndProc = wndproc; wc.lpfnWndProc = wndproc;
wc.lpszClassName = classname; wc.lpszClassName = classname;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(100));
wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(100));
RegisterClassEx(&wc); RegisterClassEx(&wc);
style = WS_OVERLAPPEDWINDOW; style = WS_OVERLAPPEDWINDOW;
@@ -1457,12 +1444,12 @@ struct webview_priv
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);
#else #else
w->priv.hwnd = 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 #endif
if (w->priv.hwnd == 0) if (w->priv.hwnd == 0)
{ {
OleUninitialize(); OleUninitialize();
@@ -1479,7 +1466,8 @@ struct webview_priv
#else #else
SetWindowText(w->priv.hwnd, w->title); SetWindowText(w->priv.hwnd, w->title);
#endif #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);
@@ -1506,11 +1494,6 @@ struct webview_priv
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_KEYUP: case WM_KEYUP:
{ {
// Disable refresh when pressing F5 on windows
if (msg.wParam == VK_F5)
{
break;
}
HRESULT r = S_OK; HRESULT r = S_OK;
IWebBrowser2 *webBrowser2; IWebBrowser2 *webBrowser2;
IOleObject *browser = *w->priv.browser; IOleObject *browser = *w->priv.browser;
@@ -1620,7 +1603,7 @@ 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 #ifdef UNICODE
wchar_t *u16title = webview_to_utf16(title); wchar_t *u16title = webview_to_utf16(title);
if (u16title == NULL) if (u16title == NULL)
{ {
@@ -1628,11 +1611,12 @@ struct webview_priv
} }
SetWindowText(w->priv.hwnd, u16title); SetWindowText(w->priv.hwnd, u16title);
GlobalFree(u16title); GlobalFree(u16title);
#else #else
SetWindowText(w->priv.hwnd, title); SetWindowText(w->priv.hwnd, title);
#endif #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)
@@ -1793,7 +1777,7 @@ struct webview_priv
WEBVIEW_API void webview_dialog(struct webview *w, WEBVIEW_API void webview_dialog(struct webview *w,
enum webview_dialog_type dlgtype, int flags, enum webview_dialog_type dlgtype, int flags,
const char *title, const char *arg, const char *title, const char *arg,
char *result, size_t resultsz, char *filter) char *result, size_t resultsz)
{ {
if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN || if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ||
dlgtype == WEBVIEW_DIALOG_TYPE_SAVE) dlgtype == WEBVIEW_DIALOG_TYPE_SAVE)
@@ -1833,32 +1817,6 @@ struct webview_priv
FOS_NOTESTFILECREATE | FOS_NODEREFERENCELINKS | FOS_NOTESTFILECREATE | FOS_NODEREFERENCELINKS |
FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE; FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE;
} }
if (filter[0] != '\0')
{
int count;
int i=0;
char* token;
char* filter_dup = strdup(filter);
for (count=1; filter[count]; filter[count]==',' ? count++ : *filter++);
COMDLG_FILTERSPEC rgSpec[count];
char* filters[count];
token = strtok(filter_dup, ",");
while(token != NULL)
{
filters[i] = token;
token = strtok(NULL, ",");
i++;
}
for (int i=0; i < count; i++) {
wchar_t *wFilter = (wchar_t *)malloc(4096);
MultiByteToWideChar(CP_ACP, 0, filters[i], -1, wFilter, 4096);
rgSpec[i].pszName = wFilter;
rgSpec[i].pszSpec = wFilter;
}
if (dlg->lpVtbl->SetFileTypes(dlg, count, rgSpec) != S_OK) {
goto error_dlg;
}
}
if (dlg->lpVtbl->GetOptions(dlg, &opts) != S_OK) if (dlg->lpVtbl->GetOptions(dlg, &opts) != S_OK)
{ {
goto error_dlg; goto error_dlg;
@@ -1969,26 +1927,22 @@ 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, static void webview_run_input_open_panel(id self, SEL cmd, id webview,
id listener, BOOL allowMultiple) id listener, BOOL allowMultiple) {
{
char filename[256] = ""; char filename[256] = "";
struct webview *w = struct webview *w =
(struct webview *)objc_getAssociatedObject(self, "webview"); (struct webview *)objc_getAssociatedObject(self, "webview");
webview_dialog(w, WEBVIEW_DIALOG_TYPE_OPEN, WEBVIEW_DIALOG_FLAG_FILE, "", "", webview_dialog(w, WEBVIEW_DIALOG_TYPE_OPEN, WEBVIEW_DIALOG_FLAG_FILE, "", "",
filename, 255, ""); filename, 255);
filename[255] = '\0'; if (strlen(filename)) {
if (strlen(filename) > 0)
{
[listener chooseFilename:[NSString stringWithUTF8String:filename]]; [listener chooseFilename:[NSString stringWithUTF8String:filename]];
} } else {
else
{
[listener cancel]; [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 =
@@ -2001,7 +1955,7 @@ struct webview_priv
{ {
return; return;
} }
w->external_invoke_cb(w, [(NSString *)(arg) UTF8String]); w->external_invoke_cb(w, [(NSString *)(arg)UTF8String]);
} }
WEBVIEW_API int webview_init(struct webview *w) WEBVIEW_API int webview_init(struct webview *w)
@@ -2240,16 +2194,12 @@ struct webview_priv
WEBVIEW_API void webview_dialog(struct webview *w, WEBVIEW_API void webview_dialog(struct webview *w,
enum webview_dialog_type dlgtype, int flags, enum webview_dialog_type dlgtype, int flags,
const char *title, const char *arg, const char *title, const char *arg,
char *result, size_t resultsz, char *filter) char *result, size_t resultsz)
{ {
if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN || if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ||
dlgtype == WEBVIEW_DIALOG_TYPE_SAVE) dlgtype == WEBVIEW_DIALOG_TYPE_SAVE)
{ {
NSSavePanel *panel; NSSavePanel *panel;
NSString *filter_str = [NSString stringWithUTF8String:filter];
filter_str = [filter_str stringByReplacingOccurrencesOfString:@"*."
withString:@""];
NSArray *fileTypes = [filter_str componentsSeparatedByString:@","];
if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN) if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN)
{ {
NSOpenPanel *openPanel = [NSOpenPanel openPanel]; NSOpenPanel *openPanel = [NSOpenPanel openPanel];
@@ -2262,10 +2212,6 @@ struct webview_priv
{ {
[openPanel setCanChooseFiles:YES]; [openPanel setCanChooseFiles:YES];
[openPanel setCanChooseDirectories:NO]; [openPanel setCanChooseDirectories:NO];
if(filter[0] != NULL)
{
[openPanel setAllowedFileTypes:fileTypes];
}
} }
[openPanel setResolvesAliases:NO]; [openPanel setResolvesAliases:NO];
[openPanel setAllowsMultipleSelection:NO]; [openPanel setAllowsMultipleSelection:NO];
@@ -2279,10 +2225,6 @@ struct webview_priv
[panel setShowsHiddenFiles:YES]; [panel setShowsHiddenFiles:YES];
[panel setExtensionHidden:NO]; [panel setExtensionHidden:NO];
[panel setCanSelectHiddenExtension:NO]; [panel setCanSelectHiddenExtension:NO];
if(filter[0] != NULL)
{
[panel setAllowedFileTypes:fileTypes];
}
[panel setTreatsFilePackagesAsDirectories:YES]; [panel setTreatsFilePackagesAsDirectories:YES];
[panel beginSheetModalForWindow:w->priv.window [panel beginSheetModalForWindow:w->priv.window
completionHandler:^(NSInteger result) { completionHandler:^(NSInteger result) {

View File

@@ -1,7 +1,6 @@
package runtime package runtime
import "github.com/wailsapp/wails/lib/interfaces" import "github.com/wailsapp/wails/lib/interfaces"
import "strings"
// Dialog exposes an interface to native dialogs // Dialog exposes an interface to native dialogs
type Dialog struct { type Dialog struct {
@@ -16,16 +15,8 @@ func NewDialog(renderer interfaces.Renderer) *Dialog {
} }
// SelectFile prompts the user to select a file // SelectFile prompts the user to select a file
func (r *Dialog) SelectFile(params ...string) string { func (r *Dialog) SelectFile() string {
title := "Select File" return r.renderer.SelectFile()
filter := ""
if len(params) > 0 {
title = params[0]
}
if len(params) > 1 {
filter = strings.Replace(params[1], " ", "", -1)
}
return r.renderer.SelectFile(title, filter)
} }
// SelectDirectory prompts the user to select a directory // SelectDirectory prompts the user to select a directory
@@ -34,14 +25,6 @@ func (r *Dialog) SelectDirectory() string {
} }
// SelectSaveFile prompts the user to select a file for saving // SelectSaveFile prompts the user to select a file for saving
func (r *Dialog) SelectSaveFile(params ...string) string { func (r *Dialog) SelectSaveFile() string {
title := "Select Save" return r.renderer.SelectSaveFile()
filter := ""
if len(params) > 0 {
title = params[0]
}
if len(params) > 1 {
filter = strings.Replace(params[1], " ", "", -1)
}
return r.renderer.SelectSaveFile(title, filter)
} }

View File

@@ -1,9 +1,9 @@
package runtime package runtime
import "os" import homedir "github.com/mitchellh/go-homedir"
// FileSystem exposes file system utilities to the runtime // FileSystem exposes file system utilities to the runtime
type FileSystem struct{} type FileSystem struct {}
// NewFileSystem creates a new FileSystem struct // NewFileSystem creates a new FileSystem struct
func NewFileSystem() *FileSystem { func NewFileSystem() *FileSystem {
@@ -12,5 +12,5 @@ func NewFileSystem() *FileSystem {
// HomeDir returns the user's home directory // HomeDir returns the user's home directory
func (r *FileSystem) HomeDir() (string, error) { func (r *FileSystem) HomeDir() (string, error) {
return os.UserHomeDir() return homedir.Dir()
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "@wailsapp/runtime", "name": "@wailsapp/runtime",
"version": "1.0.11", "version": "1.0.10",
"description": "Wails Javascript runtime library", "description": "Wails Javascript runtime library",
"main": "main.js", "main": "main.js",
"types": "runtime.d.ts", "types": "runtime.d.ts",
@@ -25,4 +25,4 @@
"devDependencies": { "devDependencies": {
"dts-gen": "^0.5.8" "dts-gen": "^0.5.8"
} }
} }

View File

@@ -6,12 +6,12 @@ declare const wailsapp__runtime: {
OpenURL(url: string): Promise<any>; OpenURL(url: string): Promise<any>;
}; };
Events: { Events: {
Acknowledge(eventName: string): void; Acknowledge(eventName: string): void;
Emit(eventName: string, data?: any): void; Emit(eventName: string): void;
Heartbeat(eventName: string, timeInMilliseconds: number, callback: (data?: any) => void): void; Heartbeat(eventName: string, timeInMilliseconds: number, callback: () => void): void;
On(eventName: string, callback: (data?: any) => void): void; On(eventName: string, callback: () => void): void;
OnMultiple(eventName: string, callback: (data?: any) => void, maxCallbacks: number): void; OnMultiple(eventName: string, callback: () => void, maxCallbacks: number): void;
Once(eventName: string, callback: (data?: any) => void): void; Once(eventName: string, callback: () => void): void;
}; };
Init(callback: () => void): void; Init(callback: () => void): void;
Log: { Log: {

View File

@@ -1,13 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
echo "**** Checking if Wails passes unit tests ****"
if ! go test ./...
then
echo ""
echo "ERROR: Unit tests failed!"
exit 1;
fi
# Build runtime # Build runtime
echo "**** Building Runtime ****" echo "**** Building Runtime ****"
cd runtime/js cd runtime/js
@@ -23,23 +15,9 @@ cd lib/renderer
mewn mewn
cd ../.. cd ../..
cd cmd/wails
echo "**** Checking if Wails compiles ****"
if ! go build .
then
echo ""
echo "ERROR: Build failed!"
exit 1;
fi
echo "**** Installing Wails locally ****" echo "**** Installing Wails locally ****"
if ! go install cd cmd/wails
then go install
echo ""
echo "ERROR: Install failed!"
exit 1;
fi
cd ../.. cd ../..
echo "**** Tidying the mods! ****" echo "**** Tidying the mods! ****"