mirror of
https://github.com/taigrr/wails.git
synced 2026-04-02 13:19:00 -07:00
Compare commits
1 Commits
485-permis
...
fix-runtim
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
848a9ea260 |
6
.github/workflows/latest-pre.yml
vendored
6
.github/workflows/latest-pre.yml
vendored
@@ -13,10 +13,10 @@ jobs:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.13
|
||||
- name: Set up Go 1.12
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
go-version: 1.12
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
@@ -27,6 +27,6 @@ jobs:
|
||||
go get -v -d ./...
|
||||
- name: Build
|
||||
run: go build -v ./cmd/wails
|
||||
|
||||
|
||||
- name: Test
|
||||
run: ./wails version
|
||||
|
||||
6
.github/workflows/pr.yml
vendored
6
.github/workflows/pr.yml
vendored
@@ -13,10 +13,10 @@ jobs:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.13
|
||||
- name: Set up Go 1.12
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
go-version: 1.12
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
@@ -27,6 +27,6 @@ jobs:
|
||||
go get -v -d ./...
|
||||
- name: Build
|
||||
run: go build -v ./cmd/wails
|
||||
|
||||
|
||||
- name: Test
|
||||
run: ./wails version
|
||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -4,7 +4,7 @@ on:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- '!**pre**'
|
||||
- '!**pre**'
|
||||
jobs:
|
||||
|
||||
build:
|
||||
@@ -15,10 +15,10 @@ jobs:
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
|
||||
- name: Set up Go 1.13
|
||||
- name: Set up Go 1.12
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.13
|
||||
go-version: 1.12
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
@@ -29,6 +29,6 @@ jobs:
|
||||
go get -v -d ./...
|
||||
- name: Build
|
||||
run: go build -v ./cmd/wails
|
||||
|
||||
|
||||
- name: Test
|
||||
run: ./wails version
|
||||
@@ -15,23 +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)
|
||||
* [iceleo-com](https://github.com/iceleo-com)
|
||||
* [fallendusk](https://github.com/fallendusk)
|
||||
* [Florian Didran](https://github.com/fdidron)
|
||||
* [Nikolai Zimmermann](https://github.com/Chronophylos)
|
||||
* [Toyam Cox](https://github.com/Vaelatern)
|
||||
* [Robin Eklind](https://github.com/mewmew)
|
||||
* [Kris Raney](https://github.com/kraney)
|
||||
* [Jack Mordaunt](https://github.com/JackMordaunt)
|
||||
* [Michael Hipp](https://github.com/MichaelHipp)
|
||||
* [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)
|
||||
* [Tim Kipp](https://github.com/timkippdev)
|
||||
* [Dmitry Gomzyakov](https://github.com/kyoto44)
|
||||
* [Arthur Wiebe](https://github.com/artooro)
|
||||
* [Ilgıt Yıldırım](https://github.com/ilgityildirim)
|
||||
* [Travis McLane](https://github.com/tmclane)
|
||||
@@ -12,6 +12,7 @@
|
||||
<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/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://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>
|
||||
|
||||
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!
|
||||
@@ -35,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:
|
||||
|
||||
- Go 1.13
|
||||
- Go 1.12
|
||||
- npm
|
||||
|
||||
### MacOS
|
||||
@@ -54,9 +55,9 @@ _Debian: 8, 9, 10_
|
||||
|
||||
_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 / Ctlos Linux
|
||||
#### Arch Linux
|
||||
|
||||
`sudo pacman -S webkit2gtk gtk3`
|
||||
|
||||
|
||||
13
app.go
13
app.go
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/wailsapp/wails/lib/ipc"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/lib/renderer"
|
||||
wailsruntime "github.com/wailsapp/wails/runtime"
|
||||
)
|
||||
|
||||
// -------------------------------- Compile time Flags ------------------------------
|
||||
@@ -21,16 +20,6 @@ import (
|
||||
// BuildMode indicates what mode we are in
|
||||
var BuildMode = cmd.BuildModeProd
|
||||
|
||||
// Runtime is the Go Runtime struct
|
||||
type Runtime = wailsruntime.Runtime
|
||||
|
||||
// Store is a state store used for syncing with
|
||||
// the front end
|
||||
type Store = wailsruntime.Store
|
||||
|
||||
// CustomLogger is a specialised logger
|
||||
type CustomLogger = logger.CustomLogger
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// App defines the main application struct
|
||||
@@ -136,7 +125,7 @@ func (a *App) start() error {
|
||||
a.ipc.Start(a.eventManager, a.bindingManager)
|
||||
|
||||
// Create the runtime
|
||||
a.runtime = wailsruntime.NewRuntime(a.eventManager, a.renderer)
|
||||
a.runtime = NewRuntime(a.eventManager, a.renderer)
|
||||
|
||||
// Start binding manager and give it our renderer
|
||||
err = a.bindingManager.Start(a.renderer, a.runtime)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build linux darwin !windows
|
||||
// +build +linux +darwin !windows
|
||||
|
||||
package wails
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
21
cmd/fs.go
21
cmd/fs.go
@@ -12,7 +12,6 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/leaanthony/slicer"
|
||||
)
|
||||
@@ -48,22 +47,6 @@ func (fs *FSHelper) FileExists(path string) bool {
|
||||
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
|
||||
// set to the given data. It will create intermediary directories if needed.
|
||||
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
|
||||
func (fs *FSHelper) RemoveFiles(files []string, continueOnError bool) error {
|
||||
func (fs *FSHelper) RemoveFiles(files []string) error {
|
||||
for _, filename := range files {
|
||||
err := os.Remove(filename)
|
||||
if err != nil && !continueOnError {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
289
cmd/helpers.go
289
cmd/helpers.go
@@ -5,15 +5,12 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/leaanthony/mewn"
|
||||
"github.com/leaanthony/mewn/lib"
|
||||
"github.com/leaanthony/slicer"
|
||||
"github.com/leaanthony/spinner"
|
||||
)
|
||||
@@ -59,141 +56,21 @@ func InstallGoDependencies(verbose bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EmbedAssets will embed the built frontend assets via mewn.
|
||||
func EmbedAssets() ([]string, error) {
|
||||
mewnFiles := lib.GetMewnFiles([]string{}, false)
|
||||
// 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 {
|
||||
|
||||
referencedAssets, err := lib.GetReferencedAssets(mewnFiles)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
targetFiles := []string{}
|
||||
|
||||
for _, referencedAsset := range referencedAssets {
|
||||
packfileData, err := lib.GeneratePackFileString(referencedAsset, false)
|
||||
// Generate Windows assets if needed
|
||||
if runtime.GOOS == "windows" {
|
||||
cleanUp := !packageApp
|
||||
err := NewPackageHelper().PackageWindows(projectOptions, cleanUp)
|
||||
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
|
||||
if err := CheckMewn(projectOptions.Verbose); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := CheckWindres(); err != nil {
|
||||
err := CheckMewn(projectOptions.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -213,13 +90,18 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
||||
}
|
||||
|
||||
buildCommand := slicer.String()
|
||||
buildCommand.Add("go")
|
||||
buildCommand.Add("mewn")
|
||||
|
||||
if buildMode == BuildModeBridge {
|
||||
// Ignore errors
|
||||
buildCommand.Add("-i")
|
||||
}
|
||||
|
||||
buildCommand.Add("build")
|
||||
|
||||
if binaryName != "" {
|
||||
// Alter binary name based on OS
|
||||
switch projectOptions.Platform {
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
if !strings.HasSuffix(binaryName, ".exe") {
|
||||
binaryName += ".exe"
|
||||
@@ -229,7 +111,7 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
||||
binaryName = strings.TrimSuffix(binaryName, ".exe")
|
||||
}
|
||||
}
|
||||
buildCommand.Add("-o", filepath.Join("build", binaryName))
|
||||
buildCommand.Add("-o", binaryName)
|
||||
}
|
||||
|
||||
// If we are forcing a rebuild
|
||||
@@ -237,13 +119,31 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
||||
buildCommand.Add("-a")
|
||||
}
|
||||
|
||||
buildCommand.AddSlice([]string{"-ldflags", ldFlags(projectOptions, buildMode)})
|
||||
|
||||
if projectOptions.Verbose {
|
||||
fmt.Printf("Command: %v\n", buildCommand.AsSlice())
|
||||
// Setup ld flags
|
||||
ldflags := "-w -s "
|
||||
if buildMode == BuildModeDebug {
|
||||
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 packSpinner != nil {
|
||||
packSpinner.Error()
|
||||
@@ -254,57 +154,7 @@ func BuildNative(binaryName string, forceRebuild bool, buildMode string, project
|
||||
packSpinner.Success()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// packageApp
|
||||
if packageApp {
|
||||
err = PackageApplication(projectOptions)
|
||||
if err != nil {
|
||||
@@ -317,14 +167,22 @@ func BuildApplication(binaryName string, forceRebuild bool, buildMode string, pa
|
||||
|
||||
// PackageApplication will attempt to package the application in a platform dependent way
|
||||
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
|
||||
if projectOptions.Verbose {
|
||||
packageSpinner = spinner.New("Packaging application...")
|
||||
packageSpinner = spinner.New(message)
|
||||
packageSpinner.SetSpinSpeed(50)
|
||||
packageSpinner.Start()
|
||||
}
|
||||
|
||||
err := NewPackageHelper(projectOptions.Platform).Package(projectOptions)
|
||||
err := NewPackageHelper().Package(projectOptions)
|
||||
if err != nil {
|
||||
if packageSpinner != nil {
|
||||
packageSpinner.Error()
|
||||
@@ -386,7 +244,7 @@ func CheckMewn(verbose bool) (err error) {
|
||||
|
||||
// CheckWindres checks if Windres is installed and if not, aborts
|
||||
func CheckWindres() (err error) {
|
||||
if runtime.GOOS != "windows" { // FIXME: Handle windows cross-compile for windows!
|
||||
if runtime.GOOS != "windows" {
|
||||
return nil
|
||||
}
|
||||
programHelper := NewProgramHelper()
|
||||
@@ -396,15 +254,6 @@ func CheckWindres() (err error) {
|
||||
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
|
||||
func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forceRebuild bool, caller string) error {
|
||||
|
||||
@@ -528,7 +377,7 @@ func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
|
||||
time.Sleep(2 * time.Second)
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
@@ -544,33 +393,3 @@ func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
41
cmd/linux.go
41
cmd/linux.go
@@ -53,18 +53,6 @@ const (
|
||||
Deepin
|
||||
// Raspbian distribution
|
||||
Raspbian
|
||||
// Tumbleweed (OpenSUSE) distribution
|
||||
Tumbleweed
|
||||
// Leap (OpenSUSE) distribution
|
||||
Leap
|
||||
// ArchLabs distribution
|
||||
ArchLabs
|
||||
// PopOS distribution
|
||||
PopOS
|
||||
// Solus distribution
|
||||
Solus
|
||||
// Ctlos Linux distribution
|
||||
Ctlos
|
||||
)
|
||||
|
||||
// DistroInfo contains all the information relating to a linux distribution
|
||||
@@ -113,7 +101,7 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
}
|
||||
switch splitLine[0] {
|
||||
case "ID":
|
||||
osID = strings.ToLower(strings.Trim(splitLine[1], "\""))
|
||||
osID = strings.Trim(splitLine[1], "\"")
|
||||
case "NAME":
|
||||
osNAME = strings.Trim(splitLine[1], "\"")
|
||||
case "VERSION_ID":
|
||||
@@ -129,10 +117,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
result.Distribution = CentOS
|
||||
case "arch":
|
||||
result.Distribution = Arch
|
||||
case "archlabs":
|
||||
result.Distribution = ArchLabs
|
||||
case "ctlos":
|
||||
result.Distribution = Ctlos
|
||||
case "debian":
|
||||
result.Distribution = Debian
|
||||
case "ubuntu":
|
||||
@@ -163,14 +147,6 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
result.Distribution = Deepin
|
||||
case "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:
|
||||
result.Distribution = Unknown
|
||||
}
|
||||
@@ -207,17 +183,6 @@ func DpkgInstalled(packageName string) (bool, error) {
|
||||
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.
|
||||
func PacmanInstalled(packageName string) (bool, error) {
|
||||
program := NewProgramHelper()
|
||||
@@ -289,9 +254,5 @@ func RequestSupportForDistribution(distroInfo *DistroInfo) error {
|
||||
|
||||
fmt.Println("Opening browser to file request.")
|
||||
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
|
||||
}
|
||||
|
||||
@@ -22,25 +22,5 @@ UBUNTU_CODENAME=bionic
|
||||
if result.Distribution != Ubuntu {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,15 +28,6 @@ distributions:
|
||||
gccversioncommand: &gccdumpfullversion -dumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
pop:
|
||||
id: pop
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Pop!_OS
|
||||
gccversioncommand: &gccdumpfullversion -dumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
kali:
|
||||
id: kali
|
||||
releases:
|
||||
@@ -185,24 +176,6 @@ distributions:
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
archlabs:
|
||||
id: archlabs
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: ArchLabs
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
ctlos:
|
||||
id: ctlos
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Ctlos Linux
|
||||
gccversioncommand: *gccdumpversion
|
||||
programs: *archdefaultprograms
|
||||
libraries: *archdefaultlibraries
|
||||
manjaro:
|
||||
id: manjaro
|
||||
releases:
|
||||
@@ -250,51 +223,3 @@ distributions:
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
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
|
||||
|
||||
294
cmd/package.go
294
cmd/package.go
@@ -1,12 +1,9 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/png"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
@@ -17,24 +14,21 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/jackmordaunt/icns"
|
||||
"golang.org/x/image/draw"
|
||||
)
|
||||
|
||||
// PackageHelper helps with the 'wails package' command
|
||||
type PackageHelper struct {
|
||||
platform string
|
||||
fs *FSHelper
|
||||
log *Logger
|
||||
system *SystemHelper
|
||||
fs *FSHelper
|
||||
log *Logger
|
||||
system *SystemHelper
|
||||
}
|
||||
|
||||
// NewPackageHelper creates a new PackageHelper!
|
||||
func NewPackageHelper(platform string) *PackageHelper {
|
||||
func NewPackageHelper() *PackageHelper {
|
||||
return &PackageHelper{
|
||||
platform: platform,
|
||||
fs: NewFSHelper(),
|
||||
log: NewLogger(),
|
||||
system: NewSystemHelper(),
|
||||
fs: NewFSHelper(),
|
||||
log: NewLogger(),
|
||||
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 {
|
||||
if val != "" {
|
||||
return val
|
||||
@@ -174,30 +63,29 @@ func defaultString(val string, defaultVal string) string {
|
||||
func (b *PackageHelper) getPackageFileBaseDir() string {
|
||||
// Calculate template base dir
|
||||
_, 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
|
||||
func (b *PackageHelper) Package(po *ProjectOptions) error {
|
||||
switch b.platform {
|
||||
switch runtime.GOOS {
|
||||
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)
|
||||
case "windows":
|
||||
return b.PackageWindows(po, true)
|
||||
return b.PackageWindows(po, false)
|
||||
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:
|
||||
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
|
||||
func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
||||
build := path.Join(b.fs.Cwd(), "build")
|
||||
|
||||
system := NewSystemHelper()
|
||||
config, err := system.LoadConfig()
|
||||
@@ -212,68 +100,39 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
||||
packageID := strings.Join([]string{"wails", name, version}, ".")
|
||||
plistData := newPlistData(name, exe, packageID, version, author)
|
||||
appname := po.Name + ".app"
|
||||
plistFilename := path.Join(build, appname, "Contents", "Info.plist")
|
||||
customPlist := path.Join(b.fs.Cwd(), "info.plist")
|
||||
|
||||
// Check binary exists
|
||||
source := path.Join(build, exe)
|
||||
if po.CrossCompile == true {
|
||||
file, err := b.fs.FindFile(build, "darwin")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
source = path.Join(build, file)
|
||||
}
|
||||
|
||||
source := path.Join(b.fs.Cwd(), exe)
|
||||
if !b.fs.FileExists(source) {
|
||||
// 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
|
||||
os.RemoveAll(appname)
|
||||
|
||||
// Create directories
|
||||
exeDir := path.Join(build, appname, "/Contents/MacOS")
|
||||
exeDir := path.Join(b.fs.Cwd(), appname, "/Contents/MacOS")
|
||||
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)
|
||||
tmpl := template.New("infoPlist")
|
||||
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
|
||||
infoPlist, err := ioutil.ReadFile(plistFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmpl.Parse(string(infoPlist))
|
||||
|
||||
// Do we have a custom plist in the project directory?
|
||||
if !fs.FileExists(customPlist) {
|
||||
|
||||
// No - create a new plist from our defaults
|
||||
tmpl := template.New("infoPlist")
|
||||
plistFile := filepath.Join(b.getPackageFileBaseDir(), "info.plist")
|
||||
infoPlist, err := ioutil.ReadFile(plistFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmpl.Parse(string(infoPlist))
|
||||
|
||||
// Write the template to a buffer
|
||||
var tpl bytes.Buffer
|
||||
err = tmpl.Execute(&tpl, plistData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Save to the package
|
||||
err = ioutil.WriteFile(plistFilename, tpl.Bytes(), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Also write to project directory for customisation
|
||||
err = ioutil.WriteFile(customPlist, tpl.Bytes(), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Yes - we have a plist. Copy it to the package verbatim
|
||||
err = fs.CopyFile(customPlist, plistFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Write the template to a buffer
|
||||
var tpl bytes.Buffer
|
||||
err = tmpl.Execute(&tpl, plistData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filename := path.Join(b.fs.Cwd(), appname, "Contents", "Info.plist")
|
||||
err = ioutil.WriteFile(filename, tpl.Bytes(), 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Copy executable
|
||||
@@ -291,37 +150,22 @@ func (b *PackageHelper) packageOSX(po *ProjectOptions) error {
|
||||
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
|
||||
func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||
outputDir := b.fs.Cwd()
|
||||
basename := strings.TrimSuffix(po.BinaryName, ".exe")
|
||||
|
||||
// Copy default icon if needed
|
||||
icon, err := b.copyIcon()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate icon from PNG
|
||||
err = generateWindowsIcon(icon, basename+".ico")
|
||||
if err != nil {
|
||||
return err
|
||||
// Copy icon
|
||||
tgtIconFile := filepath.Join(b.fs.Cwd(), basename+".ico")
|
||||
if !b.fs.FileExists(tgtIconFile) {
|
||||
srcIconfile := filepath.Join(b.getPackageFileBaseDir(), "wails.ico")
|
||||
err := b.fs.CopyFile(srcIconfile, tgtIconFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Copy manifest
|
||||
tgtManifestFile := filepath.Join(outputDir, basename+".exe.manifest")
|
||||
tgtManifestFile := filepath.Join(b.fs.Cwd(), basename+".exe.manifest")
|
||||
if !b.fs.FileExists(tgtManifestFile) {
|
||||
srcManifestfile := filepath.Join(b.getPackageFileBaseDir(), "wails.exe.manifest")
|
||||
err := b.fs.CopyFile(srcManifestfile, tgtManifestFile)
|
||||
@@ -331,7 +175,7 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||
}
|
||||
|
||||
// Copy rc file
|
||||
tgtRCFile := filepath.Join(outputDir, basename+".rc")
|
||||
tgtRCFile := filepath.Join(b.fs.Cwd(), basename+".rc")
|
||||
if !b.fs.FileExists(tgtRCFile) {
|
||||
srcRCfile := filepath.Join(b.getPackageFileBaseDir(), "wails.rc")
|
||||
rcfilebytes, err := ioutil.ReadFile(srcRCfile)
|
||||
@@ -346,37 +190,33 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||
}
|
||||
|
||||
// Build syso
|
||||
sysofile := filepath.Join(outputDir, basename+"-res.syso")
|
||||
sysofile := filepath.Join(b.fs.Cwd(), basename+"-res.syso")
|
||||
|
||||
// cross-compile
|
||||
if b.platform != runtime.GOOS {
|
||||
args := []string{
|
||||
"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
|
||||
}
|
||||
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)
|
||||
windresBatFile := filepath.Join(batfile.fullPath, "windres.bat")
|
||||
windresCommand := []string{windresBatFile, sysofile, tgtRCFile}
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *PackageHelper) copyIcon() (string, error) {
|
||||
func (b *PackageHelper) copyIcon(resourceDir string) (string, error) {
|
||||
|
||||
// TODO: Read this from project.json
|
||||
const appIconFilename = "appicon.png"
|
||||
@@ -401,7 +241,7 @@ func (b *PackageHelper) copyIcon() (string, error) {
|
||||
|
||||
func (b *PackageHelper) packageIconOSX(resourceDir string) error {
|
||||
|
||||
srcIcon, err := b.copyIcon()
|
||||
srcIcon, err := b.copyIcon(resourceDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
100 ICON "$NAME$.ico"
|
||||
110 24 "$NAME$.exe.manifest"
|
||||
100 24 "$NAME$.exe.manifest"
|
||||
@@ -138,11 +138,11 @@ func (p *ProgramHelper) RunCommand(command string) error {
|
||||
|
||||
// RunCommandArray runs the command specified in the array
|
||||
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
|
||||
program, err := exec.LookPath(programCommand)
|
||||
program, err := exec.LookPath(program)
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -158,10 +159,6 @@ type ProjectOptions struct {
|
||||
WailsVersion string
|
||||
typescriptDefsFilename string
|
||||
Verbose bool `json:"-"`
|
||||
CrossCompile bool
|
||||
Platform string
|
||||
Architecture string
|
||||
LdFlags string
|
||||
}
|
||||
|
||||
// Defaults sets the default project template
|
||||
@@ -336,6 +333,11 @@ func processBinaryName(po *ProjectOptions) {
|
||||
if po.BinaryName == "" {
|
||||
var binaryNameComputed = computeBinaryName(po.Name)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -5,11 +5,12 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
// SystemHelper - Defines everything related to the system
|
||||
@@ -37,11 +38,10 @@ func NewSystemHelper() *SystemHelper {
|
||||
// setSystemDirs calculates the system directories it is interested in
|
||||
func (s *SystemHelper) setSystemDirs() {
|
||||
var err error
|
||||
s.homeDir, err = os.UserHomeDir()
|
||||
s.homeDir, err = homedir.Dir()
|
||||
if err != nil {
|
||||
log.Fatal("Cannot find home directory! Please file a bug report!")
|
||||
}
|
||||
|
||||
// TODO: A better config system
|
||||
s.wailsSystemDir = filepath.Join(s.homeDir, ".wails")
|
||||
s.wailsSystemConfig = filepath.Join(s.wailsSystemDir, s.configFilename)
|
||||
@@ -132,7 +132,7 @@ func (s *SystemHelper) setup() error {
|
||||
}
|
||||
|
||||
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.
|
||||
`
|
||||
|
||||
@@ -274,18 +274,16 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
||||
distroInfo := GetLinuxDistroInfo()
|
||||
|
||||
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
|
||||
case Arch, ArcoLinux, ArchLabs, Ctlos, Manjaro, ManjaroARM:
|
||||
case Arch, ArcoLinux, Manjaro, ManjaroARM:
|
||||
libraryChecker = PacmanInstalled
|
||||
case CentOS, Fedora, Tumbleweed, Leap:
|
||||
case CentOS, Fedora:
|
||||
libraryChecker = RpmInstalled
|
||||
case Gentoo:
|
||||
libraryChecker = EqueryInstalled
|
||||
case VoidLinux:
|
||||
libraryChecker = XbpsInstalled
|
||||
case Solus:
|
||||
libraryChecker = EOpkgInstalled
|
||||
default:
|
||||
return false, RequestSupportForDistribution(distroInfo)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ const routes: Routes = [];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot(routes,{useHash:true})
|
||||
RouterModule.forRoot(routes)
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.4",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react": "^16.13.0",
|
||||
"react-dom": "^16.13.0",
|
||||
"wails-react-scripts": "3.0.1-2",
|
||||
"react-modal": "3.11.2",
|
||||
"@wailsapp/runtime": "^1.0.10"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.8 KiB |
@@ -1,13 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Web site created using create-react-app" />
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
@@ -23,9 +20,8 @@
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="app"></div>
|
||||
<!--
|
||||
@@ -38,6 +34,5 @@
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 176 KiB |
@@ -6,16 +6,6 @@
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
@@ -3,16 +3,11 @@
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
|
||||
@@ -1,35 +1,48 @@
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import Modal from 'react-modal';
|
||||
|
||||
function HelloWorld() {
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [result, setResult] = useState(null);
|
||||
class HelloWorld extends React.Component {
|
||||
constructor(props, context) {
|
||||
super();
|
||||
this.state = {
|
||||
showModal: false
|
||||
};
|
||||
|
||||
const handleOpenModal = () => {
|
||||
setShowModal(true);
|
||||
this.handleOpenModal = this.handleOpenModal.bind(this);
|
||||
this.handleCloseModal = this.handleCloseModal.bind(this);
|
||||
}
|
||||
|
||||
window.backend.basic().then((result) => setResult(result));
|
||||
};
|
||||
handleOpenModal () {
|
||||
this.setState({ showModal: true });
|
||||
|
||||
const handleCloseModal = () => {
|
||||
setShowModal(false);
|
||||
};
|
||||
window.backend.basic().then(result =>
|
||||
this.setState({
|
||||
result
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<button onClick={() => handleOpenModal()} type="button">
|
||||
Hello
|
||||
</button>
|
||||
<Modal
|
||||
appElement={document.getElementById("app")}
|
||||
isOpen={showModal}
|
||||
contentLabel="Minimal Modal Example"
|
||||
>
|
||||
<p>{result}</p>
|
||||
<button onClick={() => handleCloseModal()}>Close Modal</button>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
handleCloseModal () {
|
||||
this.setState({ showModal: false });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { result } = this.state;
|
||||
return (
|
||||
<div className="App">
|
||||
<button onClick={this.handleOpenModal} type="button">
|
||||
Hello
|
||||
</button>
|
||||
<Modal
|
||||
isOpen={this.state.showModal}
|
||||
contentLabel="Minimal Modal Example"
|
||||
>
|
||||
<p>{result}</p>
|
||||
<button onClick={this.handleCloseModal}>Close Modal</button>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default HelloWorld;
|
||||
|
||||
@@ -3,20 +3,9 @@ import ReactDOM from 'react-dom';
|
||||
import 'core-js/stable';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
|
||||
import * as Wails from '@wailsapp/runtime';
|
||||
|
||||
Wails.Init(() => {
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById("app")
|
||||
);
|
||||
ReactDOM.render(<App />, document.getElementById('app'));
|
||||
});
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||
serviceWorker.unregister();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "React JS",
|
||||
"version": "1.0.0",
|
||||
"shortdescription": "Create React App v4 template",
|
||||
"description": "Create React App v4 standard tooling",
|
||||
"shortdescription": "Create React App v3 template",
|
||||
"description": "Create React App v3 standar tooling",
|
||||
"install": "npm install",
|
||||
"build": "npm run build",
|
||||
"author": "bh90210 <ktc@pm.me>",
|
||||
|
||||
4
cmd/templates/svelte/frontend/.gitignore
vendored
4
cmd/templates/svelte/frontend/.gitignore
vendored
@@ -1,4 +0,0 @@
|
||||
/node_modules/
|
||||
/public/build/
|
||||
|
||||
.DS_Store
|
||||
@@ -1,90 +0,0 @@
|
||||
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
|
||||
|
||||
---
|
||||
|
||||
# svelte app
|
||||
|
||||
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
|
||||
|
||||
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
|
||||
|
||||
```bash
|
||||
npx degit sveltejs/template svelte-app
|
||||
cd svelte-app
|
||||
```
|
||||
|
||||
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
|
||||
|
||||
|
||||
## Get started
|
||||
|
||||
Install the dependencies...
|
||||
|
||||
```bash
|
||||
cd svelte-app
|
||||
npm install
|
||||
```
|
||||
|
||||
...then start [Rollup](https://rollupjs.org):
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
|
||||
|
||||
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
|
||||
|
||||
|
||||
## Building and running in production mode
|
||||
|
||||
To create an optimised version of the app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
|
||||
|
||||
|
||||
## Single-page app mode
|
||||
|
||||
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
|
||||
|
||||
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
|
||||
|
||||
```js
|
||||
"start": "sirv public --single"
|
||||
```
|
||||
|
||||
## Deploying to the web
|
||||
|
||||
### With [Vercel](https://vercel.com)
|
||||
|
||||
Install `vercel` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g vercel
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
cd public
|
||||
vercel deploy --name my-project
|
||||
```
|
||||
|
||||
### With [surge](https://surge.sh/)
|
||||
|
||||
Install `surge` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g surge
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
surge public my-project.surge.sh
|
||||
```
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"name": "{{.NPMProjectName}}",
|
||||
"author": "{{.Author.Name}}<{{.Author.Email}}>",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"dev": "rollup -c -w",
|
||||
"start": "sirv public"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.11.6",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-runtime": "^7.11.5",
|
||||
"@babel/preset-env": "^7.11.5",
|
||||
"@rollup/plugin-commonjs": "^14.0.0",
|
||||
"@rollup/plugin-image": "^2.0.5",
|
||||
"@rollup/plugin-node-resolve": "^8.0.0",
|
||||
"core-js": "^3.6.5",
|
||||
"rollup": "^2.3.4",
|
||||
"rollup-plugin-babel": "^4.4.0",
|
||||
"rollup-plugin-livereload": "^2.0.0",
|
||||
"rollup-plugin-polyfill": "^3.0.0",
|
||||
"rollup-plugin-svelte": "^6.0.0",
|
||||
"rollup-plugin-terser": "^7.0.0",
|
||||
"svelte": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"sirv-cli": "^1.0.0",
|
||||
"@wailsapp/runtime": "^1.0.10",
|
||||
"svelte-simple-modal": "^0.6.0"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||
|
||||
<title>Svelte app</title>
|
||||
|
||||
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||
<link rel='stylesheet' href='/build/bundle.css'>
|
||||
|
||||
<script defer src='/build/bundle.js'></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,110 +0,0 @@
|
||||
import svelte from 'rollup-plugin-svelte';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import livereload from 'rollup-plugin-livereload';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import image from '@rollup/plugin-image';
|
||||
import babel from 'rollup-plugin-babel';
|
||||
import polyfill from 'rollup-plugin-polyfill';
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
function serve() {
|
||||
let server;
|
||||
|
||||
function toExit() {
|
||||
if (server) server.kill(0);
|
||||
}
|
||||
|
||||
return {
|
||||
writeBundle() {
|
||||
if (server) return;
|
||||
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
|
||||
stdio: ['ignore', 'inherit', 'inherit'],
|
||||
shell: true
|
||||
});
|
||||
|
||||
process.on('SIGTERM', toExit);
|
||||
process.on('exit', toExit);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
input: 'src/main.js',
|
||||
output: {
|
||||
sourcemap: true,
|
||||
format: 'iife',
|
||||
name: 'app',
|
||||
file: 'public/build/bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
image(),
|
||||
svelte({
|
||||
// enable run-time checks when not in production
|
||||
dev: !production,
|
||||
// we'll extract any component CSS out into
|
||||
// a separate file - better for performance
|
||||
css: css => {
|
||||
css.write('bundle.css');
|
||||
}
|
||||
}),
|
||||
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration -
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||
resolve({
|
||||
browser: true,
|
||||
dedupe: ['svelte', 'svelte/transition', 'svelte/internal']
|
||||
}),
|
||||
commonjs(),
|
||||
|
||||
// In dev mode, call `npm run start` once
|
||||
// the bundle has been generated
|
||||
!production && serve(),
|
||||
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload('public'),
|
||||
|
||||
// Credit: https://blog.az.sg/posts/svelte-and-ie11/
|
||||
babel({
|
||||
extensions: [ '.js', '.jsx', '.es6', '.es', '.mjs', '.svelte', '.html' ],
|
||||
runtimeHelpers: true,
|
||||
exclude: [ 'node_modules/@babel/**', 'node_modules/core-js/**' ],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: '> 0.25%, not dead, IE 11',
|
||||
modules: false,
|
||||
spec: true,
|
||||
useBuiltIns: 'usage',
|
||||
forceAllTransforms: true,
|
||||
corejs: 3,
|
||||
},
|
||||
|
||||
]
|
||||
],
|
||||
plugins: [
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
[
|
||||
'@babel/plugin-transform-runtime',
|
||||
{
|
||||
useESModules: true
|
||||
}
|
||||
]
|
||||
]
|
||||
}),
|
||||
polyfill(['@webcomponents/webcomponentsjs']),
|
||||
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser()
|
||||
],
|
||||
watch: {
|
||||
clearScreen: false
|
||||
}
|
||||
};
|
||||
@@ -1,69 +0,0 @@
|
||||
|
||||
|
||||
<script>
|
||||
import Modal from 'svelte-simple-modal';
|
||||
import HelloWorld from './components/HelloWorld.svelte'
|
||||
import logo from './logo.png';
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<div class="App">
|
||||
<header class="App-header">
|
||||
<Modal>
|
||||
<img src={logo} class="App-logo" alt="logo" />
|
||||
<p>Welcome to your new <code>wails/svelte</code> project.</p>
|
||||
<HelloWorld/>
|
||||
</Modal>
|
||||
</header>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
:global(body) {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
}
|
||||
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,18 +0,0 @@
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
import ModalContent from './ModalContent.svelte'
|
||||
|
||||
const { open } = getContext('simple-modal');
|
||||
|
||||
const handleOpenModal = () => {
|
||||
window.backend.basic().then((result) => {
|
||||
open(ModalContent, { message: result });
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<p><button on:click={handleOpenModal}>Hello</button></p>
|
||||
</main>
|
||||
|
||||
<style></style>
|
||||
@@ -1,7 +0,0 @@
|
||||
<script>
|
||||
export let message;
|
||||
</script>
|
||||
|
||||
<p>
|
||||
{message}
|
||||
</p>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 301 KiB |
@@ -1,13 +0,0 @@
|
||||
import App from './App.svelte';
|
||||
|
||||
import * as Wails from '@wailsapp/runtime';
|
||||
|
||||
let app;
|
||||
|
||||
Wails.Init(() => {
|
||||
app = new App({
|
||||
target: document.body,
|
||||
});
|
||||
});
|
||||
|
||||
export default app;
|
||||
@@ -1,5 +0,0 @@
|
||||
module {{.BinaryName}}
|
||||
|
||||
require (
|
||||
github.com/wailsapp/wails {{.WailsVersion}}
|
||||
)
|
||||
@@ -1,27 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/leaanthony/mewn"
|
||||
"github.com/wailsapp/wails"
|
||||
)
|
||||
|
||||
func basic() string {
|
||||
return "World!"
|
||||
}
|
||||
|
||||
func main() {
|
||||
js := mewn.String("./frontend/public/build/bundle.js")
|
||||
css := mewn.String("./frontend/public/build/bundle.css")
|
||||
|
||||
app := wails.CreateApp(&wails.AppConfig{
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
Title: "{{.Name}}",
|
||||
JS: js,
|
||||
CSS: css,
|
||||
Colour: "#131313",
|
||||
})
|
||||
|
||||
app.Bind(basic)
|
||||
app.Run()
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"name": "Svelte",
|
||||
"version": "1.0.0",
|
||||
"shortdescription": "A basic Svelte template",
|
||||
"description": "A basic Svelte template",
|
||||
"install": "npm install",
|
||||
"build": "npm run build",
|
||||
"author": "Tim Kipp <timkipp.22.developer@gmail.com>",
|
||||
"created": "2020-09-06 13:06:10.469848 -0700 PDT m=+213.578828559",
|
||||
"frontenddir": "frontend",
|
||||
"serve": "npm run dev",
|
||||
"bridge": "src",
|
||||
"wailsdir": ""
|
||||
}
|
||||
@@ -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.
|
||||
@@ -1,46 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/wailsapp/wails"
|
||||
)
|
||||
|
||||
// Counter is what we use for counting
|
||||
type Counter struct {
|
||||
r *wails.Runtime
|
||||
store *wails.Store
|
||||
}
|
||||
|
||||
// WailsInit is called when the component is being initialised
|
||||
func (c *Counter) WailsInit(runtime *wails.Runtime) error {
|
||||
c.r = runtime
|
||||
c.store = runtime.Store.New("Counter", 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RandomValue sets the counter to a random value
|
||||
func (c *Counter) RandomValue() {
|
||||
c.store.Set(rand.Intn(1000))
|
||||
}
|
||||
|
||||
// Increment will increment the counter
|
||||
func (c *Counter) Increment() {
|
||||
|
||||
increment := func(data int) int {
|
||||
return data + 1
|
||||
}
|
||||
|
||||
// Update the store using the increment function
|
||||
c.store.Update(increment)
|
||||
}
|
||||
|
||||
// Decrement will decrement the counter
|
||||
func (c *Counter) Decrement() {
|
||||
|
||||
decrement := func(data int) int {
|
||||
return data - 1
|
||||
}
|
||||
// Update the store using the decrement function
|
||||
c.store.Update(decrement)
|
||||
}
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
@@ -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
@@ -1,47 +0,0 @@
|
||||
import 'core-js/stable';
|
||||
const runtime = require('@wailsapp/runtime');
|
||||
|
||||
// Main entry point
|
||||
function start() {
|
||||
|
||||
var mystore = runtime.Store.New('Counter');
|
||||
|
||||
// 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 onClick='window.backend.Counter.Increment()'>
|
||||
Increment Counter
|
||||
</button>
|
||||
<button onClick='window.backend.Counter.Decrement()'>
|
||||
Decrement Counter
|
||||
</button>
|
||||
</div>
|
||||
<div class='result'>Counter: <span id='counter'></span></div>
|
||||
<div class='container'>
|
||||
<input id='newCounter' type="number" value="0"/>
|
||||
<button id='setvalue'>Set Counter Value</button>
|
||||
<button onclick='window.backend.Counter.RandomValue()'>Set to Random Value</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Connect counter value button to Go method
|
||||
document.getElementById('setvalue').onclick = function() {
|
||||
let newValue = parseInt(document.getElementById('newCounter').value,10);
|
||||
mystore.set(newValue);
|
||||
};
|
||||
|
||||
mystore.subscribe( function(state) {
|
||||
document.getElementById('counter').innerText = state;
|
||||
});
|
||||
|
||||
mystore.set(0);
|
||||
};
|
||||
|
||||
// We provide our entrypoint as a callback for runtime.Init
|
||||
runtime.Init(start);
|
||||
@@ -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')
|
||||
},
|
||||
]
|
||||
})
|
||||
]
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
module {{.BinaryName}}
|
||||
|
||||
require (
|
||||
github.com/wailsapp/wails {{.WailsVersion}}
|
||||
)
|
||||
@@ -1,23 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/leaanthony/mewn"
|
||||
"github.com/wailsapp/wails"
|
||||
)
|
||||
|
||||
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(&Counter{})
|
||||
app.Run()
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cmd
|
||||
|
||||
// Version - Wails version
|
||||
const Version = "v1.8.0"
|
||||
const Version = "v1.0.3-pre2"
|
||||
|
||||
@@ -3,24 +3,11 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/leaanthony/spinner"
|
||||
"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() {
|
||||
|
||||
var packageApp = false
|
||||
@@ -28,8 +15,6 @@ func init() {
|
||||
var debugMode = false
|
||||
var typescriptFilename = ""
|
||||
var verbose = false
|
||||
var platform = ""
|
||||
var ldflags = ""
|
||||
|
||||
buildSpinner := spinner.NewSpinner()
|
||||
buildSpinner.SetSpinSpeed(50)
|
||||
@@ -41,16 +26,7 @@ func init() {
|
||||
BoolFlag("f", "Force rebuild of application components", &forceRebuild).
|
||||
BoolFlag("d", "Build in Debug mode", &debugMode).
|
||||
BoolFlag("verbose", "Verbose output", &verbose).
|
||||
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)
|
||||
StringFlag("t", "Generate Typescript definitions to given file (at runtime)", &typescriptFilename)
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
// 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
|
||||
// Check if we have a frontend
|
||||
err = cmd.ValidateFrontendConfig(projectOptions)
|
||||
|
||||
@@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/leaanthony/spinner"
|
||||
"github.com/wailsapp/wails/cmd"
|
||||
@@ -35,6 +34,7 @@ func init() {
|
||||
|
||||
// Project options
|
||||
projectOptions := &cmd.ProjectOptions{}
|
||||
projectOptions.Verbose = verbose
|
||||
|
||||
// Check we are in project directory
|
||||
// Check project.json loads correctly
|
||||
@@ -44,10 +44,6 @@ func init() {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set project options
|
||||
projectOptions.Verbose = verbose
|
||||
projectOptions.Platform = runtime.GOOS
|
||||
|
||||
// Save project directory
|
||||
projectDir := fs.Cwd()
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/leaanthony/spinner"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/wailsapp/wails/cmd"
|
||||
)
|
||||
|
||||
@@ -146,7 +146,7 @@ func updateToVersion(targetVersion *cmd.SemanticVersion, force bool) error {
|
||||
updateSpinner.Start("Installing Wails " + desiredVersion)
|
||||
|
||||
// Run command in non module directory
|
||||
homeDir, err := os.UserHomeDir()
|
||||
homeDir, err := homedir.Dir()
|
||||
if err != nil {
|
||||
log.Fatal("Cannot find home directory! Please file a bug report!")
|
||||
}
|
||||
|
||||
9
go.mod
9
go.mod
@@ -14,18 +14,19 @@ require (
|
||||
github.com/leaanthony/spinner v0.5.3
|
||||
github.com/mattn/go-colorable v0.1.1 // 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/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
github.com/sirupsen/logrus v1.4.1
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
|
||||
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 // indirect
|
||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862
|
||||
golang.org/x/text v0.3.0
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4
|
||||
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
|
||||
)
|
||||
|
||||
go 1.13
|
||||
go 1.12
|
||||
|
||||
16
go.sum
16
go.sum
@@ -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/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/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/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
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=
|
||||
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-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
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/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
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-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20190509222800-a4d6f7feada5 h1:6M3SDHlHHDCx2PcQw3S4KsR170vGqDhJDOmpVd4Hjak=
|
||||
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-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-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-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-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
|
||||
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc=
|
||||
|
||||
@@ -196,7 +196,7 @@ func (b *boundMethod) processWailsInit() error {
|
||||
// It must be *wails.Runtime
|
||||
inputName := b.inputs[0].String()
|
||||
b.log.Debugf("WailsInit input type: %s", inputName)
|
||||
if inputName != "*runtime.Runtime" {
|
||||
if inputName != "*wails.Runtime" {
|
||||
return fmt.Errorf("Invalid WailsInit() definition. Expected input to be wails.Runtime, but got %s", inputName)
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ func (b *boundMethod) processWailsInit() error {
|
||||
}
|
||||
|
||||
func (b *boundMethod) processWailsShutdown() error {
|
||||
// We must not have any inputs
|
||||
// We must have only 1 input, it must be *wails.Runtime
|
||||
if len(b.inputs) != 0 {
|
||||
return fmt.Errorf("Invalid WailsShutdown() definition. Expected 0 inputs, but got %d", len(b.inputs))
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ type Renderer interface {
|
||||
NotifyEvent(eventData *messages.EventData) error
|
||||
|
||||
// Dialog Runtime
|
||||
SelectFile(title string, filter string) string
|
||||
SelectFile() string
|
||||
SelectDirectory() string
|
||||
SelectSaveFile(title string, filter string) string
|
||||
SelectSaveFile() string
|
||||
|
||||
// Window Runtime
|
||||
SetColour(string) error
|
||||
|
||||
@@ -42,12 +42,12 @@ type Bridge struct {
|
||||
server *http.Server
|
||||
|
||||
lock sync.Mutex
|
||||
sessions map[string]*session
|
||||
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.sessions = map[string]session{}
|
||||
h.ipcManager = ipcManager
|
||||
h.appConfig = appConfig
|
||||
h.eventManager = eventManager
|
||||
@@ -70,11 +70,13 @@ func (h *Bridge) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (h *Bridge) startSession(conn *websocket.Conn) {
|
||||
s := newSession(conn,
|
||||
h.bindingCache,
|
||||
h.ipcManager,
|
||||
logger.NewCustomLogger("BridgeSession"),
|
||||
h.eventManager)
|
||||
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())
|
||||
@@ -114,7 +116,7 @@ func (h *Bridge) NewBinding(methodName string) error {
|
||||
|
||||
// SelectFile is unsupported for Bridge but required
|
||||
// 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")
|
||||
return ""
|
||||
}
|
||||
@@ -128,7 +130,7 @@ func (h *Bridge) SelectDirectory() string {
|
||||
|
||||
// SelectSaveFile is unsupported for Bridge but required
|
||||
// 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")
|
||||
return ""
|
||||
}
|
||||
@@ -152,20 +154,13 @@ func (h *Bridge) NotifyEvent(event *messages.EventData) error {
|
||||
// Marshall the data
|
||||
data, err = json.Marshal(event.Data)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// Double encode data to ensure everything is escaped correctly.
|
||||
data, err = json.Marshal(string(data))
|
||||
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{}
|
||||
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 {
|
||||
@@ -212,9 +207,6 @@ func (h *Bridge) SetTitle(title string) {
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) Close() {
|
||||
h.log.Debug("Shutting down")
|
||||
for _, session := range h.sessions {
|
||||
session.Shutdown()
|
||||
}
|
||||
err := h.server.Close()
|
||||
if err != nil {
|
||||
h.log.Errorf(err.Error())
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package renderer
|
||||
|
||||
// Autogenerated by Mewn - Do not alter
|
||||
|
||||
import "github.com/leaanthony/mewn"
|
||||
|
||||
func init() {
|
||||
mewn.AddAsset(".", "../../runtime/assets/wails.js", "1f8b08000000000000ff94587f6f1b37d2fe2a2be27d5532a6b752ae875e56dd06a9eba23e38761127d73f744241ed8e24262b52478eac0812bffb61f6b76cb9770704b1440ec9e13ccfcc3cd460b135196a6bb8118747e5224c0f61d20c46c09d38e805c7a99b0907b87526a2cf317cdd58877e424b6c4a43e941274e16c9602cebc9e410c2a45e646851a68a82db66adb4b2fb0c42dab84807a36e2c40bc4e8d84384b51429ca79dab12a51307882d7d14c7e3fdfc336418e7b0d0067e7376030ef7a5d901cc760d4ecd0b480623b9044c5c104142ecd2fed5d9d654ab73364871bf01bb881ef6ebb92d86c3ea6f8cf6019d36cb8f6a391cbe74e2735b797854c51612f6dee6db025810f2a5c5ec8f3fc0d766cdb2c1a872174fae5f82321ee270c84d0adc0821ff36c4062133d10bfe1dcd325b1ec5d2e64e6638a47f717752b788b07469ed5ce6402170b32d0a41db41ecb87bc97527590e0bb52d903d8d78750b13847c5d3ae4cbb874413662611d2f69146913190171ce9db4b2bd2e8a434b229c8578ae4d5efa25ad100dbf1cc5c8a4cfd9fce4b66f5b8b6ed7b8f63d2467265b06935f2899621285443ace3e81a436ac43b471162d5d325e297fbf334db0aa2ca005b4c726654c0287d8a72311f8f484e340bcf41051cc326413c20085ac3db9311a99e4cf7dfe1a84a8c13c84490d5c1556f633ccb7cbb3ab8a205aab1bb3b0678d7ccfe877e50c4179ce6ed1b3bb76cebab35679cfea1785aa386bb56bae639bebd86a9595ec7e03e6d387dbb3ebf6cdeeb5dd2f9ad2ea8ce1bc39403707e86aa196ec0e7667d75c356b543a9d75f5326b70abc34ff8274612e473957db9f93901b951fbc2aa3cc13039a9be7ac177dae47617ef942efcdce97c096f9f0fc53b987b9b7d018c3d502a88a43682af08cea822d6e6d17ea1b220555c8059e2eac7519b67988e26f8433331c18b0ba1a638e34604fef787fbbbb84a51bdd873274468efb6ad589e7156d8259387021ea1488c5c83f76a0909869e714137da7296577c33bd295f4fe99264fd99453db36b98d59fcceb49a8e8d49fdad5538b8a434604bae7463e9ef4b265834d93dadba218a4301cd61f8e470ee9484803bbe83767d7da03ef9077d256a8ea496e0f3a3517ec925d6cb808bb952e803f4ef5ac2a943f8e44450c0ff851afc16e91f719647999119c5da9a288d046ecc25cb008f51af2c86e318e3ec0bfb6e031baf93989d88516220809624247a407acb6fc5599bc80444907546e122b1d785b3c42e2c204dd9e7022da3179a082a9cdf24ead898bb942953cc1996a9116215398ad28969935de161097b12662843e115627e56ec959c5ce985d9455adb5dbd356b5d58ab39f9cdd7970719bb37d08e72fdb56796b44d8a435cf33b7dfa0ed97720ab84909b94fdae05f5ebf734eedf9b86d0f270be325e0076572bbfe073527e2e374343b57fddf8c46df8fdfbc79fdd7efbeff6ef4e6cdf8d57b85abd8956bb908650158b75d2032bce4d7e059a71e701369e351998c7a1e0a812b67771139fc71bf819610c6588c08b6484559a1bc8f948f54d46cc844e0b8d25e1a2181187b3996f43dbeaa0bcc49036cf45aac369b625fb54c23e4e5789012ed47699a72b84cc72204797d922af74daa5c4fcd2ca5ff8ec7e9acee29e4f4babce98466e2cdd6afb8eb61f9d075df273c9bce625fe80c6a8f945b6ed760d08b6a988fa962a707d3632a8649c6193c824126a1caecbb1367bfd071c4f826af6117fdd28481913dbb30420e461dbf2bcbc138744e5f5560913948975254299b07fdfa5ba356a3f53b0d45da478499361ab52ab4879c35dd6a3a6be85762e4b7739f393d8713906c153f234285a4879ed24371801465df87f89a42e1e3ebb546aa94baf089df9b2cf1681d24db4dae10f2f97ee1ac4130794259f9040610a4b617d65dab6cd5ab4d461c0c0741c95e3953ed764e5571101347ce96b5e39c83f7e6cfdc23b236de9d3a507166a39c2f1b18a4e63ff92a84c4e1b0891e2924fadc41fbb94d68feb991b7ca7bbd34c7637fbfae418ea94136e4ec37ca8a1f693b37c5d9a459e648bf82f8afe41f482748bbd3bb09e86d155abd29eae428f3bccb9050c7b80e5c7a388d7adaff723c76b39d7dc9ca9bf47007bb9faa8e903c07763a8b336b3285dcc47e5310c76226ca8f6d7e9eee4c59828dca18b72ac3a5a389fba199b81c4fdc453aae4ea9de8b65767de156885eded6a9c51a27ac644d86a9e851153a8f3eab474579b4c148e760502f34b898093181a99d51139fda597a0865859cda59a8941dc61bbbe1a23e55ffe9a9fa7f3b55cfd227ad882456ef0dddd0a62d7f25073a6c276d2b3512a885b64f8e4e429c2421a6861e0fcb33b35dd90f1202174136bde139da1393e690d91c3e7db8b9b2eb8d35600878079b4265c0bffda7bff876291913ddd07474f9465d2e6687d781a6feffff8614042abf789ab975b56d6a6aca6e4c154ab28a36ca7bc849fd34da3889daf8635c6b4ac9e2e87d2d2f23265a6a8a4955890b0e955eab10acdb834b316e76d5b9b4e96343b746c2a5ac094af44d7baa93ec9b1273074bed11f2c160c09a934e1591ee9f4ac2a900e51aad67e3138926640e052044e485c46a87b736ae741baf07444223a580e31853e71341de59d48b7df24c4e50dbedca15940dbaeea0425689570ed585ab9f79344e7e68ea4e94b982a0d37de8b0075dce4f6123c7220f06093953ba174765c18fa8694769d96b836d0509d7623884a67e383916a1d41410827c97e70f654a3db96175a9dc66657ad4bf445c1740df38abb2908909c4085f3135b2b59cdb7c4fd5134c7eb5d2454eecc0e1f0a1ec513786e27df5f070a6eabd7816ee0b200e5022be43747abe45e08cea3a938cceff36f39e09897169fbb002c0b7fd2f71e6fdc7d2cf044f7c7b7226d9dcd9bcfa2da79b5c81ca8fc7f6eb12b076ceffb4ffa84a4dcf191931d2b0e2e484ead61a93af14ea9bdfae6e89d606dc4904542b4082bc4d0fb776993859ebefc4caaa9b27877bf304a5fbfa378c7bf37e5ba0de1490dc4b5225c983fc1594c339a85364bb773149d1c91df1a057b7ca24ba3108ee5115e54f1654bd1c3da3dad1fe3b8a646610a50fefb22fc6ee0ac897903c79520fe8989edcce5b99adba45d1d6d06713ad1ac77b75c148f60dd538da8853941e4a29a3e51fc94d4f867ead2489089f4f9ef1f25634add89a32d54f7fc70459be2c4f14d4ad5dc6754f7af5ead5abe84a6d972b8c3e99555951f2aaf04434c7847c6969573849febe64f5e9c32d59e0cb16b7da407467c90a5eb6bab2c5766d6a3bf7b25d1902b2b122c88746221656e5a49cc34c4cfe1d0000ffff6a61b37f93160000")
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
package renderer
|
||||
|
||||
import (
|
||||
"time"
|
||||
"unsafe"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/leaanthony/mewn"
|
||||
@@ -21,22 +20,7 @@ type session struct {
|
||||
ipc interfaces.IPCManager
|
||||
|
||||
// Mutex for writing to the socket
|
||||
shutdown chan bool
|
||||
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),
|
||||
}
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if !s.done {
|
||||
s.writeChan <- *(*[]byte)(unsafe.Pointer(&msg))
|
||||
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.")
|
||||
go s.writePump()
|
||||
|
||||
wailsRuntime := mewn.String("../../runtime/assets/wails.js")
|
||||
s.evalJS(wailsRuntime, wailsRuntimeMessage)
|
||||
@@ -86,10 +74,6 @@ func (s *session) start(firstSession bool) {
|
||||
s.log.Debugf("Got message: %#v\n", string(buffer))
|
||||
|
||||
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 {
|
||||
|
||||
// Prepend message type to message
|
||||
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
@@ -245,7 +245,7 @@ func (w *WebView) NewBinding(methodName string) error {
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
// 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)
|
||||
go 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()
|
||||
})
|
||||
}()
|
||||
@@ -273,7 +273,7 @@ func (w *WebView) SelectDirectory() string {
|
||||
wg.Add(1)
|
||||
go 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()
|
||||
})
|
||||
}()
|
||||
@@ -282,7 +282,7 @@ func (w *WebView) SelectDirectory() string {
|
||||
}
|
||||
|
||||
// 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
|
||||
// We need to run this on the main thread, however Dispatch is
|
||||
// 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)
|
||||
go 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()
|
||||
})
|
||||
}()
|
||||
@@ -329,14 +329,7 @@ func (w *WebView) NotifyEvent(event *messages.EventData) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Double encode data to ensure everything is escaped correctly.
|
||||
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) + ")"
|
||||
message := fmt.Sprintf("wails._.Notify('%s','%s')", event.Name, data)
|
||||
return w.evalJS(message)
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
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,
|
||||
(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) {
|
||||
@@ -186,7 +186,7 @@ type WebView interface {
|
||||
// Dialog() opens a system dialog of the given type and title. String
|
||||
// argument can be provided for certain dialogs, such as alert boxes. For
|
||||
// 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
|
||||
// only. See Dispatch() for more details.
|
||||
Terminate()
|
||||
@@ -311,7 +311,7 @@ func (w *webview) SetFullscreen(fullscreen bool) {
|
||||
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
|
||||
titlePtr := C.CString(title)
|
||||
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))
|
||||
resultPtr := (*C.char)(C.calloc((C.size_t)(unsafe.Sizeof((*C.char)(nil))), (C.size_t)(maxPath)))
|
||||
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,
|
||||
argPtr, resultPtr, C.size_t(maxPath), filterPtr)
|
||||
argPtr, resultPtr, C.size_t(maxPath))
|
||||
return C.GoString(resultPtr)
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ struct webview_priv
|
||||
#define DEFAULT_URL \
|
||||
"data:text/" \
|
||||
"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%" \
|
||||
"3E%3C%2Fdiv%3E%3Cscript%20type=%22text%2Fjavascript%22%3E%3C%2Fscript%3E%" \
|
||||
"3C%2Fbody%3E%0A%3C%2Fhtml%3E"
|
||||
@@ -174,7 +174,7 @@ struct webview_priv
|
||||
WEBVIEW_API void webview_dialog(struct webview *w,
|
||||
enum webview_dialog_type dlgtype, int flags,
|
||||
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,
|
||||
void *arg);
|
||||
WEBVIEW_API void webview_terminate(struct webview *w);
|
||||
@@ -418,7 +418,7 @@ struct webview_priv
|
||||
WEBVIEW_API void webview_dialog(struct webview *w,
|
||||
enum webview_dialog_type dlgtype, int flags,
|
||||
const char *title, const char *arg,
|
||||
char *result, size_t resultsz, char *filter)
|
||||
char *result, size_t resultsz)
|
||||
{
|
||||
GtkWidget *dlg;
|
||||
if (result != NULL)
|
||||
@@ -438,17 +438,6 @@ struct webview_priv
|
||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||
(dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ? "_Open" : "_Save"),
|
||||
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_select_multiple(GTK_FILE_CHOOSER(dlg), FALSE);
|
||||
gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dlg), TRUE);
|
||||
@@ -1238,7 +1227,7 @@ struct webview_priv
|
||||
}
|
||||
VariantInit(&myURL);
|
||||
myURL.vt = VT_BSTR;
|
||||
// #ifndef UNICODE
|
||||
// #ifndef UNICODE
|
||||
{
|
||||
wchar_t *buffer = webview_to_utf16(webPageName);
|
||||
if (buffer == NULL)
|
||||
@@ -1248,9 +1237,9 @@ struct webview_priv
|
||||
myURL.bstrVal = SysAllocString(buffer);
|
||||
GlobalFree(buffer);
|
||||
}
|
||||
// #else
|
||||
// myURL.bstrVal = SysAllocString(webPageName);
|
||||
// #endif
|
||||
// #else
|
||||
// myURL.bstrVal = SysAllocString(webPageName);
|
||||
// #endif
|
||||
if (!myURL.bstrVal)
|
||||
{
|
||||
badalloc:
|
||||
@@ -1288,7 +1277,7 @@ struct webview_priv
|
||||
if (!SafeArrayAccessData(sfArray, (void **)&pVar))
|
||||
{
|
||||
pVar->vt = VT_BSTR;
|
||||
// #ifndef UNICODE
|
||||
// #ifndef UNICODE
|
||||
{
|
||||
wchar_t *buffer = webview_to_utf16(url);
|
||||
if (buffer == NULL)
|
||||
@@ -1298,9 +1287,9 @@ struct webview_priv
|
||||
bstr = SysAllocString(buffer);
|
||||
GlobalFree(buffer);
|
||||
}
|
||||
// #else
|
||||
// bstr = SysAllocString(url);
|
||||
// #endif
|
||||
// #else
|
||||
// bstr = SysAllocString(url);
|
||||
// #endif
|
||||
if ((pVar->bstrVal = bstr))
|
||||
{
|
||||
htmlDoc2->lpVtbl->write(htmlDoc2, sfArray);
|
||||
@@ -1421,8 +1410,6 @@ struct webview_priv
|
||||
wc.hInstance = hInstance;
|
||||
wc.lpfnWndProc = wndproc;
|
||||
wc.lpszClassName = classname;
|
||||
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(100));
|
||||
wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(100));
|
||||
RegisterClassEx(&wc);
|
||||
|
||||
style = WS_OVERLAPPEDWINDOW;
|
||||
@@ -1431,13 +1418,6 @@ struct webview_priv
|
||||
style = WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
|
||||
}
|
||||
|
||||
// Scale
|
||||
// Credit: https://github.com/webview/webview/issues/54#issuecomment-379528243
|
||||
HDC hDC = GetDC(NULL);
|
||||
w->width = GetDeviceCaps(hDC, 88)*w->width/96.0;
|
||||
w->height = GetDeviceCaps(hDC, 90)*w->height/96.0;
|
||||
ReleaseDC(NULL, hDC);
|
||||
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = w->width;
|
||||
@@ -1464,12 +1444,12 @@ struct webview_priv
|
||||
rect.right - rect.left, rect.bottom - rect.top,
|
||||
HWND_DESKTOP, NULL, hInstance, (void *)w);
|
||||
#else
|
||||
w->priv.hwnd =
|
||||
w->priv.hwnd =
|
||||
CreateWindowEx(0, classname, w->title, style, rect.left, rect.top,
|
||||
rect.right - rect.left, rect.bottom - rect.top,
|
||||
HWND_DESKTOP, NULL, hInstance, (void *)w);
|
||||
#endif
|
||||
|
||||
|
||||
if (w->priv.hwnd == 0)
|
||||
{
|
||||
OleUninitialize();
|
||||
@@ -1486,7 +1466,8 @@ struct webview_priv
|
||||
#else
|
||||
SetWindowText(w->priv.hwnd, w->title);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
ShowWindow(w->priv.hwnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(w->priv.hwnd);
|
||||
SetFocus(w->priv.hwnd);
|
||||
@@ -1513,11 +1494,6 @@ struct webview_priv
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
{
|
||||
// Disable refresh when pressing F5 on windows
|
||||
if (msg.wParam == VK_F5)
|
||||
{
|
||||
break;
|
||||
}
|
||||
HRESULT r = S_OK;
|
||||
IWebBrowser2 *webBrowser2;
|
||||
IOleObject *browser = *w->priv.browser;
|
||||
@@ -1627,7 +1603,7 @@ struct webview_priv
|
||||
|
||||
WEBVIEW_API void webview_set_title(struct webview *w, const char *title)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
#ifdef UNICODE
|
||||
wchar_t *u16title = webview_to_utf16(title);
|
||||
if (u16title == NULL)
|
||||
{
|
||||
@@ -1635,11 +1611,12 @@ struct webview_priv
|
||||
}
|
||||
SetWindowText(w->priv.hwnd, u16title);
|
||||
GlobalFree(u16title);
|
||||
#else
|
||||
#else
|
||||
SetWindowText(w->priv.hwnd, title);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
WEBVIEW_API void webview_set_fullscreen(struct webview *w, int fullscreen)
|
||||
{
|
||||
if (w->priv.is_fullscreen == !!fullscreen)
|
||||
@@ -1800,7 +1777,7 @@ struct webview_priv
|
||||
WEBVIEW_API void webview_dialog(struct webview *w,
|
||||
enum webview_dialog_type dlgtype, int flags,
|
||||
const char *title, const char *arg,
|
||||
char *result, size_t resultsz, char *filter)
|
||||
char *result, size_t resultsz)
|
||||
{
|
||||
if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ||
|
||||
dlgtype == WEBVIEW_DIALOG_TYPE_SAVE)
|
||||
@@ -1840,32 +1817,6 @@ struct webview_priv
|
||||
FOS_NOTESTFILECREATE | FOS_NODEREFERENCELINKS |
|
||||
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)
|
||||
{
|
||||
goto error_dlg;
|
||||
@@ -1976,26 +1927,22 @@ struct webview_priv
|
||||
[script setValue:self forKey:@"external"];
|
||||
}
|
||||
|
||||
static void webview_run_input_open_panel(id self, SEL cmd, id webview,
|
||||
id listener, BOOL allowMultiple)
|
||||
{
|
||||
static void webview_run_input_open_panel(id self, SEL cmd, id webview,
|
||||
id listener, BOOL allowMultiple) {
|
||||
char filename[256] = "";
|
||||
struct webview *w =
|
||||
(struct webview *)objc_getAssociatedObject(self, "webview");
|
||||
|
||||
webview_dialog(w, WEBVIEW_DIALOG_TYPE_OPEN, WEBVIEW_DIALOG_FLAG_FILE, "", "",
|
||||
filename, 255, "");
|
||||
filename[255] = '\0';
|
||||
if (strlen(filename) > 0)
|
||||
{
|
||||
filename, 255);
|
||||
if (strlen(filename)) {
|
||||
[listener chooseFilename:[NSString stringWithUTF8String:filename]];
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
[listener cancel];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void webview_external_invoke(id self, SEL cmd, id arg)
|
||||
{
|
||||
struct webview *w =
|
||||
@@ -2008,7 +1955,7 @@ struct webview_priv
|
||||
{
|
||||
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)
|
||||
@@ -2247,16 +2194,12 @@ struct webview_priv
|
||||
WEBVIEW_API void webview_dialog(struct webview *w,
|
||||
enum webview_dialog_type dlgtype, int flags,
|
||||
const char *title, const char *arg,
|
||||
char *result, size_t resultsz, char *filter)
|
||||
char *result, size_t resultsz)
|
||||
{
|
||||
if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ||
|
||||
dlgtype == WEBVIEW_DIALOG_TYPE_SAVE)
|
||||
{
|
||||
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)
|
||||
{
|
||||
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
|
||||
@@ -2269,10 +2212,6 @@ struct webview_priv
|
||||
{
|
||||
[openPanel setCanChooseFiles:YES];
|
||||
[openPanel setCanChooseDirectories:NO];
|
||||
if(filter[0] != NULL)
|
||||
{
|
||||
[openPanel setAllowedFileTypes:fileTypes];
|
||||
}
|
||||
}
|
||||
[openPanel setResolvesAliases:NO];
|
||||
[openPanel setAllowsMultipleSelection:NO];
|
||||
@@ -2286,10 +2225,6 @@ struct webview_priv
|
||||
[panel setShowsHiddenFiles:YES];
|
||||
[panel setExtensionHidden:NO];
|
||||
[panel setCanSelectHiddenExtension:NO];
|
||||
if(filter[0] != NULL)
|
||||
{
|
||||
[panel setAllowedFileTypes:fileTypes];
|
||||
}
|
||||
[panel setTreatsFilePackagesAsDirectories:YES];
|
||||
[panel beginSheetModalForWindow:w->priv.window
|
||||
completionHandler:^(NSInteger result) {
|
||||
|
||||
32
runtime.go
Normal file
32
runtime.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package wails
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/lib/interfaces"
|
||||
"github.com/wailsapp/wails/lib/logger"
|
||||
"github.com/wailsapp/wails/runtime"
|
||||
)
|
||||
|
||||
// CustomLogger type alias
|
||||
type CustomLogger = logger.CustomLogger
|
||||
|
||||
// Runtime is the Wails Runtime Interface, given to a user who has defined the WailsInit method
|
||||
type Runtime struct {
|
||||
Events *runtime.Events
|
||||
Log *runtime.Log
|
||||
Dialog *runtime.Dialog
|
||||
Window *runtime.Window
|
||||
Browser *runtime.Browser
|
||||
FileSystem *runtime.FileSystem
|
||||
}
|
||||
|
||||
// NewRuntime creates a new Runtime struct
|
||||
func NewRuntime(eventManager interfaces.EventManager, renderer interfaces.Renderer) *Runtime {
|
||||
return &Runtime{
|
||||
Events: runtime.NewEvents(eventManager),
|
||||
Log: runtime.NewLog(),
|
||||
Dialog: runtime.NewDialog(renderer),
|
||||
Window: runtime.NewWindow(renderer),
|
||||
Browser: runtime.NewBrowser(),
|
||||
FileSystem: runtime.NewFileSystem(),
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,7 +1,6 @@
|
||||
package runtime
|
||||
|
||||
import "github.com/wailsapp/wails/lib/interfaces"
|
||||
import "strings"
|
||||
|
||||
// Dialog exposes an interface to native dialogs
|
||||
type Dialog struct {
|
||||
@@ -16,16 +15,8 @@ func NewDialog(renderer interfaces.Renderer) *Dialog {
|
||||
}
|
||||
|
||||
// SelectFile prompts the user to select a file
|
||||
func (r *Dialog) SelectFile(params ...string) string {
|
||||
title := "Select File"
|
||||
filter := ""
|
||||
if len(params) > 0 {
|
||||
title = params[0]
|
||||
}
|
||||
if len(params) > 1 {
|
||||
filter = strings.Replace(params[1], " ", "", -1)
|
||||
}
|
||||
return r.renderer.SelectFile(title, filter)
|
||||
func (r *Dialog) SelectFile() string {
|
||||
return r.renderer.SelectFile()
|
||||
}
|
||||
|
||||
// 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
|
||||
func (r *Dialog) SelectSaveFile(params ...string) string {
|
||||
title := "Select Save"
|
||||
filter := ""
|
||||
if len(params) > 0 {
|
||||
title = params[0]
|
||||
}
|
||||
if len(params) > 1 {
|
||||
filter = strings.Replace(params[1], " ", "", -1)
|
||||
}
|
||||
return r.renderer.SelectSaveFile(title, filter)
|
||||
func (r *Dialog) SelectSaveFile() string {
|
||||
return r.renderer.SelectSaveFile()
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package runtime
|
||||
|
||||
import "os"
|
||||
import homedir "github.com/mitchellh/go-homedir"
|
||||
|
||||
// FileSystem exposes file system utilities to the runtime
|
||||
type FileSystem struct{}
|
||||
type FileSystem struct {}
|
||||
|
||||
// NewFileSystem creates a new FileSystem struct
|
||||
func NewFileSystem() *FileSystem {
|
||||
@@ -12,5 +12,5 @@ func NewFileSystem() *FileSystem {
|
||||
|
||||
// HomeDir returns the user's home directory
|
||||
func (r *FileSystem) HomeDir() (string, error) {
|
||||
return os.UserHomeDir()
|
||||
return homedir.Dir()
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import { NewBinding } from './bindings';
|
||||
import { Callback } from './calls';
|
||||
import { AddScript, InjectCSS } from './utils';
|
||||
import { AddIPCListener } from './ipc';
|
||||
import * as Store from './store';
|
||||
|
||||
// Initialise global if not already
|
||||
window.wails = window.wails || {};
|
||||
@@ -43,7 +42,6 @@ var runtime = {
|
||||
Heartbeat,
|
||||
Acknowledge,
|
||||
},
|
||||
Store,
|
||||
_: internal,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
/**
|
||||
* Creates a new sync store with the given name and optional default value
|
||||
*
|
||||
* @export
|
||||
* @param {string} name
|
||||
* @param {*} optionalDefault
|
||||
*/
|
||||
export function New(name, optionalDefault) {
|
||||
|
||||
var data;
|
||||
|
||||
// Check we are initialised
|
||||
if( !window.wails) {
|
||||
throw Error('Wails is not initialised');
|
||||
}
|
||||
|
||||
// Store for the callbacks
|
||||
let callbacks = [];
|
||||
|
||||
// Subscribe to updates by providing a callback
|
||||
this.subscribe = (callback) => {
|
||||
callbacks.push(callback);
|
||||
};
|
||||
|
||||
// sets the store data to the provided `newdata` value
|
||||
this.set = (newdata) => {
|
||||
|
||||
data = newdata;
|
||||
|
||||
// Emit a notification to back end
|
||||
window.wails.Events.Emit('wails:sync:store:updatedbyfrontend:'+name, JSON.stringify(data));
|
||||
|
||||
// Notify callbacks
|
||||
callbacks.forEach( function(callback) {
|
||||
callback(data);
|
||||
});
|
||||
};
|
||||
|
||||
// update mutates the value in the store by calling the
|
||||
// provided method with the current value. The value returned
|
||||
// by the updater function will be set as the new store value
|
||||
this.update = (updater) => {
|
||||
var newValue = updater(data);
|
||||
this.set(newValue);
|
||||
};
|
||||
|
||||
// Setup event callback
|
||||
window.wails.Events.On('wails:sync:store:updatedbybackend:'+name, function(result) {
|
||||
|
||||
// Parse data
|
||||
result = JSON.parse(result);
|
||||
|
||||
// Todo: Potential preprocessing?
|
||||
|
||||
// Save data
|
||||
data = result;
|
||||
|
||||
// Notify callbacks
|
||||
callbacks.forEach( function(callback) {
|
||||
callback(data);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Set to the optional default if set
|
||||
if( optionalDefault ) {
|
||||
this.set(optionalDefault);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
5904
runtime/js/package-lock.json
generated
5904
runtime/js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -29,15 +29,15 @@
|
||||
},
|
||||
"homepage": "https://github.com/wailsapp/runtime#readme",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.11.5",
|
||||
"@babel/core": "^7.11.5",
|
||||
"@babel/plugin-transform-object-assign": "^7.10.4",
|
||||
"@babel/preset-env": "^7.11.5",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-preset-minify": "^0.5.1",
|
||||
"core-js": "^3.6.5",
|
||||
"eslint": "^7.8.1",
|
||||
"webpack": "^4.44.1",
|
||||
"webpack-cli": "^3.3.12"
|
||||
"@babel/cli": "^7.5.0",
|
||||
"@babel/core": "^7.5.4",
|
||||
"@babel/plugin-transform-object-assign": "^7.2.0",
|
||||
"@babel/preset-env": "^7.5.4",
|
||||
"babel-loader": "^8.0.6",
|
||||
"babel-preset-minify": "^0.5.0",
|
||||
"core-js": "^3.1.4",
|
||||
"eslint": "^6.5.1",
|
||||
"webpack": "^4.35.3",
|
||||
"webpack-cli": "^3.3.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,10 @@ const Log = require('./log');
|
||||
const Browser = require('./browser');
|
||||
const Events = require('./events');
|
||||
const Init = require('./init');
|
||||
const Store = require('./store');
|
||||
|
||||
module.exports = {
|
||||
Log: Log,
|
||||
Browser: Browser,
|
||||
Events: Events,
|
||||
Init: Init,
|
||||
Store: Store,
|
||||
Init: Init
|
||||
};
|
||||
492
runtime/js/runtime/package-lock.json
generated
492
runtime/js/runtime/package-lock.json
generated
@@ -1,492 +0,0 @@
|
||||
{
|
||||
"name": "@wailsapp/runtime",
|
||||
"version": "1.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
|
||||
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
|
||||
"dev": true
|
||||
},
|
||||
"cliui": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
|
||||
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"wrap-ansi": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||
"dev": true
|
||||
},
|
||||
"decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
|
||||
"dev": true
|
||||
},
|
||||
"dts-dom": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/dts-dom/-/dts-dom-3.6.0.tgz",
|
||||
"integrity": "sha512-on5jxTgt+A6r0Zyyz6ZRHXaAO7J1VPnOd6+AmvI1vH440AlAZZNc5rUHzgPuTjGlrVr1rOWQYNl7ZJK6rDohbw==",
|
||||
"dev": true
|
||||
},
|
||||
"dts-gen": {
|
||||
"version": "0.5.8",
|
||||
"resolved": "https://registry.npmjs.org/dts-gen/-/dts-gen-0.5.8.tgz",
|
||||
"integrity": "sha512-kIAV6dlHaF7r5J+tIuOC1BJls2P72YM0cyWQUR88zcJEpX2ccRZe+HmXLfkkvfPwjvSO3FEqUiyC8On/grx5qw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dts-dom": "^3.6.0",
|
||||
"parse-git-config": "^1.1.1",
|
||||
"typescript": "^3.5.1",
|
||||
"yargs": "^4.8.1"
|
||||
}
|
||||
},
|
||||
"error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"find-up": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
|
||||
"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-exists": "^2.0.0",
|
||||
"pinkie-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs-exists-sync": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz",
|
||||
"integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=",
|
||||
"dev": true
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
||||
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
|
||||
"dev": true
|
||||
},
|
||||
"git-config-path": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz",
|
||||
"integrity": "sha1-bTP37WPbDQ4RgTFQO6s6ykfVRmQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"fs-exists-sync": "^0.1.0",
|
||||
"homedir-polyfill": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
|
||||
"dev": true
|
||||
},
|
||||
"homedir-polyfill": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
|
||||
"integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"parse-passwd": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.8",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
|
||||
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
|
||||
"dev": true
|
||||
},
|
||||
"invert-kv": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
|
||||
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
|
||||
"dev": true
|
||||
},
|
||||
"is-arrayish": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
|
||||
"dev": true
|
||||
},
|
||||
"is-extendable": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
|
||||
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
|
||||
"dev": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-utf8": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
|
||||
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
|
||||
"dev": true
|
||||
},
|
||||
"lcid": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
|
||||
"integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"invert-kv": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
||||
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"parse-json": "^2.2.0",
|
||||
"pify": "^2.0.0",
|
||||
"pinkie-promise": "^2.0.0",
|
||||
"strip-bom": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"lodash.assign": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
|
||||
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-package-data": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
|
||||
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hosted-git-info": "^2.1.4",
|
||||
"resolve": "^1.10.0",
|
||||
"semver": "2 || 3 || 4 || 5",
|
||||
"validate-npm-package-license": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||
"dev": true
|
||||
},
|
||||
"os-locale": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
|
||||
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lcid": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"parse-git-config": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-1.1.1.tgz",
|
||||
"integrity": "sha1-06mYQxcTL1c5hxK7pDjhKVkN34w=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"extend-shallow": "^2.0.1",
|
||||
"fs-exists-sync": "^0.1.0",
|
||||
"git-config-path": "^1.0.1",
|
||||
"ini": "^1.3.4"
|
||||
}
|
||||
},
|
||||
"parse-json": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
|
||||
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"error-ex": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"parse-passwd": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
|
||||
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
|
||||
"dev": true
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
|
||||
"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pinkie-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
},
|
||||
"path-type": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
|
||||
"integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"pify": "^2.0.0",
|
||||
"pinkie-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||
"dev": true
|
||||
},
|
||||
"pinkie": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
|
||||
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
|
||||
"dev": true
|
||||
},
|
||||
"pinkie-promise": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
|
||||
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pinkie": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
|
||||
"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"load-json-file": "^1.0.0",
|
||||
"normalize-package-data": "^2.3.2",
|
||||
"path-type": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"read-pkg-up": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
|
||||
"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"find-up": "^1.0.0",
|
||||
"read-pkg": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
|
||||
"dev": true
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
|
||||
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
|
||||
"integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
|
||||
"dev": true
|
||||
},
|
||||
"spdx-correct": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
|
||||
"integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"spdx-expression-parse": "^3.0.0",
|
||||
"spdx-license-ids": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"spdx-exceptions": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
|
||||
"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
|
||||
"dev": true
|
||||
},
|
||||
"spdx-expression-parse": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
|
||||
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"spdx-exceptions": "^2.1.0",
|
||||
"spdx-license-ids": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"spdx-license-ids": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
|
||||
"integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"strip-bom": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
|
||||
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-utf8": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.9.7",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
|
||||
"integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
|
||||
"dev": true
|
||||
},
|
||||
"validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"spdx-correct": "^3.0.0",
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"which-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
|
||||
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
|
||||
"dev": true
|
||||
},
|
||||
"window-size": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz",
|
||||
"integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=",
|
||||
"dev": true
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
||||
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"y18n": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
|
||||
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz",
|
||||
"integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cliui": "^3.2.0",
|
||||
"decamelize": "^1.1.1",
|
||||
"get-caller-file": "^1.0.1",
|
||||
"lodash.assign": "^4.0.3",
|
||||
"os-locale": "^1.4.0",
|
||||
"read-pkg-up": "^1.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^1.0.1",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^1.0.1",
|
||||
"which-module": "^1.0.0",
|
||||
"window-size": "^0.2.0",
|
||||
"y18n": "^3.2.1",
|
||||
"yargs-parser": "^2.4.1"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz",
|
||||
"integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^3.0.0",
|
||||
"lodash.assign": "^4.0.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wailsapp/runtime",
|
||||
"version": "1.1.1",
|
||||
"version": "1.0.11",
|
||||
"description": "Wails Javascript runtime library",
|
||||
"main": "main.js",
|
||||
"types": "runtime.d.ts",
|
||||
@@ -25,4 +25,4 @@
|
||||
"devDependencies": {
|
||||
"dts-gen": "^0.5.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
3
runtime/js/runtime/runtime.d.ts
vendored
3
runtime/js/runtime/runtime.d.ts
vendored
@@ -21,9 +21,6 @@ declare const wailsapp__runtime: {
|
||||
Info(message: string): void;
|
||||
Warning(message: string): void;
|
||||
};
|
||||
Store: {
|
||||
New(name: string, optionalDefault?: any): any;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
_ __ _ __
|
||||
| | / /___ _(_) /____
|
||||
| | /| / / __ `/ / / ___/
|
||||
| |/ |/ / /_/ / / (__ )
|
||||
|__/|__/\__,_/_/_/____/
|
||||
The lightweight framework for web-like apps
|
||||
(c) Lea Anthony 2019-present
|
||||
*/
|
||||
|
||||
/* jshint esversion: 6 */
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Store with the given name and optional default value
|
||||
*
|
||||
* @export
|
||||
* @param {string} name
|
||||
* @param {*} optionalDefault
|
||||
*/
|
||||
function New(name, optionalDefault) {
|
||||
return window.wails.Store.New(name, optionalDefault);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
New: New,
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
package runtime
|
||||
|
||||
import "github.com/wailsapp/wails/lib/interfaces"
|
||||
|
||||
// Runtime is the Wails Runtime Interface, given to a user who has defined the WailsInit method
|
||||
type Runtime struct {
|
||||
Events *Events
|
||||
Log *Log
|
||||
Dialog *Dialog
|
||||
Window *Window
|
||||
Browser *Browser
|
||||
FileSystem *FileSystem
|
||||
Store *StoreProvider
|
||||
}
|
||||
|
||||
// NewRuntime creates a new Runtime struct
|
||||
func NewRuntime(eventManager interfaces.EventManager, renderer interfaces.Renderer) *Runtime {
|
||||
result := &Runtime{
|
||||
Events: NewEvents(eventManager),
|
||||
Log: NewLog(),
|
||||
Dialog: NewDialog(renderer),
|
||||
Window: NewWindow(renderer),
|
||||
Browser: NewBrowser(),
|
||||
FileSystem: NewFileSystem(),
|
||||
}
|
||||
// We need a reference to itself
|
||||
result.Store = NewStoreProvider(result)
|
||||
return result
|
||||
}
|
||||
293
runtime/store.go
293
runtime/store.go
@@ -1,293 +0,0 @@
|
||||
// Package runtime contains all the methods and data structures related to the
|
||||
// runtime library of Wails. This includes both Go and JS runtimes.
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Options defines the optional data that may be used
|
||||
// when creating a Store
|
||||
type Options struct {
|
||||
|
||||
// The name of the store
|
||||
Name string
|
||||
|
||||
// The runtime to attach the store to
|
||||
Runtime *Runtime
|
||||
|
||||
// Indicates if notifying Go listeners should be notified of updates
|
||||
// synchronously (on the current thread) or asynchronously using
|
||||
// goroutines
|
||||
NotifySynchronously bool
|
||||
}
|
||||
|
||||
// StoreProvider is a struct that creates Stores
|
||||
type StoreProvider struct {
|
||||
runtime *Runtime
|
||||
}
|
||||
|
||||
// NewStoreProvider creates new stores using the provided Runtime reference.
|
||||
func NewStoreProvider(runtime *Runtime) *StoreProvider {
|
||||
return &StoreProvider{
|
||||
runtime: runtime,
|
||||
}
|
||||
}
|
||||
|
||||
// Store is where we keep named data
|
||||
type Store struct {
|
||||
name string
|
||||
data reflect.Value
|
||||
dataType reflect.Type
|
||||
eventPrefix string
|
||||
callbacks []reflect.Value
|
||||
runtime *Runtime
|
||||
notifySynchronously bool
|
||||
|
||||
// Lock
|
||||
mux sync.Mutex
|
||||
|
||||
// Error handler
|
||||
errorHandler func(error)
|
||||
}
|
||||
|
||||
// New creates a new store
|
||||
func (p *StoreProvider) New(name string, defaultValue interface{}) *Store {
|
||||
|
||||
dataType := reflect.TypeOf(defaultValue)
|
||||
|
||||
result := Store{
|
||||
name: name,
|
||||
runtime: p.runtime,
|
||||
data: reflect.ValueOf(defaultValue),
|
||||
dataType: dataType,
|
||||
}
|
||||
|
||||
// Setup the sync listener
|
||||
result.setupListener()
|
||||
|
||||
return &result
|
||||
}
|
||||
|
||||
// OnError takes a function that will be called
|
||||
// whenever an error occurs
|
||||
func (s *Store) OnError(callback func(error)) {
|
||||
s.errorHandler = callback
|
||||
}
|
||||
|
||||
// Processes the updates sent by the front end
|
||||
func (s *Store) processUpdatedData(data string) error {
|
||||
|
||||
// Decode incoming data
|
||||
var rawdata json.RawMessage
|
||||
d := json.NewDecoder(bytes.NewBufferString(data))
|
||||
err := d.Decode(&rawdata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create a new instance of our data and unmarshal
|
||||
// the received value into it
|
||||
newData := reflect.New(s.dataType).Interface()
|
||||
err = json.Unmarshal(rawdata, &newData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Lock mutex for writing
|
||||
s.mux.Lock()
|
||||
|
||||
// Handle nulls
|
||||
if newData == nil {
|
||||
s.data = reflect.Zero(s.dataType)
|
||||
} else {
|
||||
// Store the resultant value in the data store
|
||||
s.data = reflect.ValueOf(newData).Elem()
|
||||
}
|
||||
|
||||
// Unlock mutex
|
||||
s.mux.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Setup listener for front end changes
|
||||
func (s *Store) setupListener() {
|
||||
|
||||
// Listen for updates from the front end
|
||||
s.runtime.Events.On("wails:sync:store:updatedbyfrontend:"+s.name, func(data ...interface{}) {
|
||||
|
||||
// Process the incoming data
|
||||
err := s.processUpdatedData(data[0].(string))
|
||||
|
||||
if err != nil {
|
||||
if s.errorHandler != nil {
|
||||
s.errorHandler(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Notify listeners
|
||||
s.notify()
|
||||
})
|
||||
}
|
||||
|
||||
// notify the listeners of the current data state
|
||||
func (s *Store) notify() {
|
||||
|
||||
// Execute callbacks
|
||||
for _, callback := range s.callbacks {
|
||||
|
||||
// Build args
|
||||
args := []reflect.Value{s.data}
|
||||
|
||||
if s.notifySynchronously {
|
||||
callback.Call(args)
|
||||
} else {
|
||||
go callback.Call(args)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Set will update the data held by the store
|
||||
// and notify listeners of the change
|
||||
func (s *Store) Set(data interface{}) error {
|
||||
|
||||
inType := reflect.TypeOf(data)
|
||||
|
||||
if inType != s.dataType {
|
||||
return fmt.Errorf("invalid data given in Store.Set(). Expected %s, got %s", s.dataType.String(), inType.String())
|
||||
}
|
||||
|
||||
// Save data
|
||||
s.mux.Lock()
|
||||
s.data = reflect.ValueOf(data)
|
||||
s.mux.Unlock()
|
||||
|
||||
// Stringify data
|
||||
newdata, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
if s.errorHandler != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Emit event to front end
|
||||
s.runtime.Events.Emit("wails:sync:store:updatedbybackend:"+s.name, string(newdata))
|
||||
|
||||
// Notify subscribers
|
||||
s.notify()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// callbackCheck ensures the given function to Subscribe() is
|
||||
// of the correct signature. Absolutely cannot wait for
|
||||
// generics to land rather than writing this nonsense.
|
||||
func (s *Store) callbackCheck(callback interface{}) error {
|
||||
|
||||
// Get type
|
||||
callbackType := reflect.TypeOf(callback)
|
||||
|
||||
// Check callback is a function
|
||||
if callbackType.Kind() != reflect.Func {
|
||||
return fmt.Errorf("invalid value given to store.Subscribe(). Expected 'func(%s)'", s.dataType.String())
|
||||
}
|
||||
|
||||
// Check input param
|
||||
if callbackType.NumIn() != 1 {
|
||||
return fmt.Errorf("invalid number of parameters given in callback function. Expected 1")
|
||||
}
|
||||
|
||||
// Check input data type
|
||||
if callbackType.In(0) != s.dataType {
|
||||
return fmt.Errorf("invalid type for input parameter given in callback function. Expected %s, got %s", s.dataType.String(), callbackType.In(0))
|
||||
}
|
||||
|
||||
// Check output param
|
||||
if callbackType.NumOut() != 0 {
|
||||
return fmt.Errorf("invalid number of return parameters given in callback function. Expected 0")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Subscribe will subscribe to updates to the store by
|
||||
// providing a callback. Any updates to the store are sent
|
||||
// to the callback
|
||||
func (s *Store) Subscribe(callback interface{}) {
|
||||
|
||||
err := s.callbackCheck(callback)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
callbackFunc := reflect.ValueOf(callback)
|
||||
|
||||
s.callbacks = append(s.callbacks, callbackFunc)
|
||||
}
|
||||
|
||||
// updaterCheck ensures the given function to Update() is
|
||||
// of the correct signature. Absolutely cannot wait for
|
||||
// generics to land rather than writing this nonsense.
|
||||
func (s *Store) updaterCheck(updater interface{}) error {
|
||||
|
||||
// Get type
|
||||
updaterType := reflect.TypeOf(updater)
|
||||
|
||||
// Check updater is a function
|
||||
if updaterType.Kind() != reflect.Func {
|
||||
return fmt.Errorf("invalid value given to store.Update(). Expected 'func(%s) %s'", s.dataType.String(), s.dataType.String())
|
||||
}
|
||||
|
||||
// Check input param
|
||||
if updaterType.NumIn() != 1 {
|
||||
return fmt.Errorf("invalid number of parameters given in updater function. Expected 1")
|
||||
}
|
||||
|
||||
// Check input data type
|
||||
if updaterType.In(0) != s.dataType {
|
||||
return fmt.Errorf("invalid type for input parameter given in updater function. Expected %s, got %s", s.dataType.String(), updaterType.In(0))
|
||||
}
|
||||
|
||||
// Check output param
|
||||
if updaterType.NumOut() != 1 {
|
||||
return fmt.Errorf("invalid number of return parameters given in updater function. Expected 1")
|
||||
}
|
||||
|
||||
// Check output data type
|
||||
if updaterType.Out(0) != s.dataType {
|
||||
return fmt.Errorf("invalid type for return parameter given in updater function. Expected %s, got %s", s.dataType.String(), updaterType.Out(0))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update takes a function that is passed the current state.
|
||||
// The result of that function is then set as the new state
|
||||
// of the store. This will notify listeners of the change
|
||||
func (s *Store) Update(updater interface{}) {
|
||||
|
||||
err := s.updaterCheck(updater)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Build args
|
||||
args := []reflect.Value{s.data}
|
||||
|
||||
// Make call
|
||||
results := reflect.ValueOf(updater).Call(args)
|
||||
|
||||
// We will only have 1 result. Set the store to it
|
||||
err = s.Set(results[0].Interface())
|
||||
if err != nil && s.errorHandler != nil {
|
||||
s.errorHandler(err)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,5 @@
|
||||
#!/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
|
||||
echo "**** Building Runtime ****"
|
||||
cd runtime/js
|
||||
@@ -23,23 +15,9 @@ cd lib/renderer
|
||||
mewn
|
||||
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 ****"
|
||||
if ! go install
|
||||
then
|
||||
echo ""
|
||||
echo "ERROR: Install failed!"
|
||||
exit 1;
|
||||
fi
|
||||
cd cmd/wails
|
||||
go install
|
||||
cd ../..
|
||||
|
||||
echo "**** Tidying the mods! ****"
|
||||
|
||||
Reference in New Issue
Block a user