Compare commits

..

9 Commits

Author SHA1 Message Date
Lea Anthony
ea377ed2c3 Add contributors 2020-01-02 08:36:12 +11:00
Lea Anthony
6c1baac7f4 Merge branch 'develop' into vuetify2-support 2020-01-02 07:24:53 +10:00
Travis McLane
b8bfe24340 fix: babel -> core-js, regenerator-runtime 2020-01-01 15:08:11 -06:00
Travis McLane
7352e9d6a2 fix: codacy corrections 2020-01-01 15:01:43 -06:00
Michael Hipp
245f678aa1 Remove babel-polyfill, add mdi/font 2019-12-31 09:01:11 -06:00
Michael Hipp
ef99dc592b Update App.vue, HelloWorld.vue for Vuetify v2 2019-12-31 09:01:11 -06:00
Michael Hipp
e93103ed6b Get vuetify2 template installing vuetify v2.0 (but with styling probs) 2019-12-31 09:01:11 -06:00
Michael Hipp
46c1e81a20 Change template descr of vuetify-basic to say Vuetify 1.5 2019-12-31 09:01:11 -06:00
Michael Hipp
702b475a3b Initial create of vuetify2-basic folder 2019-12-31 09:01:10 -06:00
46 changed files with 753 additions and 1118 deletions

View File

@@ -1,32 +0,0 @@
name: latest pre-release
on:
push:
tags:
- '**-pre**'
jobs:
build:
name: Test Build Latest Pre-Release
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- name: Set up Go 1.12
uses: actions/setup-go@v1
with:
go-version: 1.12
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v1
- name: Get dependencies
run: |
go get -v -d ./...
- name: Build
run: go build -v ./cmd/wails
- name: Test
run: ./wails version

View File

@@ -1,32 +0,0 @@
name: pr
on:
pull_request:
branches:
- develop
jobs:
build:
name: Test Build PR
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- name: Set up Go 1.12
uses: actions/setup-go@v1
with:
go-version: 1.12
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v1
- name: Get dependencies
run: |
go get -v -d ./...
- name: Build
run: go build -v ./cmd/wails
- name: Test
run: ./wails version

View File

@@ -1,34 +0,0 @@
name: release
on:
push:
branches:
- master
tags:
- '!**pre**'
jobs:
build:
name: Test Build Latest Release
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- name: Set up Go 1.12
uses: actions/setup-go@v1
with:
go-version: 1.12
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v1
- name: Get dependencies
run: |
go get -v -d ./...
- name: Build
run: go build -v ./cmd/wails
- name: Test
run: ./wails version

View File

@@ -22,4 +22,4 @@ Wails is what it is because of the time and effort given by these great people.
* [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)

View File

@@ -11,8 +11,7 @@
<a href="https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_shield" alt="FOSSA Status"><img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=shield"/></a> <a href="https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_shield" alt="FOSSA Status"><img src="https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=shield"/></a>
<a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a> <a href="https://houndci.com"><img src="https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg"/></a>
<a href="https://github.com/avelino/awesome-go" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a> <a href="https://github.com/avelino/awesome-go" rel="nofollow"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome"></a>
<a href="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" rel="nofollow"><img src="https://github.com/wailsapp/wails/workflows/release/badge.svg?branch=master" alt="Release Pipelines"></a> <a href="https://dev.azure.com/leaanthony/Wails/_build/latest?definitionId=1&branchName=master" rel="nofollow"><img src="https://dev.azure.com/leaanthony/Wails/_apis/build/status/wailsapp.wails?branchName=master" alt="Pipelines"></a>
<a href="https://github.com/wailsapp/wails/workflows/latest-pre/badge.svg?branch=masterr" rel="nofollow"><img src="https://github.com/wailsapp/wails/workflows/latest-pre/badge.svg?branch=master" alt="Pre-Release Pipelines"></a>
</p> </p>
The traditional method of providing web interfaces to Go programs is via a built-in web server. Wails offers a different approach: it provides the ability to wrap both Go code and a web frontend into a single binary. Tools are provided to make this easy for you by handling project creation, compilation and bundling. All you have to do is get creative! The traditional method of providing web interfaces to Go programs is via a built-in web server. Wails offers a different approach: it provides the ability to wrap both Go code and a web frontend into a single binary. Tools are provided to make this easy for you by handling project creation, compilation and bundling. All you have to do is get creative!
@@ -147,11 +146,3 @@ This project was mainly coded to the following albums:
## Licensing ## Licensing
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fwailsapp%2Fwails.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fwailsapp%2Fwails?ref=badge_large)
## Special Thank You
<p align="center" style="text-align: center">
A special thank you to JetBrains for donating licenses to us!<br/><br/>
Please click the logo to let them know your appreciation!<br/><br/>
<a href="https://www.jetbrains.com?from=Wails"><img src="jetbrains-grayscale.png" width="30%"></a>
</p>

2
app.go
View File

