mirror of
https://github.com/taigrr/wails.git
synced 2026-04-04 06:02:43 -07:00
Compare commits
30 Commits
397---wind
...
443---ldfl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03200edd52 | ||
|
|
bbc16fe03a | ||
|
|
bdfc3ca631 | ||
|
|
490d66cf77 | ||
|
|
bce686d779 | ||
|
|
c0b0ef0200 | ||
|
|
8e869baed7 | ||
|
|
7522428d5c | ||
|
|
bc570999e8 | ||
|
|
393a4fceb2 | ||
|
|
da20bcc8d2 | ||
|
|
b091baa16f | ||
|
|
ecaaafa9d9 | ||
|
|
0009da9585 | ||
|
|
6235e83677 | ||
|
|
9f93e7d979 | ||
|
|
949bc40317 | ||
|
|
81777f29d8 | ||
|
|
5d35dd3105 | ||
|
|
ad034d3950 | ||
|
|
98337df92d | ||
|
|
9cc417cf04 | ||
|
|
030b954971 | ||
|
|
7a3ab27977 | ||
|
|
0e6265a9d7 | ||
|
|
b003a080b0 | ||
|
|
376ba743f4 | ||
|
|
aa8ffff68d | ||
|
|
613a44af5e | ||
|
|
2e15c4e045 |
@@ -27,3 +27,5 @@ Wails is what it is because of the time and effort given by these great people.
|
||||
* [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)
|
||||
|
||||
@@ -55,7 +55,7 @@ _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_
|
||||
_Also succesfully tested on: Zorin 15, Parrot 4.7, Linuxmint 19, Elementary 5, Kali, Neon_, Pop!_OS
|
||||
|
||||
#### Arch Linux / ArchLabs
|
||||
|
||||
|
||||
@@ -561,6 +561,11 @@ func ldFlags(po *ProjectOptions, buildMode string) string {
|
||||
|
||||
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()
|
||||
|
||||
27
cmd/linux.go
27
cmd/linux.go
@@ -59,6 +59,10 @@ const (
|
||||
Leap
|
||||
// ArchLabs distribution
|
||||
ArchLabs
|
||||
// PopOS distribution
|
||||
PopOS
|
||||
// Solus distribution
|
||||
Solus
|
||||
)
|
||||
|
||||
// DistroInfo contains all the information relating to a linux distribution
|
||||
@@ -107,7 +111,7 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
}
|
||||
switch splitLine[0] {
|
||||
case "ID":
|
||||
osID = strings.Trim(splitLine[1], "\"")
|
||||
osID = strings.ToLower(strings.Trim(splitLine[1], "\""))
|
||||
case "NAME":
|
||||
osNAME = strings.Trim(splitLine[1], "\"")
|
||||
case "VERSION_ID":
|
||||
@@ -116,7 +120,7 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
}
|
||||
|
||||
// Check distro name against list of distros
|
||||
switch strings.ToLower(osID) {
|
||||
switch osID {
|
||||
case "fedora":
|
||||
result.Distribution = Fedora
|
||||
case "centos":
|
||||
@@ -159,6 +163,10 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
result.Distribution = Tumbleweed
|
||||
case "opensuse-leap":
|
||||
result.Distribution = Leap
|
||||
case "pop":
|
||||
result.Distribution = PopOS
|
||||
case "solus":
|
||||
result.Distribution = Solus
|
||||
default:
|
||||
result.Distribution = Unknown
|
||||
}
|
||||
@@ -195,6 +203,17 @@ 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()
|
||||
@@ -266,5 +285,9 @@ 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
|
||||
}
|
||||
|
||||
@@ -28,6 +28,15 @@ 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:
|
||||
@@ -232,6 +241,25 @@ 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
|
||||
|
||||
121
cmd/package.go
121
cmd/package.go
@@ -16,9 +16,8 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"golang.org/x/image/draw"
|
||||
|
||||
"github.com/jackmordaunt/icns"
|
||||
"golang.org/x/image/draw"
|
||||
)
|
||||
|
||||
// PackageHelper helps with the 'wails package' command
|
||||
@@ -60,83 +59,107 @@ func newPlistData(title, exe, packageID, version, author string) *plistData {
|
||||
}
|
||||
}
|
||||
|
||||
type windowsIconHeader struct {
|
||||
type windowsIcoHeader struct {
|
||||
_ uint16
|
||||
imageType uint16
|
||||
imageCount uint16
|
||||
width uint8
|
||||
height uint8
|
||||
colours uint8
|
||||
_ uint8
|
||||
planes uint16
|
||||
bpp uint16
|
||||
size uint32
|
||||
offset uint32
|
||||
}
|
||||
|
||||
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 {
|
||||
header := &windowsIconHeader{
|
||||
imageType: 1,
|
||||
imageCount: 1,
|
||||
bpp: 32,
|
||||
planes: 1,
|
||||
offset: 22,
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
sizes := []int{256, 128, 64, 48, 32, 16}
|
||||
|
||||
// Load png
|
||||
pngfile, err := os.Open(pngFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer pngfile.Close()
|
||||
|
||||
// Decode to internal image
|
||||
pngdata, err := png.Decode(pngfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Scale to 256*256
|
||||
rect := image.Rect(0, 0, 255, 255)
|
||||
rawdata := image.NewRGBA(rect)
|
||||
scale := draw.ApproxBiLinear
|
||||
scale.Scale(rawdata, rect, pngdata, pngdata.Bounds(), draw.Over, nil)
|
||||
icons := []windowsIcoContainer{}
|
||||
|
||||
// Convert back to PNG
|
||||
icondata := new(bytes.Buffer)
|
||||
writer := bufio.NewWriter(icondata)
|
||||
err = png.Encode(writer, rawdata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = writer.Flush()
|
||||
if err != nil {
|
||||
return err
|
||||
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)
|
||||
}
|
||||
|
||||
// Save size of PNG data
|
||||
header.size = uint32(len(icondata.Bytes()))
|
||||
|
||||
// Open icon file for writing
|
||||
outfilename := filepath.Join(filepath.Dir(pngFilename), iconfile)
|
||||
outfile, err := os.Create(outfilename)
|
||||
outfile, err := os.Create(iconfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outfile.Close()
|
||||
|
||||
// Write out the header
|
||||
err = binary.Write(outfile, binary.LittleEndian, header)
|
||||
ico := windowsIcoHeader{
|
||||
imageType: 1,
|
||||
imageCount: uint16(len(sizes)),
|
||||
}
|
||||
err = binary.Write(outfile, binary.LittleEndian, ico)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write out the image data
|
||||
_, err = outfile.Write(icondata.Bytes())
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
100 ICON "$NAME$.ico"
|
||||
100 24 "$NAME$.exe.manifest"
|
||||
110 24 "$NAME$.exe.manifest"
|
||||
@@ -161,6 +161,7 @@ type ProjectOptions struct {
|
||||
CrossCompile bool
|
||||
Platform string
|
||||
Architecture string
|
||||
LdFlags string
|
||||
}
|
||||
|
||||
// Defaults sets the default project template
|
||||
|
||||
@@ -274,7 +274,7 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
||||
distroInfo := GetLinuxDistroInfo()
|
||||
|
||||
switch distroInfo.Distribution {
|
||||
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian:
|
||||
case Ubuntu, Debian, Zorin, Parrot, Linuxmint, Elementary, Kali, Neon, Deepin, Raspbian, PopOS:
|
||||
libraryChecker = DpkgInstalled
|
||||
case Arch, ArcoLinux, ArchLabs, Manjaro, ManjaroARM:
|
||||
libraryChecker = PacmanInstalled
|
||||
@@ -284,6 +284,8 @@ func CheckDependencies(logger *Logger) (bool, error) {
|
||||
libraryChecker = EqueryInstalled
|
||||
case VoidLinux:
|
||||
libraryChecker = XbpsInstalled
|
||||
case Solus:
|
||||
libraryChecker = EOpkgInstalled
|
||||
default:
|
||||
return false, RequestSupportForDistribution(distroInfo)
|
||||
}
|
||||
|
||||
5
cmd/templates/vanilla/README.md
Normal file
5
cmd/templates/vanilla/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# 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.
|
||||
42
cmd/templates/vanilla/frontend/package.json.template
Normal file
42
cmd/templates/vanilla/frontend/package.json.template
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
9
cmd/templates/vanilla/frontend/src/index.html
Normal file
9
cmd/templates/vanilla/frontend/src/index.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="main.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script src="main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
30
cmd/templates/vanilla/frontend/src/main.css
Normal file
30
cmd/templates/vanilla/frontend/src/main.css
Normal file
File diff suppressed because one or more lines are too long
28
cmd/templates/vanilla/frontend/src/main.js
Normal file
28
cmd/templates/vanilla/frontend/src/main.js
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
const runtime = require('@wailsapp/runtime');
|
||||
|
||||
// We need to wait for runtime.Init to complete before
|
||||
// running our JS
|
||||
runtime.Init(() => {
|
||||
|
||||
// Ensure the default app div is 100% wide/high
|
||||
var app = document.getElementById('app');
|
||||
app.style.width = '100%';
|
||||
app.style.height = '100%';
|
||||
|
||||
// Inject html
|
||||
app.innerHTML = `
|
||||
<div class='logo'></div>
|
||||
<div class='container'>
|
||||
<button id='button'>Click Me!</button>
|
||||
<div id='result'/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Connect button to Go method
|
||||
document.getElementById('button').onclick = () => {
|
||||
window.backend.basic().then((result) => {
|
||||
document.getElementById('result').innerText = result;
|
||||
})
|
||||
}
|
||||
});
|
||||
56
cmd/templates/vanilla/frontend/webpack.config.js
Normal file
56
cmd/templates/vanilla/frontend/webpack.config.js
Normal file
@@ -0,0 +1,56 @@
|
||||
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')
|
||||
},
|
||||
]
|
||||
})
|
||||
]
|
||||
};
|
||||
5
cmd/templates/vanilla/go.mod.template
Normal file
5
cmd/templates/vanilla/go.mod.template
Normal file
@@ -0,0 +1,5 @@
|
||||
module {{.BinaryName}}
|
||||
|
||||
require (
|
||||
github.com/wailsapp/wails {{.WailsVersion}}
|
||||
)
|
||||
27
cmd/templates/vanilla/main.go.template
Normal file
27
cmd/templates/vanilla/main.go.template
Normal file
@@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/leaanthony/mewn"
|
||||
"github.com/wailsapp/wails"
|
||||
)
|
||||
|
||||
func basic() string {
|
||||
return "Hello World!"
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
js := mewn.String("./frontend/build/main.js")
|
||||
css := mewn.String("./frontend/build/main.css")
|
||||
|
||||
app := wails.CreateApp(&wails.AppConfig{
|
||||
Width: 1024,
|
||||
Height: 768,
|
||||
Title: "{{.Name}}",
|
||||
JS: js,
|
||||
CSS: css,
|
||||
Colour: "#131313",
|
||||
})
|
||||
app.Bind(basic)
|
||||
app.Run()
|
||||
}
|
||||
12
cmd/templates/vanilla/template.json
Normal file
12
cmd/templates/vanilla/template.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"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.6.0-pre2"
|
||||
const Version = "v1.6.0"
|
||||
|
||||
@@ -29,6 +29,7 @@ func init() {
|
||||
var typescriptFilename = ""
|
||||
var verbose = false
|
||||
var platform = ""
|
||||
var ldflags = ""
|
||||
|
||||
buildSpinner := spinner.NewSpinner()
|
||||
buildSpinner.SetSpinSpeed(50)
|
||||
@@ -40,7 +41,8 @@ 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("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() {
|
||||
@@ -84,7 +86,7 @@ func init() {
|
||||
}
|
||||
}
|
||||
if !supported {
|
||||
return fmt.Errorf("Unsupported platform '%s' specified.\nPlease run `wails build -h` to see the supported platform/architecture options.", platform)
|
||||
return fmt.Errorf("unsupported platform '%s' specified.\nPlease run `wails build -h` to see the supported platform/architecture options", platform)
|
||||
}
|
||||
|
||||
projectOptions.CrossCompile = true
|
||||
@@ -93,6 +95,9 @@ func init() {
|
||||
projectOptions.Architecture = plat[1]
|
||||
}
|
||||
|
||||
// Add ldflags
|
||||
projectOptions.LdFlags = ldflags
|
||||
|
||||
// Validate config
|
||||
// Check if we have a frontend
|
||||
err = cmd.ValidateFrontendConfig(projectOptions)
|
||||
|
||||
@@ -35,8 +35,6 @@ func init() {
|
||||
|
||||
// Project options
|
||||
projectOptions := &cmd.ProjectOptions{}
|
||||
projectOptions.Verbose = verbose
|
||||
projectOptions.Platform = runtime.GOOS
|
||||
|
||||
// Check we are in project directory
|
||||
// Check project.json loads correctly
|
||||
@@ -46,6 +44,10 @@ func init() {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set project options
|
||||
projectOptions.Verbose = verbose
|
||||
projectOptions.Platform = runtime.GOOS
|
||||
|
||||
// Save project directory
|
||||
projectDir := fs.Cwd()
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ type Renderer interface {
|
||||
NotifyEvent(eventData *messages.EventData) error
|
||||
|
||||
// Dialog Runtime
|
||||
SelectFile() string
|
||||
SelectFile(title string, filter string) string
|
||||
SelectDirectory() string
|
||||
SelectSaveFile() string
|
||||
SelectSaveFile(title string, filter string) string
|
||||
|
||||
// Window Runtime
|
||||
SetColour(string) error
|
||||
|
||||
@@ -114,7 +114,7 @@ func (h *Bridge) NewBinding(methodName string) error {
|
||||
|
||||
// SelectFile is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) SelectFile() string {
|
||||
func (h *Bridge) SelectFile(title string, filter string) string {
|
||||
h.log.Warn("SelectFile() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
@@ -128,7 +128,7 @@ func (h *Bridge) SelectDirectory() string {
|
||||
|
||||
// SelectSaveFile is unsupported for Bridge but required
|
||||
// for the Renderer interface
|
||||
func (h *Bridge) SelectSaveFile() string {
|
||||
func (h *Bridge) SelectSaveFile(title string, filter string) string {
|
||||
h.log.Warn("SelectSaveFile() unsupported in bridge mode")
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -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() string {
|
||||
func (w *WebView) SelectFile(title string, filter string) string {
|
||||
var result string
|
||||
|
||||
// We need to run this on the main thread, however Dispatch is
|
||||
@@ -255,7 +255,7 @@ func (w *WebView) SelectFile() string {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
w.window.Dispatch(func() {
|
||||
result = w.window.Dialog(wv.DialogTypeOpen, 0, "Select File", "")
|
||||
result = w.window.Dialog(wv.DialogTypeOpen, 0, title, "", filter)
|
||||
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() string {
|
||||
func (w *WebView) SelectSaveFile(title string, filter string) 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() string {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
w.window.Dispatch(func() {
|
||||
result = w.window.Dialog(wv.DialogTypeSave, 0, "Save file", "")
|
||||
result = w.window.Dialog(wv.DialogTypeSave, 0, title, "", filter)
|
||||
wg.Done()
|
||||
})
|
||||
}()
|
||||
|
||||
@@ -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 *title, char *arg, char *res, size_t ressz, char *filter) {
|
||||
webview_dialog(w, dlgtype, flags,
|
||||
(const char*)title, (const char*) arg, res, ressz);
|
||||
(const char*)title, (const char*) arg, res, ressz, filter);
|
||||
}
|
||||
|
||||
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) string
|
||||
Dialog(dlgType DialogType, flags int, title string, arg string, filter 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) string {
|
||||
func (w *webview) Dialog(dlgType DialogType, flags int, title string, arg string, filter string) string {
|
||||
const maxPath = 4096
|
||||
titlePtr := C.CString(title)
|
||||
defer C.free(unsafe.Pointer(titlePtr))
|
||||
@@ -319,8 +319,10 @@ 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))
|
||||
argPtr, resultPtr, C.size_t(maxPath), filterPtr)
|
||||
return C.GoString(resultPtr)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 *result, size_t resultsz, char *filter);
|
||||
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 *result, size_t resultsz, char *filter)
|
||||
{
|
||||
GtkWidget *dlg;
|
||||
if (result != NULL)
|
||||
@@ -438,6 +438,16 @@ 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);
|
||||
}
|
||||
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);
|
||||
@@ -1410,6 +1420,8 @@ 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;
|
||||
@@ -1780,7 +1792,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 *result, size_t resultsz, char *filter)
|
||||
{
|
||||
if (dlgtype == WEBVIEW_DIALOG_TYPE_OPEN ||
|
||||
dlgtype == WEBVIEW_DIALOG_TYPE_SAVE)
|
||||
@@ -1820,6 +1832,32 @@ 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;
|
||||
@@ -1938,7 +1976,7 @@ struct webview_priv
|
||||
(struct webview *)objc_getAssociatedObject(self, "webview");
|
||||
|
||||
webview_dialog(w, WEBVIEW_DIALOG_TYPE_OPEN, WEBVIEW_DIALOG_FLAG_FILE, "", "",
|
||||
filename, 255);
|
||||
filename, 255, "");
|
||||
filename[255] = '\0';
|
||||
if (strlen(filename) > 0)
|
||||
{
|
||||
@@ -2201,12 +2239,16 @@ 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 *result, size_t resultsz, char *filter)
|
||||
{
|
||||
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];
|
||||
@@ -2219,6 +2261,10 @@ struct webview_priv
|
||||
{
|
||||
[openPanel setCanChooseFiles:YES];
|
||||
[openPanel setCanChooseDirectories:NO];
|
||||
if(filter[0] != NULL)
|
||||
{
|
||||
[openPanel setAllowedFileTypes:fileTypes];
|
||||
}
|
||||
}
|
||||
[openPanel setResolvesAliases:NO];
|
||||
[openPanel setAllowsMultipleSelection:NO];
|
||||
@@ -2232,6 +2278,10 @@ 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) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package runtime
|
||||
|
||||
import "github.com/wailsapp/wails/lib/interfaces"
|
||||
import "strings"
|
||||
|
||||
// Dialog exposes an interface to native dialogs
|
||||
type Dialog struct {
|
||||
@@ -15,8 +16,16 @@ func NewDialog(renderer interfaces.Renderer) *Dialog {
|
||||
}
|
||||
|
||||
// SelectFile prompts the user to select a file
|
||||
func (r *Dialog) SelectFile() string {
|
||||
return r.renderer.SelectFile()
|
||||
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)
|
||||
}
|
||||
|
||||
// SelectDirectory prompts the user to select a directory
|
||||
@@ -25,6 +34,14 @@ func (r *Dialog) SelectDirectory() string {
|
||||
}
|
||||
|
||||
// SelectSaveFile prompts the user to select a file for saving
|
||||
func (r *Dialog) SelectSaveFile() string {
|
||||
return r.renderer.SelectSaveFile()
|
||||
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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user