@@ -97,7 +97,7 @@ func (a *App) start() error {
// Check if we are to run in bridge mode // Check if we are to run in bridge mode
if BuildMode == cmd.BuildModeBridge { if BuildMode == cmd.BuildModeBridge {
a.renderer = renderer.NewBridge() a.renderer = &renderer.Bridge{}
} }
// Initialise the renderer // Initialise the renderer

138
azure-pipelines.yaml Normal file
View File

@@ -0,0 +1,138 @@
# avoid double trigger by applying some rules
# start a pipeline when push to 'master' branch
trigger:
- master
# or when pull request on 'develop' branch
pr:
- develop
# for now there is only one stage 'Build'
# in the future we could use multistage strategy for releases
stages:
- stage: Build
# there are 3 jobs
# one for each os
jobs:
- deployment: Linux
displayName: Lin
variables:
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
GOBIN: '$(GOPATH)/bin' # Go binaries path
GOMODULE: 'on'
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
pool:
vmImage: 'Ubuntu-16.04'
environment: 'linux-dev'
strategy:
runOnce:
deploy:
steps:
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
clean: true # whether to fetch clean each time
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
# go version 1.12.7
- script: |
wget "https://storage.googleapis.com/golang/go1.12.7.linux-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
displayName: 'Install Go 1.12.7 Linux'
- script: |
mkdir -p '$(GOBIN)'
mkdir -p '$(GOPATH)/pkg'
mkdir -p '$(GOROOT)'
shopt -s extglob
shopt -s dotglob
echo '##vso[task.prependpath]$(GOBIN)'
echo '##vso[task.prependpath]$(GOROOT)/bin'
displayName: 'Set up the Go workspace'
- script: |
go version
go get -v -d ./...
cd cmd/wails
go install
workingDirectory: '$(modulePath)'
displayName: 'Get dependencies, then build'
- script: |
wails version
workingDirectory: '$(modulePath)'
displayName: 'Check we have output'
- deployment: Mac
displayName: Mac
variables:
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
GOBIN: '$(GOPATH)/bin' # Go binaries path
GOMODULE: 'on'
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
pool:
vmImage: 'macOS-10.14'
environment: 'mac-dev'
strategy:
runOnce:
deploy:
steps:
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
clean: true # whether to fetch clean each time
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
# go version 1.12.7
- script: |
wget "https://storage.googleapis.com/golang/go1.12.7.darwin-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
displayName: 'Install Go 1.12.7 Linux'
- script: |
mkdir -p '$(GOBIN)'
mkdir -p '$(GOPATH)/pkg'
mkdir -p '$(GOROOT)'
shopt -s extglob
shopt -s dotglob
echo '##vso[task.prependpath]$(GOBIN)'
echo '##vso[task.prependpath]$(GOROOT)/bin'
displayName: 'Set up the Go workspace'
- script: |
go version
go get -v -d ./...
cd cmd/wails
go install
workingDirectory: '$(modulePath)'
displayName: 'Get dependencies, then build'
- script: |
wails version
workingDirectory: '$(modulePath)'
displayName: 'Check we have output'
- deployment: Win
displayName: Win
variables:
GOMODULE: 'on'
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
pool:
vmImage: 'windows-2019'
environment: 'win-dev'
strategy:
runOnce:
deploy:
steps:
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
clean: true # whether to fetch clean each time
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
# Go tool installer
# Find in cache or download a specific version of Go and add it to the PATH
- task: GoTool@0
inputs:
version: '1.12.7'
goPath: '$(Agent.BuildDirectory)/go'
goBin: '$(Agent.BuildDirectory)/go/bin'
displayName: 'Set up the Go workspace'
- script: |
go version
go get -v -d ./...
cd cmd/wails
go install
workingDirectory: '$(modulePath)'
displayName: 'Get dependencies, then build'
- script: |
wails version
workingDirectory: '$(Agent.BuildDirectory)/go/bin'
displayName: 'Check we have output'

138
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,138 @@
# avoid double trigger by applying some rules
# start a pipeline when push to 'master' branch
trigger:
- master
# or when pull request on 'develop' branch
pr:
- develop
# for now there is only one stage 'Build'
# in the future we could use multistage strategy for releases
stages:
- stage: Build
# there are 3 jobs
# one for each os
jobs:
- deployment: Linux
displayName: Lin
variables:
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
GOBIN: '$(GOPATH)/bin' # Go binaries path
GOMODULE: 'on'
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
pool:
vmImage: 'Ubuntu-16.04'
environment: 'linux-dev'
strategy:
runOnce:
deploy:
steps:
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
clean: true # whether to fetch clean each time
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
# go version 1.12.7
- script: |
wget "https://storage.googleapis.com/golang/go1.12.7.linux-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
displayName: 'Install Go 1.12.7 Linux'
- script: |
mkdir -p '$(GOBIN)'
mkdir -p '$(GOPATH)/pkg'
mkdir -p '$(GOROOT)'
shopt -s extglob
shopt -s dotglob
echo '##vso[task.prependpath]$(GOBIN)'
echo '##vso[task.prependpath]$(GOROOT)/bin'
displayName: 'Set up the Go workspace'
- script: |
go version
go get -v -d ./...
cd cmd/wails
go install
workingDirectory: '$(modulePath)'
displayName: 'Get dependencies, then build'
- script: |
wails version
workingDirectory: '$(modulePath)'
displayName: 'Check we have output'
- deployment: Mac
displayName: Mac
variables:
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
GOBIN: '$(GOPATH)/bin' # Go binaries path
GOMODULE: 'on'
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
pool:
vmImage: 'macOS-10.14'
environment: 'mac-dev'
strategy:
runOnce:
deploy:
steps:
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
clean: true # whether to fetch clean each time
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
# go version 1.12.7
- script: |
wget "https://storage.googleapis.com/golang/go1.12.7.darwin-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.12.7.tar.gz"
displayName: 'Install Go 1.12.7 Linux'
- script: |
mkdir -p '$(GOBIN)'
mkdir -p '$(GOPATH)/pkg'
mkdir -p '$(GOROOT)'
shopt -s extglob
shopt -s dotglob
echo '##vso[task.prependpath]$(GOBIN)'
echo '##vso[task.prependpath]$(GOROOT)/bin'
displayName: 'Set up the Go workspace'
- script: |
go version
go get -v -d ./...
cd cmd/wails
go install
workingDirectory: '$(modulePath)'
displayName: 'Get dependencies, then build'
- script: |
wails version
workingDirectory: '$(modulePath)'
displayName: 'Check we have output'
- deployment: Win
displayName: Win
variables:
GOMODULE: 'on'
modulePath: '$(Agent.BuildDirectory)/wails' # Path to the module's code
pool:
vmImage: 'windows-2019'
environment: 'win-dev'
strategy:
runOnce:
deploy:
steps:
- checkout: self # self represents the repo where the initial Pipelines YAML file was found
clean: true # whether to fetch clean each time
path: wails # path to check out source code, relative to the agent's build directory (e.g. \_work\1)
# Go tool installer
# Find in cache or download a specific version of Go and add it to the PATH
- task: GoTool@0
inputs:
version: '1.12.7'
goPath: '$(Agent.BuildDirectory)/go'
goBin: '$(Agent.BuildDirectory)/go/bin'
displayName: 'Set up the Go workspace'
- script: |
go version
go get -v -d ./...
cd cmd/wails
go install
workingDirectory: '$(modulePath)'
displayName: 'Get dependencies, then build'
- script: |
wails version
workingDirectory: '$(Agent.BuildDirectory)/go/bin'
displayName: 'Check we have output'

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 {
@@ -149,16 +132,6 @@ func (fs *FSHelper) LocalDir(dir string) (*Dir, error) {
}, err }, err
} }
// LoadRelativeFile loads the given file relative to the caller's directory
func (fs *FSHelper) LoadRelativeFile(relativePath string) ([]byte, error) {
_, filename, _, _ := runtime.Caller(0)
fullPath, err := filepath.Abs(filepath.Join(path.Dir(filename), relativePath))
if err != nil {
return nil, err
}
return ioutil.ReadFile(fullPath)
}
// GetSubdirs will return a list of FQPs to subdirectories in the given directory // GetSubdirs will return a list of FQPs to subdirectories in the given directory
func (d *Dir) GetSubdirs() (map[string]string, error) { func (d *Dir) GetSubdirs() (map[string]string, error) {

View File

@@ -1,78 +0,0 @@
package cmd
import (
"fmt"
"path/filepath"
"regexp"
"github.com/Masterminds/semver"
)
func GetWailsVersion() (*semver.Version, error) {
var FS = NewFSHelper()
var result *semver.Version
// Load file
var err error
goModFile, err := filepath.Abs(filepath.Join(".", "go.mod"))
if err != nil {
return nil, fmt.Errorf("Unable to load go.mod at %s", goModFile)
}
goMod, err := FS.LoadAsString(goModFile)
if err != nil {
return nil, fmt.Errorf("Unable to load go.mod")
}
// Find wails version
versionRegexp := regexp.MustCompile(`.*github.com/wailsapp/wails.*(v\d+.\d+.\d+(?:-pre\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)
}
return result, nil
}
func GetCurrentVersion() (*semver.Version, error) {
result, err := semver.NewVersion(Version)
if err != nil {
return nil, fmt.Errorf("Unable to parse Wails version: %s", Version)
}
return result, nil
}
func GoModOutOfSync() (bool, error) {
gomodversion, err := GetWailsVersion()
if err != nil {
return true, err
}
currentVersion, err := GetCurrentVersion()
if err != nil {
return true, err
}
result := !currentVersion.Equal(gomodversion)
return result, nil
}
func UpdateGoModVersion() error {
currentVersion, err := GetCurrentVersion()
if err != nil {
return err
}
currentVersionString := currentVersion.String()
requireLine := "-require=github.com/wailsapp/wails@v" + currentVersionString
// Issue: go mod edit -require=github.com/wailsapp/wails@1.0.2-pre5
helper := NewProgramHelper()
command := []string{"go", "mod", "edit", requireLine}
return helper.RunCommandArray(command)
}

View File

@@ -11,7 +11,6 @@ import (
"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"
) )
@@ -37,88 +36,35 @@ func ValidateFrontendConfig(projectOptions *ProjectOptions) error {
} }
// InstallGoDependencies will run go get in the current directory // InstallGoDependencies will run go get in the current directory
func InstallGoDependencies(verbose bool) error { func InstallGoDependencies() error {
var depSpinner *spinner.Spinner depSpinner := spinner.New("Ensuring Dependencies are up to date...")
if !verbose { depSpinner.SetSpinSpeed(50)
depSpinner = spinner.New("Ensuring Dependencies are up to date...") depSpinner.Start()
depSpinner.SetSpinSpeed(50) err := NewProgramHelper().RunCommand("go get")
depSpinner.Start()
}
err := NewProgramHelper(verbose).RunCommand("go get")
if err != nil { if err != nil {
if !verbose { depSpinner.Error()
depSpinner.Error()
}
return err return err
} }
if !verbose { depSpinner.Success()
depSpinner.Success()
}
return nil return nil
} }
// EmbedAssets will embed the built frontend assets via mewn.
func EmbedAssets() ([]string, error) {
mewnFiles := lib.GetMewnFiles([]string{}, false)
referencedAssets, err := lib.GetReferencedAssets(mewnFiles)
if err != nil {
return []string{}, err
}
targetFiles := []string{}
for _, referencedAsset := range referencedAssets {
packfileData, err := lib.GeneratePackFileString(referencedAsset, false)
if err != nil {
return []string{}, err
}
targetFile := filepath.Join(referencedAsset.BaseDir, referencedAsset.PackageName+"-mewn.go")
targetFiles = append(targetFiles, targetFile)
ioutil.WriteFile(targetFile, []byte(packfileData), 0644)
}
return targetFiles, nil
}
// BuildApplication will attempt to build the project based on the given inputs // 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 { func BuildApplication(binaryName string, forceRebuild bool, buildMode string, packageApp bool, projectOptions *ProjectOptions) error {
if buildMode == BuildModeBridge && projectOptions.CrossCompile {
return fmt.Errorf("you cant serve the application in cross-compilation")
}
// Generate Windows assets if needed // Generate Windows assets if needed
if projectOptions.Platform == "windows" { if runtime.GOOS == "windows" {
cleanUp := !packageApp cleanUp := !packageApp
err := NewPackageHelper(projectOptions.Platform).PackageWindows(projectOptions, cleanUp) err := NewPackageHelper().PackageWindows(projectOptions, cleanUp)
if err != nil { if err != nil {
return err return err
} }
} }
if projectOptions.CrossCompile { // Check Mewn is installed
// Check build directory err := CheckMewn()
buildDirectory := filepath.Join(fs.Cwd(), "build") if err != nil {
if !fs.DirExists(buildDirectory) { return err
fs.MkDir(buildDirectory)
}
// Check Docker
if err := CheckIfInstalled("docker"); err != nil {
return err
}
// Check xgo
if err := CheckIfInstalled("xgo"); err != nil {
return err
}
} else {
// Check Mewn is installed
err := CheckMewn(projectOptions.Verbose)
if err != nil {
return err
}
} }
compileMessage := "Packing + Compiling project" compileMessage := "Packing + Compiling project"
@@ -127,47 +73,21 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
compileMessage += " (Debug Mode)" compileMessage += " (Debug Mode)"
} }
var packSpinner *spinner.Spinner packSpinner := spinner.New(compileMessage + "...")
if !projectOptions.Verbose { packSpinner.SetSpinSpeed(50)
packSpinner = spinner.New(compileMessage + "...") packSpinner.Start()
packSpinner.SetSpinSpeed(50)
packSpinner.Start()
} else {
println(compileMessage)
}
// embed resources
targetFiles, err := EmbedAssets()
if err != nil {
return err
}
// cleanup temporary embedded assets
defer func() {
for _, filename := range targetFiles {
if err := os.Remove(filename); err != nil {
fmt.Println(err)
}
}
}()
buildCommand := slicer.String() buildCommand := slicer.String()
if projectOptions.CrossCompile { buildCommand.Add("mewn")
buildCommand.Add("xgo")
} else {
buildCommand.Add("mewn")
}
if buildMode == BuildModeBridge { if buildMode == BuildModeBridge {
// Ignore errors // Ignore errors
buildCommand.Add("-i") buildCommand.Add("-i")
} }
if !projectOptions.CrossCompile { buildCommand.Add("build")
buildCommand.Add("build")
}
if binaryName != "" && !projectOptions.CrossCompile { if binaryName != "" {
// Alter binary name based on OS // Alter binary name based on OS
switch runtime.GOOS { switch runtime.GOOS {
case "windows": case "windows":
@@ -179,11 +99,12 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
binaryName = strings.TrimSuffix(binaryName, ".exe") binaryName = strings.TrimSuffix(binaryName, ".exe")
} }
} }
buildCommand.Add("-o", binaryName) buildCommand.Add("-o")
buildCommand.Add(binaryName)
} }
// If we are forcing a rebuild // If we are forcing a rebuild
if forceRebuild && !projectOptions.CrossCompile { if forceRebuild {
buildCommand.Add("-a") buildCommand.Add("-a")
} }
@@ -194,40 +115,19 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
} }
// Add windows flags // Add windows flags
if projectOptions.Platform == "windows" && buildMode == BuildModeProd { if runtime.GOOS == "windows" && buildMode == BuildModeProd {
ldflags += "-H windowsgui " ldflags += "-H windowsgui "
} }
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode 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}) buildCommand.AddSlice([]string{"-ldflags", ldflags})
err = NewProgramHelper().RunCommandArray(buildCommand.AsSlice())
if projectOptions.CrossCompile {
buildCommand.Add("-targets", projectOptions.Platform+"/"+projectOptions.Architecture)
buildCommand.Add("-out", "build/"+binaryName)
buildCommand.Add("./")
}
err = NewProgramHelper(projectOptions.Verbose).RunCommandArray(buildCommand.AsSlice())
if err != nil { if err != nil {
if packSpinner != nil { packSpinner.Error()
packSpinner.Error()
}
return err return err
} }
if packSpinner != nil { packSpinner.Success()
packSpinner.Success()
}
// packageApp // packageApp
if packageApp { if packageApp {
@@ -244,78 +144,52 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
func PackageApplication(projectOptions *ProjectOptions) error { func PackageApplication(projectOptions *ProjectOptions) error {
// Package app // Package app
message := "Generating .app" message := "Generating .app"
if projectOptions.Platform == "windows" { if runtime.GOOS == "windows" {
err := CheckWindres() err := CheckWindres()
if err != nil { if err != nil {
return err return err
} }
message = "Generating resource bundle" message = "Generating resource bundle"
} }
var packageSpinner *spinner.Spinner packageSpinner := spinner.New(message)
if !projectOptions.Verbose { packageSpinner.SetSpinSpeed(50)
packageSpinner = spinner.New(message) packageSpinner.Start()
packageSpinner.SetSpinSpeed(50) err := NewPackageHelper().Package(projectOptions)
packageSpinner.Start()
} else {
println(message)
}
err := NewPackageHelper(projectOptions.Platform).Package(projectOptions)
if err != nil { if err != nil {
if packageSpinner != nil { packageSpinner.Error()
packageSpinner.Error()
}
return err return err
} }
if packageSpinner != nil { packageSpinner.Success()
packageSpinner.Success()
}
return nil return nil
} }
// BuildFrontend runs the given build command // BuildFrontend runs the given build command
func BuildFrontend(projectOptions *ProjectOptions) error { func BuildFrontend(buildCommand string) error {
var buildFESpinner *spinner.Spinner buildFESpinner := spinner.New("Building frontend...")
if !projectOptions.Verbose { buildFESpinner.SetSpinSpeed(50)
buildFESpinner = spinner.New("Building frontend...") buildFESpinner.Start()
buildFESpinner.SetSpinSpeed(50) err := NewProgramHelper().RunCommand(buildCommand)
buildFESpinner.Start()
} else {
println("Building frontend...")
}
err := NewProgramHelper(projectOptions.Verbose).RunCommand(projectOptions.FrontEnd.Build)
if err != nil { if err != nil {
if buildFESpinner != nil { buildFESpinner.Error()
buildFESpinner.Error()
}
return err return err
} }
if buildFESpinner != nil { buildFESpinner.Success()
buildFESpinner.Success()
}
return nil return nil
} }
// CheckMewn checks if mewn is installed and if not, attempts to fetch it // CheckMewn checks if mewn is installed and if not, attempts to fetch it
func CheckMewn(verbose bool) (err error) { func CheckMewn() (err error) {
programHelper := NewProgramHelper(verbose) programHelper := NewProgramHelper()
if !programHelper.IsInstalled("mewn") { if !programHelper.IsInstalled("mewn") {
var buildSpinner *spinner.Spinner buildSpinner := spinner.New()
if !verbose { buildSpinner.SetSpinSpeed(50)
buildSpinner = spinner.New() buildSpinner.Start("Installing Mewn asset packer...")
buildSpinner.SetSpinSpeed(50)
buildSpinner.Start("Installing Mewn asset packer...")
}
err := programHelper.InstallGoPackage("github.com/leaanthony/mewn/cmd/mewn") err := programHelper.InstallGoPackage("github.com/leaanthony/mewn/cmd/mewn")
if err != nil { if err != nil {
if buildSpinner != nil { buildSpinner.Error()
buildSpinner.Error()
}
return err return err
} }
if buildSpinner != nil { buildSpinner.Success()
buildSpinner.Success()
}
} }
return nil return nil
} }
@@ -332,15 +206,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 {
@@ -351,14 +216,9 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
} }
// Check if frontend deps have been updated // Check if frontend deps have been updated
var feSpinner *spinner.Spinner feSpinner := spinner.New("Ensuring frontend dependencies are up to date (This may take a while)")
if !projectOptions.Verbose { feSpinner.SetSpinSpeed(50)
feSpinner = spinner.New("Ensuring frontend dependencies are up to date (This may take a while)") feSpinner.Start()
feSpinner.SetSpinSpeed(50)
feSpinner.Start()
} else {
println("Ensuring frontend dependencies are up to date (This may take a while)")
}
requiresNPMInstall := true requiresNPMInstall := true
@@ -390,11 +250,7 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
if savedMD5sum == packageJSONMD5 { if savedMD5sum == packageJSONMD5 {
// Same - no need for reinstall // Same - no need for reinstall
requiresNPMInstall = false requiresNPMInstall = false
if feSpinner != nil { feSpinner.Success("Skipped frontend dependencies (-f to force rebuild)")
feSpinner.Success("Skipped frontend dependencies (-f to force rebuild)")
} else {
println("Skipped frontend dependencies (-f to force rebuild)")
}
} }
} }
} }
@@ -403,16 +259,12 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
// Different? Build // Different? Build
if requiresNPMInstall || forceRebuild { if requiresNPMInstall || forceRebuild {
// Install dependencies // Install dependencies
err = NewProgramHelper(projectOptions.Verbose).RunCommand(projectOptions.FrontEnd.Install) err = NewProgramHelper().RunCommand(projectOptions.FrontEnd.Install)
if err != nil { if err != nil {
if feSpinner != nil { feSpinner.Error()
feSpinner.Error()
}
return err return err
} }
if feSpinner != nil { feSpinner.Success()
feSpinner.Success()
}
// Update md5sum file // Update md5sum file
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644) ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
@@ -425,7 +277,7 @@ func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forc
} }
// Build frontend // Build frontend
err = BuildFrontend(projectOptions) err = BuildFrontend(projectOptions.FrontEnd.Build)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -47,12 +47,6 @@ const (
ArcoLinux ArcoLinux
// Manjaro distribution // Manjaro distribution
Manjaro Manjaro
// ManjaroARM distribution
ManjaroARM
// Deepin distribution
Deepin
// Raspbian distribution
Raspbian
) )
// DistroInfo contains all the information relating to a linux distribution // DistroInfo contains all the information relating to a linux distribution
@@ -108,7 +102,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
version = strings.Trim(splitLine[1], "\"") version = strings.Trim(splitLine[1], "\"")
} }
} }
// Check distro name against list of distros // Check distro name against list of distros
switch osID { switch osID {
case "fedora": case "fedora":
@@ -141,12 +134,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
result.Distribution = ArcoLinux result.Distribution = ArcoLinux
case "manjaro": case "manjaro":
result.Distribution = Manjaro result.Distribution = Manjaro
case "manjaro-arm":
result.Distribution = ManjaroARM
case "deepin":
result.Distribution = Deepin
case "raspbian":
result.Distribution = Raspbian
default: default:
result.Distribution = Unknown result.Distribution = Unknown
} }

View File

@@ -3,6 +3,7 @@ package cmd
import ( import (
"log" "log"
"github.com/leaanthony/mewn"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
@@ -78,14 +79,11 @@ func (l *LinuxDB) GetDistro(distro string) *Distribution {
// NewLinuxDB creates a new LinuxDB instance from the bundled // NewLinuxDB creates a new LinuxDB instance from the bundled
// linuxdb.yaml file. // linuxdb.yaml file.
func NewLinuxDB() *LinuxDB { func NewLinuxDB() *LinuxDB {
data, err := fs.LoadRelativeFile("./linuxdb.yaml") data := mewn.Bytes("./linuxdb.yaml")
if err != nil {
log.Fatal("Could not load linuxdb.yaml")
}
result := LinuxDB{ result := LinuxDB{
Distributions: make(map[string]*Distribution), Distributions: make(map[string]*Distribution),
} }
err = result.ImportData(data) err := result.ImportData(data)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@@ -82,15 +82,6 @@ distributions:
gccversioncommand: *gccdumpfullversion gccversioncommand: *gccdumpfullversion
programs: *debiandefaultprograms programs: *debiandefaultprograms
libraries: *debiandefaultlibraries libraries: *debiandefaultlibraries
deepin:
id: deepin
releases:
default:
version: default
name: Deepin
gccversioncommand: *gccdumpfullversion
programs: *debiandefaultprograms
libraries: *debiandefaultlibraries
void: void:
id: void id: void
releases: releases:
@@ -167,15 +158,6 @@ distributions:
help: Please install with `sudo pacman -S gtk3` and try again help: Please install with `sudo pacman -S gtk3` and try again
- name: webkit2gtk - name: webkit2gtk
help: Please install with `sudo pacman -S webkit2gtk` and try again help: Please install with `sudo pacman -S webkit2gtk` and try again
arcolinux:
id: arcolinux
releases:
default:
version: default
name: ArcoLinux
gccversioncommand: *gccdumpversion
programs: *archdefaultprograms
libraries: *archdefaultlibraries
manjaro: manjaro:
id: manjaro id: manjaro
releases: releases:
@@ -185,12 +167,12 @@ distributions:
gccversioncommand: *gccdumpversion gccversioncommand: *gccdumpversion
programs: *archdefaultprograms programs: *archdefaultprograms
libraries: *archdefaultlibraries libraries: *archdefaultlibraries
manjaro-arm: arcolinux:
id: manjaro-arm id: arcolinux
releases: releases:
default: default:
version: default version: default
name: Manjaro-ARM name: ArcoLinux
gccversioncommand: *gccdumpversion gccversioncommand: *gccdumpversion
programs: *archdefaultprograms programs: *archdefaultprograms
libraries: *archdefaultlibraries libraries: *archdefaultlibraries
@@ -212,14 +194,4 @@ distributions:
- name: gtk+:3 - name: gtk+:3
help: Please install with `sudo emerge gtk+:3` and try again help: Please install with `sudo emerge gtk+:3` and try again
- name: webkit-gtk - name: webkit-gtk
help: Please install with `sudo emerge webkit-gtk` and try again help: Please install with `sudo emerge webkit-gtk` and try again
raspbian:
id: raspbian
releases:
default:
version: default
name: Raspbian
gccversioncommand: *gccdumpfullversion
programs: *debiandefaultprograms
libraries: *debiandefaultlibraries

View File

@@ -18,19 +18,17 @@ import (
// 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(),
} }
} }
@@ -65,23 +63,16 @@ 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 // Check we have the exe
if !b.fs.FileExists(po.BinaryName) { if !b.fs.FileExists(po.BinaryName) {
// Check cross-compiled application return fmt.Errorf("cannot bundle non-existent binary file '%s'. Please build with 'wails build' first", po.BinaryName)
if b.platform == runtime.GOOS {
return fmt.Errorf("cannot bundle non-existent binary file '%s'. Please build with 'wails build' first", po.BinaryName)
}
if _, err := b.fs.FindFile(path.Join(b.fs.Cwd(), "build"), "darwin"); err != nil {
return fmt.Errorf("cannot bundle non-existent cross-compiled binary file '%s'. Please build with 'wails build -x darwin' first", po.BinaryName)
}
} }
return b.packageOSX(po) return b.packageOSX(po)
case "windows": case "windows":
@@ -89,7 +80,7 @@ func (b *PackageHelper) Package(po *ProjectOptions) error {
case "linux": case "linux":
return fmt.Errorf("linux is not supported at this time. Please see https://github.com/wailsapp/wails/issues/2") 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)
} }
} }
@@ -112,22 +103,6 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
// Check binary exists // Check binary exists
source := path.Join(b.fs.Cwd(), exe) source := path.Join(b.fs.Cwd(), exe)
if b.platform != runtime.GOOS {
file, err := b.fs.FindFile(path.Join(b.fs.Cwd(), "build"), "darwin")
if err != nil {
return err
}
// rename to exe
if err := os.Rename(path.Join(b.fs.Cwd(), "build", file), path.Join(b.fs.Cwd(), "build", exe)); err != nil {
return err
}
source = path.Join(b.fs.Cwd(), "build", exe)
}
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?", exe) return fmt.Errorf("Target '%s' not available. Has it been compiled yet?", exe)
@@ -217,36 +192,16 @@ 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")
// cross-compile batfile, err := fs.LocalDir(".")
if b.platform != runtime.GOOS { if err != nil {
folder, err := os.Getwd() return err
if err != nil { }
return err
}
args := []string{ windresBatFile := filepath.Join(batfile.fullPath, "windres.bat")
"docker", "run", "--rm", windresCommand := []string{windresBatFile, sysofile, tgtRCFile}
"-v", folder + ":/build", err = NewProgramHelper().RunCommandArray(windresCommand)
"--entrypoint", "/bin/sh", if err != nil {
"techknowlogick/xgo", return err
"-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")
windresCommand := []string{windresBatFile, sysofile, tgtRCFile}
err = NewProgramHelper().RunCommandArray(windresCommand)
if err != nil {
return err
}
} }
// clean up // clean up

View File

@@ -3,7 +3,6 @@ package cmd
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"strings" "strings"
@@ -12,22 +11,14 @@ import (
// ProgramHelper - Utility functions around installed applications // ProgramHelper - Utility functions around installed applications
type ProgramHelper struct { type ProgramHelper struct {
shell *ShellHelper shell *ShellHelper
verbose bool
} }
// NewProgramHelper - Creates a new ProgramHelper // NewProgramHelper - Creates a new ProgramHelper
func NewProgramHelper(verbose ...bool) *ProgramHelper { func NewProgramHelper() *ProgramHelper {
result := &ProgramHelper{ return &ProgramHelper{
shell: NewShellHelper(), shell: NewShellHelper(),
} }
if len(verbose) > 0 {
result.verbose = verbose[0]
if result.verbose {
result.shell.SetVerbose()
}
}
return result
} }
// IsInstalled tries to determine if the given binary name is installed // IsInstalled tries to determine if the given binary name is installed
@@ -38,9 +29,8 @@ func (p *ProgramHelper) IsInstalled(programName string) bool {
// Program - A struct to define an installed application/binary // Program - A struct to define an installed application/binary
type Program struct { type Program struct {
Name string `json:"name"` Name string `json:"name"`
Path string `json:"path"` Path string `json:"path"`
verbose bool
} }
// FindProgram attempts to find the given program on the system.FindProgram // FindProgram attempts to find the given program on the system.FindProgram
@@ -55,9 +45,8 @@ func (p *ProgramHelper) FindProgram(programName string) *Program {
return nil return nil
} }
return &Program{ return &Program{
Name: programName, Name: programName,
Path: path, Path: path,
verbose: p.verbose,
} }
} }
@@ -74,18 +63,12 @@ func (p *Program) Run(vars ...string) (stdout, stderr string, exitCode int, err
return "", "", 1, err return "", "", 1, err
} }
cmd := exec.Command(command, vars...) cmd := exec.Command(command, vars...)
if !p.verbose { var stdo, stde bytes.Buffer
var stdo, stde bytes.Buffer cmd.Stdout = &stdo
cmd.Stdout = &stdo cmd.Stderr = &stde
cmd.Stderr = &stde err = cmd.Run()
err = cmd.Run() stdout = string(stdo.Bytes())
stdout = string(stdo.Bytes()) stderr = string(stde.Bytes())
stderr = string(stde.Bytes())
} else {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
}
// https://stackoverflow.com/questions/10385551/get-exit-code-go // https://stackoverflow.com/questions/10385551/get-exit-code-go
if err != nil { if err != nil {

View File

@@ -142,26 +142,21 @@ func (ph *ProjectHelper) NewProjectOptions() *ProjectOptions {
// ProjectOptions holds all the options available for a project // ProjectOptions holds all the options available for a project
type ProjectOptions struct { type ProjectOptions struct {
Name string `json:"name"` Name string `json:"name"`
Description string `json:"description"` Description string `json:"description"`
Author *author `json:"author,omitempty"` Author *author `json:"author,omitempty"`
Version string `json:"version"` Version string `json:"version"`
OutputDirectory string `json:"-"` OutputDirectory string `json:"-"`
UseDefaults bool `json:"-"` UseDefaults bool `json:"-"`
Template string `json:"-"` Template string `json:"-"`
BinaryName string `json:"binaryname"` BinaryName string `json:"binaryname"`
FrontEnd *frontend `json:"frontend,omitempty"` FrontEnd *frontend `json:"frontend,omitempty"`
NPMProjectName string `json:"-"` NPMProjectName string `json:"-"`
system *SystemHelper system *SystemHelper
log *Logger log *Logger
templates *TemplateHelper templates *TemplateHelper
selectedTemplate *TemplateDetails selectedTemplate *TemplateDetails
WailsVersion string WailsVersion string
typescriptDefsFilename string
Verbose bool `json:"-"`
CrossCompile bool `json:"-"`
Platform string `json:"-"`
Architecture string `json:"-"`
} }
// Defaults sets the default project template // Defaults sets the default project template
@@ -170,11 +165,6 @@ func (po *ProjectOptions) Defaults() {
po.WailsVersion = Version po.WailsVersion = Version
} }
// SetTypescriptDefsFilename indicates that we want to generate typescript bindings to the given file
func (po *ProjectOptions) SetTypescriptDefsFilename(filename string) {
po.typescriptDefsFilename = filename
}
// GetNPMBinaryName returns the type of package manager used by the project // GetNPMBinaryName returns the type of package manager used by the project
func (po *ProjectOptions) GetNPMBinaryName() (PackageManager, error) { func (po *ProjectOptions) GetNPMBinaryName() (PackageManager, error) {
if po.FrontEnd == nil { if po.FrontEnd == nil {

View File

@@ -8,7 +8,6 @@ import (
// ShellHelper helps with Shell commands // ShellHelper helps with Shell commands
type ShellHelper struct { type ShellHelper struct {
verbose bool
} }
// NewShellHelper creates a new ShellHelper! // NewShellHelper creates a new ShellHelper!
@@ -16,27 +15,16 @@ func NewShellHelper() *ShellHelper {
return &ShellHelper{} return &ShellHelper{}
} }
// SetVerbose sets the verbose flag
func (sh *ShellHelper) SetVerbose() {
sh.verbose = true
}
// Run the given command // Run the given command
func (sh *ShellHelper) Run(command string, vars ...string) (stdout, stderr string, err error) { func (sh *ShellHelper) Run(command string, vars ...string) (stdout, stderr string, err error) {
cmd := exec.Command(command, vars...) cmd := exec.Command(command, vars...)
cmd.Env = append(os.Environ(), "GO111MODULE=on") cmd.Env = append(os.Environ(), "GO111MODULE=on")
if !sh.verbose { var stdo, stde bytes.Buffer
var stdo, stde bytes.Buffer cmd.Stdout = &stdo
cmd.Stdout = &stdo cmd.Stderr = &stde
cmd.Stderr = &stde err = cmd.Run()
err = cmd.Run() stdout = string(stdo.Bytes())
stdout = string(stdo.Bytes()) stderr = string(stde.Bytes())
stderr = string(stde.Bytes())
} else {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
}
return return
} }
@@ -45,17 +33,11 @@ func (sh *ShellHelper) RunInDirectory(dir string, command string, vars ...string
cmd := exec.Command(command, vars...) cmd := exec.Command(command, vars...)
cmd.Dir = dir cmd.Dir = dir
cmd.Env = append(os.Environ(), "GO111MODULE=on") cmd.Env = append(os.Environ(), "GO111MODULE=on")
if !sh.verbose { var stdo, stde bytes.Buffer
var stdo, stde bytes.Buffer cmd.Stdout = &stdo
cmd.Stdout = &stdo cmd.Stderr = &stde
cmd.Stderr = &stde err = cmd.Run()
err = cmd.Run() stdout = string(stdo.Bytes())
stdout = string(stdo.Bytes()) stderr = string(stde.Bytes())
stderr = string(stde.Bytes())
} else {
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
}
return return
} }

View File

@@ -274,9 +274,9 @@ 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: case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon:
libraryChecker = DpkgInstalled libraryChecker = DpkgInstalled
case Arch, ArcoLinux, Manjaro, ManjaroARM: case Arch, Manjaro, ArcoLinux:
libraryChecker = PacmanInstalled libraryChecker = PacmanInstalled
case CentOS, Fedora: case CentOS, Fedora:
libraryChecker = RpmInstalled libraryChecker = RpmInstalled

View File

@@ -3,7 +3,7 @@
"version": "0.0.0", "version": "0.0.0",
"scripts": { "scripts": {
"ng": "npx ng", "ng": "npx ng",
"start": "npx ng serve --poll=2000 --host=0.0.0.0", "start": "npx ng serve --poll=2000",
"build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false", "build": "npx ng build --single-bundle true --output-hashing none --prod --bundle-styles false",
"test": "npx ng test", "test": "npx ng test",
"lint": "npx ng lint", "lint": "npx ng lint",

View File

@@ -37,6 +37,7 @@ module.exports = {
} }
}, },
devServer: { devServer: {
disableHostCheck: true disableHostCheck: true,
host: "localhost"
} }
}; };

View File

@@ -37,6 +37,7 @@ module.exports = {
} }
}, },
devServer: { devServer: {
disableHostCheck: true disableHostCheck: true,
host: "localhost"
} }
}; };

View File

@@ -37,6 +37,7 @@ module.exports = {
} }
}, },
devServer: { devServer: {
disableHostCheck: true disableHostCheck: true,
host: 'localhost'
} }
}; };

View File

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

View File

@@ -40,7 +40,7 @@ Create your first project by running 'wails init'.`
} }
// Check Mewn // Check Mewn
err = cmd.CheckMewn(false) err = cmd.CheckMewn()
if err != nil { if err != nil {
return err return err
} }

View File

@@ -7,6 +7,7 @@ import (
"log" "log"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
@@ -182,13 +183,35 @@ func checkProjectDirectory() error {
func getWailsVersion() (*semver.Version, error) { func getWailsVersion() (*semver.Version, error) {
checkSpinner.Start("Get Wails Version") checkSpinner.Start("Get Wails Version")
var result *semver.Version
result, err := cmd.GetWailsVersion() // Load file
var err error
goModFile, err = filepath.Abs(filepath.Join(".", "go.mod"))
if err != nil { if err != nil {
checkSpinner.Error(err.Error()) checkSpinner.Error()
return nil, err 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 return result, nil
} }

View File

@@ -3,10 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"runtime"
"strings"
"github.com/leaanthony/slicer"
"github.com/leaanthony/spinner" "github.com/leaanthony/spinner"
"github.com/wailsapp/wails/cmd" "github.com/wailsapp/wails/cmd"
) )
@@ -16,10 +13,6 @@ func init() {
var packageApp = false var packageApp = false
var forceRebuild = false var forceRebuild = false
var debugMode = false var debugMode = false
var typescriptFilename = ""
var verbose = false
var platform = ""
buildSpinner := spinner.NewSpinner() buildSpinner := spinner.NewSpinner()
buildSpinner.SetSpinSpeed(50) buildSpinner.SetSpinSpeed(50)
@@ -28,10 +21,7 @@ func init() {
LongDescription(commandDescription). LongDescription(commandDescription).
BoolFlag("p", "Package application on successful build", &packageApp). BoolFlag("p", "Package application on successful build", &packageApp).
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).
StringFlag("t", "Generate Typescript definitions to given file (at runtime)", &typescriptFilename).
StringFlag("x", "Cross-compile application to specified platform via xgo", &platform)
initCmd.Action(func() error { initCmd.Action(func() error {
@@ -47,7 +37,6 @@ 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
@@ -84,13 +73,16 @@ func init() {
return err return err
} }
// Ensure that runtime init.js is the production version // Ensure that runtime init.js is the production version
err = cmd.InstallProdRuntime(projectDir, projectOptions) err = cmd.InstallProdRuntime(projectDir, projectOptions)
if err != nil { if err != nil {
return err return err
} }
} }
// Move to project directory // Move to project directory
err = os.Chdir(projectDir) err = os.Chdir(projectDir)
if err != nil { if err != nil {
@@ -98,7 +90,7 @@ func init() {
} }
// Install dependencies // Install dependencies
err = cmd.InstallGoDependencies(projectOptions.Verbose) err = cmd.InstallGoDependencies()
if err != nil { if err != nil {
return err return err
} }
@@ -109,55 +101,6 @@ func init() {
buildMode = cmd.BuildModeDebug buildMode = cmd.BuildModeDebug
} }
// Save if we wish to dump typescript or not
if typescriptFilename != "" {
projectOptions.SetTypescriptDefsFilename(typescriptFilename)
}
// Update go.mod if it is out of sync with current version
outofsync, err := cmd.GoModOutOfSync()
if err != nil {
return err
}
gomodVersion, err := cmd.GetWailsVersion()
if err != nil {
return err
}
if outofsync {
syncMessage := fmt.Sprintf("Updating go.mod (Wails version %s => %s)", gomodVersion, cmd.Version)
buildSpinner := spinner.NewSpinner(syncMessage)
buildSpinner.Start()
err := cmd.UpdateGoModVersion()
if err != nil {
buildSpinner.Error(err.Error())
return err
}
buildSpinner.Success()
}
// Set cross-compile
projectOptions.Platform = runtime.GOOS
if len(platform) > 0 {
projectOptions.CrossCompile = true
projectOptions.Platform = platform
projectOptions.Architecture = "amd64"
// check build architecture
if strings.Contains(platform, "/") {
p := strings.Split(platform, "/")
projectOptions.Platform = p[0]
projectOptions.Architecture = p[1]
}
// Check supported platforms
supportedPlatforms := slicer.String([]string{"linux/amd64", "linux/386", "windows/amd64", "windows/386", "darwin/amd64"})
targetPlatform := projectOptions.Platform + "/" + projectOptions.Architecture
if !supportedPlatforms.Contains(targetPlatform) {
println("\n*** WARNING: Unsupported target platform", targetPlatform+".", "Supported:", supportedPlatforms.Join(", "))
}
}
err = cmd.BuildApplication(projectOptions.BinaryName, forceRebuild, buildMode, packageApp, projectOptions) err = cmd.BuildApplication(projectOptions.BinaryName, forceRebuild, buildMode, packageApp, projectOptions)
if err != nil { if err != nil {
return err return err

View File

@@ -10,14 +10,12 @@ import (
func init() { func init() {
var forceRebuild = false var forceRebuild = false
var verbose = false
buildSpinner := spinner.NewSpinner() buildSpinner := spinner.NewSpinner()
buildSpinner.SetSpinSpeed(50) buildSpinner.SetSpinSpeed(50)
commandDescription := `This command builds then serves your application in bridge mode. Useful for developing your app in a browser.` commandDescription := `This command builds then serves your application in bridge mode. Useful for developing your app in a browser.`
initCmd := app.Command("serve", "Run your Wails project in bridge mode"). initCmd := app.Command("serve", "Run your Wails project in bridge mode").
LongDescription(commandDescription). LongDescription(commandDescription).
BoolFlag("verbose", "Verbose output", &verbose).
BoolFlag("f", "Force rebuild of application components", &forceRebuild) BoolFlag("f", "Force rebuild of application components", &forceRebuild)
initCmd.Action(func() error { initCmd.Action(func() error {
@@ -27,14 +25,13 @@ func init() {
fmt.Println() fmt.Println()
// Check Mewn is installed // Check Mewn is installed
err := cmd.CheckMewn(verbose) err := cmd.CheckMewn()
if err != nil { if err != nil {
return err return err
} }
// 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
@@ -54,7 +51,7 @@ func init() {
} }
// Install dependencies // Install dependencies
err = cmd.InstallGoDependencies(projectOptions.Verbose) err = cmd.InstallGoDependencies()
if err != nil { if err != nil {
return err return err
} }

7
go.mod
View File

@@ -3,6 +3,9 @@ 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/abadojack/whatlanggo v1.0.1
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc // indirect
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect
github.com/fatih/color v1.7.0 github.com/fatih/color v1.7.0
github.com/go-playground/colors v1.2.0 github.com/go-playground/colors v1.2.0
github.com/gorilla/websocket v1.4.0 github.com/gorilla/websocket v1.4.0
@@ -10,7 +13,7 @@ require (
github.com/kennygrant/sanitize v1.2.4 github.com/kennygrant/sanitize v1.2.4
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/leaanthony/mewn v0.10.7 github.com/leaanthony/mewn v0.10.7
github.com/leaanthony/slicer v1.4.1 github.com/leaanthony/slicer v1.3.2
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
@@ -28,5 +31,3 @@ require (
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.12

10
go.sum
View File

@@ -7,6 +7,12 @@ github.com/abadojack/whatlanggo v1.0.1/go.mod h1:66WiQbSbJBIlOZMsvbKe5m6pzQovxCH
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=
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc h1:VBS1z48BFEe00G81z8MKOtwX7f/ISkuH38NscT8iVPw=
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc/go.mod h1:ABJPuor7YlcsHmvJ1QxX38e2NcufLY3hm0yXv+cy9sI=
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac h1:DpMwFluHWoZpV9ex5XjkWO4HyCz5HLVI8XbHw0FhHi4=
github.com/dchest/htmlmin v0.0.0-20150526090704-e254725e81ac/go.mod h1:XsAE+b4rOZc8gvgsgF+wU75mNBvBcyED1wdd9PBLlJ0=
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 h1:Fm10/KNuoAyBm2P5P5H91Xy21hGcZnBdjR+cMdytv1M=
github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947/go.mod h1:Dv9D0NUlAsaQcGQZa5kc5mqR9ua72SmA8VXi4cd+cBw=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/go-playground/colors v1.2.0 h1:0EdjTXKrr2g1L/LQTYtIqabeHpZuGZz1U4osS1T8+5M= github.com/go-playground/colors v1.2.0 h1:0EdjTXKrr2g1L/LQTYtIqabeHpZuGZz1U4osS1T8+5M=
@@ -28,8 +34,8 @@ github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/leaanthony/mewn v0.10.7 h1:jCcNJyIUOpwj+I5SuATvCugDjHkoo+j6ubEOxxrxmPA= github.com/leaanthony/mewn v0.10.7 h1:jCcNJyIUOpwj+I5SuATvCugDjHkoo+j6ubEOxxrxmPA=
github.com/leaanthony/mewn v0.10.7/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ= github.com/leaanthony/mewn v0.10.7/go.mod h1:CRkTx8unLiSSilu/Sd7i1LwrdaAL+3eQ3ses99qGMEQ=
github.com/leaanthony/slicer v1.4.1 h1:X/SmRIDhkUAolP79mSTO0jTcVX1k504PJBqvV6TwP0w= github.com/leaanthony/slicer v1.3.2 h1:kGWWFoyaY5WzwGrUsHXMmGbssuYthP4qYBNlkNpNAB8=
github.com/leaanthony/slicer v1.4.1/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/slicer v1.3.2/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ=
github.com/leaanthony/spinner v0.5.3 h1:IMTvgdQCec5QA4qRy0wil4XsRP+QcG1OwLWVK/LPZ5Y= github.com/leaanthony/spinner v0.5.3 h1:IMTvgdQCec5QA4qRy0wil4XsRP+QcG1OwLWVK/LPZ5Y=
github.com/leaanthony/spinner v0.5.3/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo= github.com/leaanthony/spinner v0.5.3/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo=
github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8= github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

View File

@@ -2,11 +2,7 @@ package binding
import ( import (
"fmt" "fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect" "reflect"
"strings"
"unicode" "unicode"
"github.com/wailsapp/wails/lib/interfaces" "github.com/wailsapp/wails/lib/interfaces"
@@ -14,8 +10,6 @@ import (
"github.com/wailsapp/wails/lib/messages" "github.com/wailsapp/wails/lib/messages"
) )
var typescriptDefinitionFilename = ""
// Manager handles method binding // Manager handles method binding
type Manager struct { type Manager struct {
methods map[string]*boundMethod methods map[string]*boundMethod
@@ -27,19 +21,16 @@ type Manager struct {
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
objectsToBind []interface{} objectsToBind []interface{}
bindPackageNames bool // Package name should be considered when binding bindPackageNames bool // Package name should be considered when binding
structList map[string][]string // structList["mystruct"] = []string{"Method1", "Method2"}
} }
// NewManager creates a new Manager struct // NewManager creates a new Manager struct
func NewManager() interfaces.BindingManager { func NewManager() interfaces.BindingManager {
result := &Manager{ result := &Manager{
methods: make(map[string]*boundMethod), methods: make(map[string]*boundMethod),
functions: make(map[string]*boundFunction), functions: make(map[string]*boundFunction),
log: logger.NewCustomLogger("Bind"), log: logger.NewCustomLogger("Bind"),
internalMethods: newInternalMethods(), internalMethods: newInternalMethods(),
structList: make(map[string][]string),
} }
return result return result
} }
@@ -97,55 +88,9 @@ func (b *Manager) initialise() error {
return err return err
} }
} }
// If we wish to generate a typescript definition file...
if typescriptDefinitionFilename != "" {
err := b.generateTypescriptDefinitions()
if err != nil {
return err
}
}
return nil return nil
} }
// Generate typescript
func (b *Manager) generateTypescriptDefinitions() error {
var output strings.Builder
for structname, methodList := range b.structList {
structname = strings.SplitN(structname, ".", 2)[1]
output.WriteString(fmt.Sprintf("Interface %s {\n", structname))
for _, method := range methodList {
output.WriteString(fmt.Sprintf("\t%s: (...args : any[]) => Promise\n", method))
}
output.WriteString("}\n")
}
output.WriteString("\n")
output.WriteString("Interface Backend {\n")
for structname := range b.structList {
structname = strings.SplitN(structname, ".", 2)[1]
output.WriteString(fmt.Sprintf("\t%[1]s: %[1]s\n", structname))
}
output.WriteString("}\n")
globals := `
declare global {
interface Window {
backend: Backend;
}
}`
output.WriteString(globals)
b.log.Info("Written Typescript file: " + typescriptDefinitionFilename)
dir := filepath.Dir(typescriptDefinitionFilename)
os.MkdirAll(dir, 0755)
return ioutil.WriteFile(typescriptDefinitionFilename, []byte(output.String()), 0755)
}
// bind the given struct method // bind the given struct method
func (b *Manager) bindMethod(object interface{}) error { func (b *Manager) bindMethod(object interface{}) error {
@@ -159,12 +104,6 @@ func (b *Manager) bindMethod(object interface{}) error {
b.log.Debugf("Processing struct: %s", baseName) b.log.Debugf("Processing struct: %s", baseName)
// Calc actual name
actualName := strings.TrimPrefix(baseName, "main.")
if b.structList[actualName] == nil {
b.structList[actualName] = []string{}
}
// Iterate over method definitions // Iterate over method definitions
for i := 0; i < objectType.NumMethod(); i++ { for i := 0; i < objectType.NumMethod(); i++ {
@@ -174,8 +113,6 @@ func (b *Manager) bindMethod(object interface{}) error {
fullMethodName := baseName + "." + methodName fullMethodName := baseName + "." + methodName
method := reflect.ValueOf(object).MethodByName(methodName) method := reflect.ValueOf(object).MethodByName(methodName)
b.structList[actualName] = append(b.structList[actualName], methodName)
// Skip unexported methods // Skip unexported methods
if !unicode.IsUpper([]rune(methodName)[0]) { if !unicode.IsUpper([]rune(methodName)[0]) {
continue continue

View File

@@ -3,6 +3,7 @@ package event
import ( import (
"fmt" "fmt"
"sync" "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"
@@ -12,7 +13,6 @@ import (
// Manager handles and processes events // Manager handles and processes events
type Manager struct { type Manager struct {
incomingEvents chan *messages.EventData incomingEvents chan *messages.EventData
quitChannel chan struct{}
listeners map[string][]*eventListener listeners map[string][]*eventListener
running bool running bool
log *logger.CustomLogger log *logger.CustomLogger
@@ -24,7 +24,6 @@ type Manager struct {
func NewManager() interfaces.EventManager { func NewManager() interfaces.EventManager {
return &Manager{ return &Manager{
incomingEvents: make(chan *messages.EventData, 100), incomingEvents: make(chan *messages.EventData, 100),
quitChannel: make(chan struct{}, 1),
listeners: make(map[string][]*eventListener), listeners: make(map[string][]*eventListener),
running: false, running: false,
log: logger.NewCustomLogger("Events"), log: logger.NewCustomLogger("Events"),
@@ -142,8 +141,8 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
} }
} }
} }
case <-e.quitChannel: default:
e.running = false time.Sleep(1 * time.Millisecond)
} }
} }
e.wg.Done() e.wg.Done()
@@ -153,7 +152,7 @@ func (e *Manager) Start(renderer interfaces.Renderer) {
// Shutdown is called when exiting the Application // Shutdown is called when exiting the Application
func (e *Manager) Shutdown() { func (e *Manager) Shutdown() {
e.log.Debug("Shutting Down") e.log.Debug("Shutting Down")
e.quitChannel <- struct{}{} e.running = false
e.log.Debug("Waiting for main loop to exit") e.log.Debug("Waiting for main loop to exit")
e.wg.Wait() e.wg.Wait()
} }

View File

@@ -1,13 +1,9 @@
package interfaces package interfaces
// CallbackFunc defines the signature of a function required to be provided to the
// Dispatch function so that the response may be returned
type CallbackFunc func(string) error
// IPCManager is the event manager interface // IPCManager is the event manager interface
type IPCManager interface { type IPCManager interface {
BindRenderer(Renderer) BindRenderer(Renderer)
Dispatch(message string, f CallbackFunc) Dispatch(message string)
Start(eventManager EventManager, bindingManager BindingManager) Start(eventManager EventManager, bindingManager BindingManager)
Shutdown() Shutdown()
} }

View File

@@ -12,6 +12,7 @@ type Renderer interface {
// Binding // Binding
NewBinding(bindingName string) error NewBinding(bindingName string) error
Callback(data string) error
// Events // Events
NotifyEvent(eventData *messages.EventData) error NotifyEvent(eventData *messages.EventData) error

View File

@@ -3,6 +3,7 @@ package ipc
import ( import (
"fmt" "fmt"
"sync" "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"
@@ -123,8 +124,8 @@ 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,
}) })
case <-i.quitChannel: default:
i.running = false time.Sleep(1 * time.Millisecond)
} }
} }
i.log.Debug("Stopping") i.log.Debug("Stopping")
@@ -135,10 +136,10 @@ func (i *Manager) Start(eventManager interfaces.EventManager, bindingManager int
// Dispatch receives JSON encoded messages from the renderer. // Dispatch receives JSON encoded messages from the renderer.
// It processes the message to ensure that it is valid and places // It processes the message to ensure that it is valid and places
// the processed message on the message queue // the processed message on the message queue
func (i *Manager) Dispatch(message string, cb interfaces.CallbackFunc) { func (i *Manager) Dispatch(message string) {
// Create a new IPC Message // Create a new IPC Message
incomingMessage, err := newIPCMessage(message, i.SendResponse(cb)) incomingMessage, err := newIPCMessage(message, i.SendResponse)
if err != nil { if err != nil {
i.log.ErrorFields("Could not understand incoming message! ", map[string]interface{}{ i.log.ErrorFields("Could not understand incoming message! ", map[string]interface{}{
"message": message, "message": message,
@@ -158,25 +159,23 @@ func (i *Manager) Dispatch(message string, cb interfaces.CallbackFunc) {
} }
// SendResponse sends the given response back to the frontend // SendResponse sends the given response back to the frontend
// It sends the data back to the correct renderer by way of the provided callback function func (i *Manager) SendResponse(response *ipcResponse) error {
func (i *Manager) SendResponse(cb interfaces.CallbackFunc) func(i *ipcResponse) error {
return func(response *ipcResponse) error { // Serialise the Message
// Serialise the Message data, err := response.Serialise()
data, err := response.Serialise() if err != nil {
if err != nil { fmt.Printf(err.Error())
fmt.Printf(err.Error()) return err
return err
}
return cb(data)
} }
// Call back to the front end
return i.renderer.Callback(data)
} }
// Shutdown is called when exiting the Application // Shutdown is called when exiting the Application
func (i *Manager) Shutdown() { func (i *Manager) Shutdown() {
i.log.Debug("Shutdown called") i.log.Debug("Shutdown called")
i.quitChannel <- struct{}{} i.running = false
i.log.Debug("Waiting of main loop shutdown") i.log.Debug("Waiting of main loop shutdown")
i.wg.Wait() i.wg.Wait()
} }

View File

@@ -1,10 +1,262 @@
package renderer package renderer
import ( import (
bridge "github.com/wailsapp/wails/lib/renderer/bridge" "encoding/json"
"fmt"
"net/http"
"strings"
"sync"
"github.com/dchest/htmlmin"
"github.com/gorilla/websocket"
"github.com/leaanthony/mewn"
"github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/messages"
) )
// NewBridge returns a new Bridge struct type messageType int
func NewBridge() *bridge.Bridge {
return &bridge.Bridge{} const (
jsMessage messageType = iota
cssMessage
htmlMessage
notifyMessage
bindingMessage
callbackMessage
wailsRuntimeMessage
)
func (m messageType) toString() string {
return [...]string{"j", "s", "h", "n", "b", "c", "w"}[m]
}
// Bridge is a backend that opens a local web server
// and renders the files over a websocket
type Bridge struct {
// Common
log *logger.CustomLogger
ipcManager interfaces.IPCManager
appConfig interfaces.AppConfig
eventManager interfaces.EventManager
bindingCache []string
// Bridge specific
initialisationJS []string
server *http.Server
theConnection *websocket.Conn
// Mutex for writing to the socket
lock sync.Mutex
}
// Initialise the Bridge Renderer
func (h *Bridge) Initialise(appConfig interfaces.AppConfig, ipcManager interfaces.IPCManager, eventManager interfaces.EventManager) error {
h.ipcManager = ipcManager
h.appConfig = appConfig
h.eventManager = eventManager
ipcManager.BindRenderer(h)
h.log = logger.NewCustomLogger("Bridge")
return nil
}
func (h *Bridge) evalJS(js string, mtype messageType) error {
message := mtype.toString() + js
if h.theConnection == nil {
h.initialisationJS = append(h.initialisationJS, message)
} else {
// Prepend message type to message
h.sendMessage(h.theConnection, message)
}
return nil
}
// EnableConsole not needed for bridge!
func (h *Bridge) EnableConsole() {
}
func (h *Bridge) injectCSS(css string) {
// Minify css to overcome issues in the browser with carriage returns
minified, err := htmlmin.Minify([]byte(css), &htmlmin.Options{
MinifyStyles: true,
})
if err != nil {
h.log.Fatal("Unable to minify CSS: " + css)
}
minifiedCSS := string(minified)
minifiedCSS = strings.Replace(minifiedCSS, "\\", "\\\\", -1)
minifiedCSS = strings.Replace(minifiedCSS, "'", "\\'", -1)
minifiedCSS = strings.Replace(minifiedCSS, "\n", " ", -1)
inject := fmt.Sprintf("wails._.InjectCSS('%s')", minifiedCSS)
h.evalJS(inject, cssMessage)
}
func (h *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024)
if err != nil {
http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
}
h.theConnection = conn
h.log.Infof("Connection from frontend accepted [%p].", h.theConnection)
conn.SetCloseHandler(func(int, string) error {
h.log.Infof("Connection dropped [%p].", h.theConnection)
h.theConnection = nil
return nil
})
go h.start(conn)
}
func (h *Bridge) sendMessage(conn *websocket.Conn, msg string) {
h.lock.Lock()
defer h.lock.Unlock()
if err := conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
h.log.Error(err.Error())
}
}
func (h *Bridge) start(conn *websocket.Conn) {
// set external.invoke
h.log.Infof("Connected to frontend.")
wailsRuntime := mewn.String("../../runtime/assets/wails.js")
h.evalJS(wailsRuntime, wailsRuntimeMessage)
// Inject bindings
for _, binding := range h.bindingCache {
h.evalJS(binding, bindingMessage)
}
// Emit that everything is loaded and ready
h.eventManager.Emit("wails:ready")
for {
messageType, buffer, err := conn.ReadMessage()
if messageType == -1 {
return
}
if err != nil {
h.log.Errorf("Error reading message: ", err)
continue
}
h.log.Debugf("Got message: %#v\n", string(buffer))
h.ipcManager.Dispatch(string(buffer))
}
}
// Run the app in Bridge mode!
func (h *Bridge) Run() error {
h.server = &http.Server{Addr: ":34115"}
http.HandleFunc("/bridge", h.wsBridgeHandler)
h.log.Info("Bridge mode started.")
h.log.Info("The frontend will connect automatically.")
err := h.server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
h.log.Fatal(err.Error())
}
return err
}
// NewBinding creates a new binding with the frontend
func (h *Bridge) NewBinding(methodName string) error {
h.bindingCache = append(h.bindingCache, methodName)
return nil
}
// SelectFile is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SelectFile() string {
h.log.Warn("SelectFile() unsupported in bridge mode")
return ""
}
// SelectDirectory is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SelectDirectory() string {
h.log.Warn("SelectDirectory() unsupported in bridge mode")
return ""
}
// SelectSaveFile is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SelectSaveFile() string {
h.log.Warn("SelectSaveFile() unsupported in bridge mode")
return ""
}
// Callback sends a callback to the frontend
func (h *Bridge) Callback(data string) error {
return h.evalJS(data, callbackMessage)
}
// NotifyEvent notifies the frontend of an event
func (h *Bridge) NotifyEvent(event *messages.EventData) error {
// Look out! Nils about!
var err error
if event == nil {
err = fmt.Errorf("Sent nil event to renderer.webViewRenderer")
h.log.Error(err.Error())
return err
}
// Default data is a blank array
data := []byte("[]")
// Process event data
if event.Data != nil {
// Marshall the data
data, err = json.Marshal(event.Data)
if err != nil {
h.log.Errorf("Cannot unmarshall JSON data in event: %s ", err.Error())
return err
}
}
message := fmt.Sprintf("window.wails._.Notify('%s','%s')", event.Name, data)
return h.evalJS(message, notifyMessage)
}
// SetColour is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SetColour(colour string) error {
h.log.WarnFields("SetColour ignored for Bridge more", logger.Fields{"col": colour})
return nil
}
// Fullscreen is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) Fullscreen() {
h.log.Warn("Fullscreen() unsupported in bridge mode")
}
// UnFullscreen is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) UnFullscreen() {
h.log.Warn("UnFullscreen() unsupported in bridge mode")
}
// SetTitle is currently unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SetTitle(title string) {
h.log.WarnFields("SetTitle() unsupported in bridge mode", logger.Fields{"title": title})
}
// Close is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) Close() {
h.log.Debug("Shutting down")
err := h.server.Close()
if err != nil {
h.log.Errorf(err.Error())
}
} }

View File

@@ -1,214 +0,0 @@
package renderer
import (
"encoding/json"
"fmt"
"net/http"
"sync"
"github.com/gorilla/websocket"
"github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger"
"github.com/wailsapp/wails/lib/messages"
)
type messageType int
const (
jsMessage messageType = iota
cssMessage
htmlMessage
notifyMessage
bindingMessage
callbackMessage
wailsRuntimeMessage
)
func (m messageType) toString() string {
return [...]string{"j", "s", "h", "n", "b", "c", "w"}[m]
}
// Bridge is a backend that opens a local web server
// and renders the files over a websocket
type Bridge struct {
// Common
log *logger.CustomLogger
ipcManager interfaces.IPCManager
appConfig interfaces.AppConfig
eventManager interfaces.EventManager
bindingCache []string
// Bridge specific
server *http.Server
lock sync.Mutex
sessions map[string]session
}
// Initialise the Bridge Renderer
func (h *Bridge) Initialise(appConfig interfaces.AppConfig, ipcManager interfaces.IPCManager, eventManager interfaces.EventManager) error {
h.sessions = map[string]session{}
h.ipcManager = ipcManager
h.appConfig = appConfig
h.eventManager = eventManager
ipcManager.BindRenderer(h)
h.log = logger.NewCustomLogger("Bridge")
return nil
}
// EnableConsole not needed for bridge!
func (h *Bridge) EnableConsole() {
}
func (h *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024)
if err != nil {
http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
}
h.log.Infof("Connection from frontend accepted [%s].", conn.RemoteAddr().String())
h.startSession(conn)
}
func (h *Bridge) startSession(conn *websocket.Conn) {
s := session{
conn: conn,
bindingCache: h.bindingCache,
ipc: h.ipcManager,
log: h.log,
eventManager: h.eventManager,
}
conn.SetCloseHandler(func(int, string) error {
h.log.Infof("Connection dropped [%s].", s.Identifier())
h.eventManager.Emit("wails:bridge:session:closed", s.Identifier())
h.lock.Lock()
defer h.lock.Unlock()
delete(h.sessions, s.Identifier())
return nil
})
h.lock.Lock()
defer h.lock.Unlock()
go s.start(len(h.sessions) == 0)
h.sessions[s.Identifier()] = s
}
// Run the app in Bridge mode!
func (h *Bridge) Run() error {
h.server = &http.Server{Addr: ":34115"}
http.HandleFunc("/bridge", h.wsBridgeHandler)
h.log.Info("Bridge mode started.")
h.log.Info("The frontend will connect automatically.")
err := h.server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
h.log.Fatal(err.Error())
}
return err
}
// NewBinding creates a new binding with the frontend
func (h *Bridge) NewBinding(methodName string) error {
h.bindingCache = append(h.bindingCache, methodName)
return nil
}
// SelectFile is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SelectFile() string {
h.log.Warn("SelectFile() unsupported in bridge mode")
return ""
}
// SelectDirectory is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SelectDirectory() string {
h.log.Warn("SelectDirectory() unsupported in bridge mode")
return ""
}
// SelectSaveFile is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SelectSaveFile() string {
h.log.Warn("SelectSaveFile() unsupported in bridge mode")
return ""
}
// NotifyEvent notifies the frontend of an event
func (h *Bridge) NotifyEvent(event *messages.EventData) error {
// Look out! Nils about!
var err error
if event == nil {
err = fmt.Errorf("Sent nil event to renderer.webViewRenderer")
h.log.Error(err.Error())
return err
}
// Default data is a blank array
data := []byte("[]")
// Process event data
if event.Data != nil {
// Marshall the data
data, err = json.Marshal(event.Data)
if err != nil {
h.log.Errorf("Cannot unmarshall JSON data in event: %s ", err.Error())
return err
}
}
message := fmt.Sprintf("window.wails._.Notify('%s','%s')", event.Name, data)
dead := []session{}
for _, session := range h.sessions {
err := session.evalJS(message, notifyMessage)
if err != nil {
h.log.Debugf("Failed to send message to %s - Removing listener : %v", session.Identifier(), err)
h.log.Infof("Connection from [%v] unresponsive - dropping", session.Identifier())
dead = append(dead, session)
}
}
h.lock.Lock()
defer h.lock.Unlock()
for _, session := range dead {
delete(h.sessions, session.Identifier())
}
return nil
}
// SetColour is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SetColour(colour string) error {
h.log.WarnFields("SetColour ignored for Bridge more", logger.Fields{"col": colour})
return nil
}
// Fullscreen is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) Fullscreen() {
h.log.Warn("Fullscreen() unsupported in bridge mode")
}
// UnFullscreen is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) UnFullscreen() {
h.log.Warn("UnFullscreen() unsupported in bridge mode")
}
// SetTitle is currently unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) SetTitle(title string) {
h.log.WarnFields("SetTitle() unsupported in bridge mode", logger.Fields{"title": title})
}
// Close is unsupported for Bridge but required
// for the Renderer interface
func (h *Bridge) Close() {
h.log.Debug("Shutting down")
err := h.server.Close()
if err != nil {
h.log.Errorf(err.Error())
}
}

View File

@@ -1,90 +0,0 @@
package renderer
import (
"sync"
"github.com/gorilla/websocket"
"github.com/leaanthony/mewn"
"github.com/wailsapp/wails/lib/interfaces"
"github.com/wailsapp/wails/lib/logger"
)
// TODO Move this back into bridge.go
// session represents a single websocket session
type session struct {
bindingCache []string
conn *websocket.Conn
eventManager interfaces.EventManager
log *logger.CustomLogger
ipc interfaces.IPCManager
// Mutex for writing to the socket
lock sync.Mutex
}
// Identifier returns a string identifier for the remote connection.
// Taking the form of the client's <ip address>:<port>.
func (s *session) Identifier() string {
if s.conn != nil {
return s.conn.RemoteAddr().String()
}
return ""
}
func (s *session) sendMessage(msg string) error {
s.lock.Lock()
defer s.lock.Unlock()
if err := s.conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
s.log.Debug(err.Error())
return err
}
return nil
}
func (s *session) start(firstSession bool) {
s.log.Infof("Connected to frontend.")
wailsRuntime := mewn.String("../../runtime/assets/wails.js")
s.evalJS(wailsRuntime, wailsRuntimeMessage)
// Inject bindings
for _, binding := range s.bindingCache {
s.evalJS(binding, bindingMessage)
}
s.eventManager.Emit("wails:bridge:session:started", s.Identifier())
// Emit that everything is loaded and ready
if firstSession {
s.eventManager.Emit("wails:ready")
}
for {
messageType, buffer, err := s.conn.ReadMessage()
if messageType == -1 {
return
}
if err != nil {
s.log.Errorf("Error reading message: %v", err)
continue
}
s.log.Debugf("Got message: %#v\n", string(buffer))
s.ipc.Dispatch(string(buffer), s.Callback)
}
}
// Callback sends a callback to the frontend
func (s *session) Callback(data string) error {
return s.evalJS(data, callbackMessage)
}
func (s *session) evalJS(js string, mtype messageType) error {
// Prepend message type to message
return s.sendMessage(mtype.toString() + js)
}

File diff suppressed because one or more lines are too long

View File

@@ -58,7 +58,7 @@ func (w *WebView) Initialise(config interfaces.AppConfig, ipc interfaces.IPCMana
URL: config.GetDefaultHTML(), URL: config.GetDefaultHTML(),
Debug: !config.GetDisableInspector(), Debug: !config.GetDisableInspector(),
ExternalInvokeCallback: func(_ wv.WebView, message string) { ExternalInvokeCallback: func(_ wv.WebView, message string) {
w.ipc.Dispatch(message, w.callback) w.ipc.Dispatch(message)
}, },
}) })
@@ -299,8 +299,8 @@ func (w *WebView) SelectSaveFile() string {
return result return result
} }
// callback sends a callback to the frontend // Callback sends a callback to the frontend
func (w *WebView) callback(data string) error { func (w *WebView) Callback(data string) error {
callbackCMD := fmt.Sprintf("window.wails._.Callback('%s');", data) callbackCMD := fmt.Sprintf("window.wails._.Callback('%s');", data)
return w.evalJS(callbackCMD) return w.evalJS(callbackCMD)
} }

View File

@@ -14,7 +14,7 @@ function init() {
window.wailsbridge = { window.wailsbridge = {
reconnectOverlay: null, reconnectOverlay: null,
reconnectTimer: 300, reconnectTimer: 300,
wsURL: 'ws://' + window.location.hostname + ':34115/bridge', wsURL: 'ws://localhost:34115/bridge',
connectionState: null, connectionState: null,
config: {}, config: {},
websocket: null, websocket: null,

File diff suppressed because one or more lines are too long

View File

@@ -52,8 +52,7 @@ function Once(eventName, callback) {
* @param {string} eventName * @param {string} eventName
*/ */
function Emit(eventName) { function Emit(eventName) {
var args = [eventName].slice.call(arguments); return window.wails.Events.Emit(eventName);
return window.wails.Events.Emit.apply(null, args);
} }

View File

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