mirror of
https://github.com/taigrr/wails.git
synced 2026-04-02 13:19:00 -07:00
Compare commits
61 Commits
v2.0.0-bet
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6d7ec3d50 | ||
|
|
d2a116fe55 | ||
|
|
eb3cf9d130 | ||
|
|
7e2258be7d | ||
|
|
bb5d446001 | ||
|
|
e9aba4795f | ||
|
|
c16bb9715f | ||
|
|
0f09e8d433 | ||
|
|
f338dff171 | ||
|
|
3c6ed12637 | ||
|
|
e2f3a11a33 | ||
|
|
0571deb290 | ||
|
|
451b357e40 | ||
|
|
84b67a8f53 | ||
|
|
448cf731bb | ||
|
|
9cb480f0f0 | ||
|
|
6825a631f5 | ||
|
|
39f91a030f | ||
|
|
202e4d5be8 | ||
|
|
045e58778a | ||
|
|
e375d60c67 | ||
|
|
fcb5499d3a | ||
|
|
dd5a54a8e0 | ||
|
|
9f24a46b8a | ||
|
|
d7eaab97dd | ||
|
|
a03d1e5ac5 | ||
|
|
d5d4d88481 | ||
|
|
1c823b09c4 | ||
|
|
e5732bcee1 | ||
|
|
c0f283335a | ||
|
|
64cdf64751 | ||
|
|
609bfc35c0 | ||
|
|
121d11db55 | ||
|
|
5c357f012d | ||
|
|
56285f8637 | ||
|
|
b61158d329 | ||
|
|
0233197073 | ||
|
|
d883397d75 | ||
|
|
5bd82c4637 | ||
|
|
e942867635 | ||
|
|
29749ed7cb | ||
|
|
0288f33556 | ||
|
|
ddeac08991 | ||
|
|
30e12d681c | ||
|
|
f9fce9f2a7 | ||
|
|
9c5bb8c6eb | ||
|
|
f2ab409284 | ||
|
|
7c190810fd | ||
|
|
2b2cd21674 | ||
|
|
f025234c85 | ||
|
|
44035637f7 | ||
|
|
008a5c70b9 | ||
|
|
24eaef1604 | ||
|
|
62adcab722 | ||
|
|
e12b630dfb | ||
|
|
81b3ecb056 | ||
|
|
b4d14644ee | ||
|
|
69fd584c32 | ||
|
|
3444ec50a7 | ||
|
|
02d4c65e01 | ||
|
|
efdcfe9985 |
22
README.md
22
README.md
@@ -106,6 +106,13 @@ Click [here](https://wails.io) if you are interested in trying out v2 Beta for W
|
||||
|
||||
This project is supported by these kind people / companies:
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.easywebadv.it/" style="width:150px;">
|
||||
<img src="website/static/img/easyweb.png" width="150"/>
|
||||
</a>
|
||||
</p>
|
||||
<br/>
|
||||
<br/>
|
||||
<a href="https://github.com/sponsors/leaanthony" style="width:100px;">
|
||||
<img src="sponsors/silver%20sponsor.png" width="100"/>
|
||||
</a>
|
||||
@@ -176,9 +183,6 @@ This project is supported by these kind people / companies:
|
||||
<a href="https://github.com/ilgityildirim" style="width:50px">
|
||||
<img src="https://github.com/ilgityildirim.png?size=50" width="50"/>
|
||||
</a>
|
||||
<a href="https://github.com/ondoki" style="width:65px">
|
||||
<img src="https://github.com/ondoki.png?size=65" width="65"/>
|
||||
</a>
|
||||
<a href="https://github.com/questrail" style="width:50px">
|
||||
<img src="https://github.com/questrail.png?size=50" width="50"/>
|
||||
</a>
|
||||
@@ -188,6 +192,18 @@ This project is supported by these kind people / companies:
|
||||
<a href="https://github.com/taigrr" style="width:45px">
|
||||
<img src="https://github.com/taigrr.png?size=45" width="45"/>
|
||||
</a>
|
||||
<a href="https://github.com/charlie-dee" style="width:55px">
|
||||
<img src="https://github.com/charlie-dee.png?size=55" width="55"/>
|
||||
</a>
|
||||
<a href="https://github.com/EdenNetworkItalia" style="width:65px">
|
||||
<img src="https://github.com/EdenNetworkItalia.png?size=65" width="65"/>
|
||||
</a>
|
||||
<a href="https://github.com/michaelolson1996" style="width:55px">
|
||||
<img src="https://github.com/michaelolson1996.png?size=55" width="55"/>
|
||||
</a>
|
||||
<a href="https://github.com/GargantuaX" style="width:45px">
|
||||
<img src="https://github.com/GargantuaX.png?size=45" width="45"/>
|
||||
</a>
|
||||
|
||||
<span id="nav-6"></span>
|
||||
|
||||
|
||||
@@ -109,6 +109,13 @@
|
||||
|
||||
这个项目由以下这些人或者公司支持:
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.easywebadv.it/" style="width:100px;">
|
||||
<img src="website/static/img/easyweb.png" width="120"/>
|
||||
</a>
|
||||
</p>
|
||||
<br/>
|
||||
<br/>
|
||||
<a href="https://github.com/sponsors/leaanthony" style="width:100px;">
|
||||
<img src="sponsors/silver%20sponsor.png" width="100"/>
|
||||
</a>
|
||||
@@ -179,9 +186,6 @@
|
||||
<a href="https://github.com/ilgityildirim" style="width:50px">
|
||||
<img src="https://github.com/ilgityildirim.png?size=50" width="50"/>
|
||||
</a>
|
||||
<a href="https://github.com/ondoki" style="width:65px">
|
||||
<img src="https://github.com/ondoki.png?size=65" width="65"/>
|
||||
</a>
|
||||
<a href="https://github.com/questrail" style="width:50px">
|
||||
<img src="https://github.com/questrail.png?size=50" width="50"/>
|
||||
</a>
|
||||
@@ -191,6 +195,18 @@
|
||||
<a href="https://github.com/taigrr" style="width:45px">
|
||||
<img src="https://github.com/taigrr.png?size=45" width="45"/>
|
||||
</a>
|
||||
<a href="https://github.com/charlie-dee" style="width:55px">
|
||||
<img src="https://github.com/charlie-dee.png?size=55" width="55"/>
|
||||
</a>
|
||||
<a href="https://github.com/EdenNetworkItalia" style="width:65px">
|
||||
<img src="https://github.com/EdenNetworkItalia.png?size=65" width="65"/>
|
||||
</a>
|
||||
<a href="https://github.com/michaelolson1996" style="width:55px">
|
||||
<img src="https://github.com/michaelolson1996.png?size=55" width="55"/>
|
||||
</a>
|
||||
<a href="https://github.com/GargantuaX" style="width:45px">
|
||||
<img src="https://github.com/GargantuaX.png?size=45" width="45"/>
|
||||
</a>
|
||||
|
||||
<span id="nav-6"></span>
|
||||
|
||||
|
||||
10
cmd/fs.go
10
cmd/fs.go
@@ -148,16 +148,6 @@ func (fs *FSHelper) LocalDir(dir string) (*Dir, error) {
|
||||
}, err
|
||||
}
|
||||
|
||||
// LoadRelativeFile loads the given file relative to the caller's directory
|
||||
func (fs *FSHelper) LoadRelativeFile(relativePath string) ([]byte, error) {
|
||||
_, filename, _, _ := runtime.Caller(0)
|
||||
fullPath, err := filepath.Abs(filepath.Join(path.Dir(filename), relativePath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return os.ReadFile(fullPath)
|
||||
}
|
||||
|
||||
// GetSubdirs will return a list of FQPs to subdirectories in the given directory
|
||||
func (d *Dir) GetSubdirs() (map[string]string, error) {
|
||||
|
||||
|
||||
@@ -74,6 +74,8 @@ const (
|
||||
NixOS
|
||||
// Artix linux distribution
|
||||
ArtixLinux
|
||||
//Uos distribution
|
||||
Uos
|
||||
)
|
||||
|
||||
// DistroInfo contains all the information relating to a linux distribution
|
||||
@@ -190,6 +192,8 @@ func parseOsRelease(osRelease string) *DistroInfo {
|
||||
result.Distribution = NixOS
|
||||
case "artix":
|
||||
result.Distribution = ArtixLinux
|
||||
case "uos":
|
||||
result.Distribution = Uos
|
||||
default:
|
||||
result.Distribution = Unknown
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"log"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
//go:embed linuxdb.yaml
|
||||
var LinuxDBYaml []byte
|
||||
|
||||
// LinuxDB is the database for linux distribution data.
|
||||
type LinuxDB struct {
|
||||
Distributions map[string]*Distribution `yaml:"distributions"`
|
||||
@@ -78,14 +82,10 @@ func (l *LinuxDB) GetDistro(distro string) *Distribution {
|
||||
// NewLinuxDB creates a new LinuxDB instance from the bundled
|
||||
// linuxdb.yaml file.
|
||||
func NewLinuxDB() *LinuxDB {
|
||||
data, err := fs.LoadRelativeFile("./linuxdb.yaml")
|
||||
if err != nil {
|
||||
log.Fatal("Could not load linuxdb.yaml")
|
||||
}
|
||||
result := LinuxDB{
|
||||
Distributions: make(map[string]*Distribution),
|
||||
}
|
||||
err = result.ImportData(data)
|
||||
err := result.ImportData(LinuxDBYaml)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -100,6 +100,15 @@ distributions:
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
uos:
|
||||
id: uos
|
||||
releases:
|
||||
default:
|
||||
version: default
|
||||
name: Uos
|
||||
gccversioncommand: *gccdumpfullversion
|
||||
programs: *debiandefaultprograms
|
||||
libraries: *debiandefaultlibraries
|
||||
void:
|
||||
id: void
|
||||
releases:
|
||||
|
||||
@@ -313,10 +313,12 @@ func (b *PackageHelper) PackageWindows(po *ProjectOptions, cleanUp bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate icon from PNG
|
||||
err = generateWindowsIcon(icon, basename+".ico")
|
||||
if err != nil {
|
||||
return err
|
||||
// Generate icon from PNG if it doesn't exist
|
||||
if !fs.FileExists(basename + ".ico") {
|
||||
err = generateWindowsIcon(icon, basename+".ico")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Copy manifest
|
||||
|
||||
@@ -278,7 +278,7 @@ 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, PopOS, Uos:
|
||||
libraryChecker = DpkgInstalled
|
||||
case Arch, ArcoLinux, ArchLabs, Ctlos, Manjaro, ManjaroARM, EndeavourOS, ArtixLinux:
|
||||
libraryChecker = PacmanInstalled
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cmd
|
||||
|
||||
// Version - Wails version
|
||||
const Version = "v1.16.8"
|
||||
const Version = "v1.16.9"
|
||||
|
||||
@@ -15,8 +15,6 @@ The build command processes the Wails project and generates an application binar
|
||||
| -ldflags "custom ld flags" | Use given ldflags | |
|
||||
| -o path/to/binary | Compile to given path/filename | |
|
||||
| -k | Keep generated assets | |
|
||||
| -package | Create a platform specific package | |
|
||||
| -production | Compile in production mode: -ldflags="-w -s" + "-h windows" on Windows | |
|
||||
| -tags | Build tags to pass to Go compiler (quoted and space separated) | |
|
||||
| -upx | Compress final binary with UPX (if installed) | |
|
||||
| -upxflags "custom flags" | Flags to pass to upx | |
|
||||
@@ -36,13 +34,13 @@ The build process is as follows:
|
||||
- The frontend is then built. This command is read from the project file `wails.json` under the key `frontend:install` and executed in the `frontend` directory. If this is not defined, it is ignored.
|
||||
- The project directory is checked to see if the `build` directory exists. If not, it is created and default project assets are copied to it.
|
||||
- An asset bundle is then created by reading the `html` key from `wails.json` and loading the referenced file. This is then parsed, looking for local Javascript and CSS references. Those files are in turn loaded into memory, converted to C data and saved into the asset bundle located at `build/assets.h`, which also includes the original HTML.
|
||||
- The application icon is then processed: if there is no `build/appicon.png`, a default icon is copied. On Windows, an `app.ico` file is generated from this png. On Mac, `icons.icns` is generated.
|
||||
- If there are icons in the `build/tray` directory, these are processed, converted to C data and saved as `build/trayicons.h`, ready for the compilation step.
|
||||
- If there are icons in the `build/dialog` directory, these are processed, converted to C data and saved as `build/userdialogicons.h`, ready for the compilation step.
|
||||
- If the `-package` flag is given for a Windows target, the Windows assets in the `build/windows` directory are processed: manifest + icons compiled to a `.syso` file (deleted after compilation).
|
||||
- If we are building a universal binary for Mac, the application is compiled for both `arm64` and `amd64`. The `lipo` tool is then executed to create the universal binary.
|
||||
- The application icon is then processed: if there is no `build/appicon.png`, a default icon is copied. On Windows,
|
||||
an `app.ico` file is generated from this png. On Mac, `icons.icns` is generated.
|
||||
- The platform assets in the `build/<platform>` directory are processed: manifest + icons compiled to a `.syso` file (
|
||||
deleted after compilation), `info.plist` copied to `.app` on Mac.
|
||||
- If we are building a universal binary for Mac, the application is compiled for both `arm64` and `amd64`. The `lipo`
|
||||
tool is then executed to create the universal binary.
|
||||
- If we are not building a universal binary for Mac, the application is built using `go build`, using build tags to indicate type of application and build mode (debug/production).
|
||||
- If the `-upx` flag was provided, `upx` is invoked to compress the binary. Custom flags may be provided using the `-upxflags` flag.
|
||||
- If the `package` flag is given for a non Windows target, the application is bundled for the platform. On Mac, this creates a `.app` with the processed icons, the `Info.plist` in `build/darwin` and the compiled binary.
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package build
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v2/internal/colour"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -38,6 +39,9 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
compilerCommand := "go"
|
||||
command.StringFlag("compiler", "Use a different go compiler to build, eg go1.15beta1", &compilerCommand)
|
||||
|
||||
skipModTidy := false
|
||||
command.BoolFlag("m", "Skip mod tidy before compile", &skipModTidy)
|
||||
|
||||
compress := false
|
||||
command.BoolFlag("upx", "Compress final binary with UPX (if installed)", &compress)
|
||||
|
||||
@@ -76,6 +80,12 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
forceBuild := false
|
||||
command.BoolFlag("f", "Force build application", &forceBuild)
|
||||
|
||||
updateGoMod := false
|
||||
command.BoolFlag("u", "Updates go.mod to use the same Wails version as the CLI", &updateGoMod)
|
||||
|
||||
debug := false
|
||||
command.BoolFlag("debug", "Retains debug data in the compiled application", &debug)
|
||||
|
||||
command.Action(func() error {
|
||||
|
||||
quiet := verbosity == 0
|
||||
@@ -157,16 +167,24 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
}
|
||||
}
|
||||
|
||||
mode := build.Production
|
||||
modeString := "Production"
|
||||
if debug {
|
||||
mode = build.Debug
|
||||
modeString = "Debug"
|
||||
}
|
||||
|
||||
// Create BuildOptions
|
||||
buildOptions := &build.Options{
|
||||
Logger: logger,
|
||||
OutputType: outputType,
|
||||
OutputFile: outputFilename,
|
||||
CleanBuildDirectory: cleanBuildDirectory,
|
||||
Mode: build.Production,
|
||||
Mode: mode,
|
||||
Pack: !noPackage,
|
||||
LDFlags: ldflags,
|
||||
Compiler: compilerCommand,
|
||||
SkipModTidy: skipModTidy,
|
||||
Verbosity: verbosity,
|
||||
ForceBuild: forceBuild,
|
||||
IgnoreFrontend: skipFrontend,
|
||||
@@ -198,6 +216,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
fmt.Fprintf(w, "Platform: \t%s\n", buildOptions.Platform)
|
||||
fmt.Fprintf(w, "Arch: \t%s\n", buildOptions.Arch)
|
||||
fmt.Fprintf(w, "Compiler: \t%s\n", compilerPath)
|
||||
fmt.Fprintf(w, "Build Mode: \t%s\n", modeString)
|
||||
fmt.Fprintf(w, "Skip Frontend: \t%t\n", skipFrontend)
|
||||
fmt.Fprintf(w, "Compress: \t%t\n", buildOptions.Compress)
|
||||
fmt.Fprintf(w, "Package: \t%t\n", buildOptions.Pack)
|
||||
@@ -210,7 +229,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
fmt.Fprintf(w, "\n")
|
||||
w.Flush()
|
||||
|
||||
err = checkGoModVersion(logger)
|
||||
err = checkGoModVersion(logger, updateGoMod)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -239,7 +258,7 @@ func doBuild(buildOptions *build.Options) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkGoModVersion(logger *clilogger.CLILogger) error {
|
||||
func checkGoModVersion(logger *clilogger.CLILogger, updateGoMod bool) error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -261,6 +280,36 @@ func checkGoModVersion(logger *clilogger.CLILogger) error {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Println("Warning: go.mod is using Wails '%s' but the CLI is '%s'. Consider updating it.\n", gomodversion.String(), internal.Version)
|
||||
if updateGoMod {
|
||||
return syncGoModVersion(cwd)
|
||||
}
|
||||
|
||||
logger.Println("Warning: go.mod is using Wails '%s' but the CLI is '%s'. Consider updating your project's `go.mod` file.\n", gomodversion.String(), internal.Version)
|
||||
return nil
|
||||
}
|
||||
|
||||
func LogGreen(message string, args ...interface{}) {
|
||||
text := fmt.Sprintf(message, args...)
|
||||
println(colour.Green(text))
|
||||
}
|
||||
|
||||
func syncGoModVersion(cwd string) error {
|
||||
gomodFilename := filepath.Join(cwd, "go.mod")
|
||||
gomodData, err := os.ReadFile(gomodFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
outOfSync, err := gomod.GoModOutOfSync(gomodData, internal.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !outOfSync {
|
||||
return nil
|
||||
}
|
||||
LogGreen("Updating go.mod to use Wails '%s'", internal.Version)
|
||||
newGoData, err := gomod.UpdateGoModVersion(gomodData, internal.Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(gomodFilename, newGoData, 0755)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/wailsapp/wails/v2/cmd/wails/internal/commands/generate/template"
|
||||
"io"
|
||||
|
||||
"github.com/leaanthony/clir"
|
||||
)
|
||||
@@ -17,6 +16,7 @@ func AddSubcommand(app *clir.Cli, w io.Writer) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
template.AddSubCommand(app, command, w)
|
||||
|
||||
return nil
|
||||
|
||||
@@ -4,13 +4,12 @@
|
||||
|
||||
About your template
|
||||
|
||||
## Building
|
||||
|
||||
To build this project in debug mode, use `wails build`. For production, use `wails build -production`.
|
||||
To generate a platform native package, add the `-package` flag.
|
||||
|
||||
## Live Development
|
||||
|
||||
To run in live development mode, run `wails dev` in the project directory. In another terminal, go into the `frontend`
|
||||
directory and run `npm run dev`. The frontend dev server will run on http://localhost:34115. Connect to this
|
||||
in your browser and connect to your application.
|
||||
To run in live development mode, run `wails dev` in the project directory. In another terminal, go into the `frontend`
|
||||
directory and run `npm run dev`. The frontend dev server will run on http://localhost:34115. Connect to this in your
|
||||
browser and connect to your application.
|
||||
|
||||
## Building
|
||||
|
||||
To build a redistributable, production mode package, use `wails build`.
|
||||
|
||||
@@ -22,7 +22,6 @@ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
|
||||
github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
|
||||
@@ -90,8 +90,6 @@ github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0H
|
||||
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
|
||||
github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
|
||||
github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
|
||||
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
|
||||
|
||||
@@ -22,7 +22,6 @@ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
|
||||
github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
|
||||
@@ -91,8 +91,6 @@ github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0H
|
||||
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
|
||||
github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
|
||||
github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
|
||||
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
|
||||
|
||||
@@ -22,7 +22,6 @@ github.com/leaanthony/go-common-file-dialog v1.0.3 // indirect
|
||||
github.com/leaanthony/go-webview2 v0.0.0-20210914103035-f00aa774a934 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
|
||||
@@ -91,8 +91,6 @@ github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0H
|
||||
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
|
||||
github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
|
||||
github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 h1:5iOd93PZbpH4Iir8QkC4coFD+zEQEZSIRcjwjTFZkr0=
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
|
||||
github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU=
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
package internal
|
||||
|
||||
var Version = "v2.0.0-beta.22"
|
||||
var Version = "v2.0.0-beta.27"
|
||||
|
||||
@@ -22,12 +22,11 @@ require (
|
||||
github.com/leaanthony/debme v1.2.1
|
||||
github.com/leaanthony/go-ansi-parser v1.0.1
|
||||
github.com/leaanthony/go-common-file-dialog v1.0.3
|
||||
github.com/leaanthony/go-webview2 v0.0.0-20211202091502-64deee9a37e3
|
||||
github.com/leaanthony/go-webview2 v1.0.2
|
||||
github.com/leaanthony/gosod v1.0.3
|
||||
github.com/leaanthony/idgen v1.0.0
|
||||
github.com/leaanthony/slicer v1.5.0
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7
|
||||
github.com/leaanthony/webview2runtime v1.1.0
|
||||
github.com/leaanthony/winc v0.0.0-20211202091710-9931d43181ff
|
||||
github.com/leaanthony/winicon v1.0.0
|
||||
github.com/matryer/is v1.4.0
|
||||
@@ -43,7 +42,7 @@ require (
|
||||
github.com/ztrue/tracerr v0.3.0
|
||||
golang.org/x/mod v0.4.1
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed
|
||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
|
||||
golang.org/x/tools v0.1.0
|
||||
nhooyr.io/websocket v1.8.6
|
||||
)
|
||||
|
||||
11
v2/go.sum
11
v2/go.sum
@@ -118,8 +118,8 @@ github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQ
|
||||
github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
|
||||
github.com/leaanthony/go-common-file-dialog v1.0.3 h1:O0uGjKnWtdEADGrkg+TyAAbZylykMwwx/MNEXn9fp+Y=
|
||||
github.com/leaanthony/go-common-file-dialog v1.0.3/go.mod h1:TGhEc9eSJgRsupZ+iH1ZgAOnEo9zp05cRH2j08RPrF0=
|
||||
github.com/leaanthony/go-webview2 v0.0.0-20211202091502-64deee9a37e3 h1:vKdQzUWiq5wtVBLTTeYuikcgQbF/HtYaOmxGzbfkcT0=
|
||||
github.com/leaanthony/go-webview2 v0.0.0-20211202091502-64deee9a37e3/go.mod h1:iX54IaVk1FnDqMuHJ47VYLPQOcVqQiOe9SJACt9CAbU=
|
||||
github.com/leaanthony/go-webview2 v1.0.2 h1:IjTbpAXUig33G3LUqf+8EClZutg2Z/C1cbxqhHKPxbU=
|
||||
github.com/leaanthony/go-webview2 v1.0.2/go.mod h1:iX54IaVk1FnDqMuHJ47VYLPQOcVqQiOe9SJACt9CAbU=
|
||||
github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
|
||||
github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
|
||||
github.com/leaanthony/idgen v1.0.0 h1:IZreR+JGEzFV4yeVuBZA25gM0keUoFy+RDUldncQ+Jw=
|
||||
@@ -128,8 +128,6 @@ github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0H
|
||||
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 h1:yoznzWzyxkO/iWdlpq+aPcuJ5Y/hpjq/lmgMFmpjwl0=
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7/go.mod h1:cWtOkiVhMF77e6phAXUcfNwYmMwCJ67Sij24lfvi9Js=
|
||||
github.com/leaanthony/webview2runtime v1.1.0 h1:N0pv55ift8XtqozIp4PNOtRCJ/Qdd/qzx80lUpalS4c=
|
||||
github.com/leaanthony/webview2runtime v1.1.0/go.mod h1:hH9GnWCve3DYzNaPOcPbhHQ7fodXR1QJNsnwixid4Tk=
|
||||
github.com/leaanthony/winc v0.0.0-20211202091710-9931d43181ff h1:FwGObElCr/T/xy8S9IKDjWsNcfJHGxgjRl/GIbcseoQ=
|
||||
github.com/leaanthony/winc v0.0.0-20211202091710-9931d43181ff/go.mod h1:KEbMsKoznsebyGHwLk5LqkFOxL5uXSRdvpP4+avmAMs=
|
||||
github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ=
|
||||
@@ -258,10 +256,9 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210611083646-a4fc73990273/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 h1:LOlKVhfDyahgmqa97awczplwkjzNaELFg3zRIJ13RYo=
|
||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
||||
@@ -15,9 +15,9 @@ func PreflightChecks(options *options.App, logger *logger.Logger) error {
|
||||
// Process the webview2 runtime situation. We can pass a strategy in via the `webview2` flag for `wails build`.
|
||||
// This will determine how wv2runtime.Process will handle a lack of valid runtime.
|
||||
installedVersion, err := wv2runtime.Process()
|
||||
if installedVersion != nil {
|
||||
logger.Debug("WebView2 Runtime installed: Name: '%s' Version:'%s' Location:'%s'. Minimum version required: %s.",
|
||||
installedVersion.Name, installedVersion.Version, installedVersion.Location, wv2runtime.MinimumRuntimeVersion)
|
||||
if installedVersion != "" {
|
||||
logger.Debug("WebView2 Runtime Version '%s' installed. Minimum version required: %s.",
|
||||
installedVersion, wv2runtime.MinimumRuntimeVersion)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -5,7 +5,7 @@ package wv2runtime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leaanthony/webview2runtime"
|
||||
"github.com/wailsapp/wails/v2/internal/webview2runtime"
|
||||
)
|
||||
|
||||
func doInstallationStrategy(installStatus installationStatus) error {
|
||||
|
||||
@@ -5,7 +5,7 @@ package wv2runtime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leaanthony/webview2runtime"
|
||||
"github.com/wailsapp/wails/v2/internal/webview2runtime"
|
||||
)
|
||||
|
||||
func doInstallationStrategy(installStatus installationStatus) error {
|
||||
|
||||
@@ -5,7 +5,7 @@ package wv2runtime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leaanthony/webview2runtime"
|
||||
"github.com/wailsapp/wails/v2/internal/webview2runtime"
|
||||
)
|
||||
|
||||
func doInstallationStrategy(installStatus installationStatus) error {
|
||||
|
||||
@@ -5,7 +5,7 @@ package wv2runtime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/leaanthony/webview2runtime"
|
||||
"github.com/wailsapp/wails/v2/internal/webview2runtime"
|
||||
)
|
||||
|
||||
func doInstallationStrategy(installStatus installationStatus) error {
|
||||
|
||||
@@ -2,7 +2,6 @@ package wv2runtime
|
||||
|
||||
import (
|
||||
"github.com/leaanthony/go-webview2/webviewloader"
|
||||
"github.com/leaanthony/webview2runtime"
|
||||
)
|
||||
|
||||
const MinimumRuntimeVersion string = "91.0.992.28"
|
||||
@@ -15,14 +14,17 @@ const (
|
||||
installed
|
||||
)
|
||||
|
||||
func Process() (*webview2runtime.Info, error) {
|
||||
func Process() (string, error) {
|
||||
installStatus := needsInstalling
|
||||
installedVersion := webview2runtime.GetInstalledVersion()
|
||||
if installedVersion != nil {
|
||||
installedVersion, err := webviewloader.GetInstalledVersion()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if installedVersion != "" {
|
||||
installStatus = installed
|
||||
compareResult, err := webviewloader.CompareBrowserVersions(installedVersion.Version, MinimumRuntimeVersion)
|
||||
compareResult, err := webviewloader.CompareBrowserVersions(installedVersion, MinimumRuntimeVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
updateRequired := compareResult == -1
|
||||
// Installed and does not require updating
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#import <WebKit/WebKit.h>
|
||||
|
||||
#if __has_include(<UniformTypeIdentifiers/UTType.h>)
|
||||
#define USE_NEW_FILTERS
|
||||
#import <UniformTypeIdentifiers/UTType.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -497,16 +497,20 @@
|
||||
filters = [filters stringByReplacingOccurrencesOfString:@"*." withString:@""];
|
||||
filters = [filters stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||||
NSArray *filterList = [filters componentsSeparatedByString:@";"];
|
||||
if (@available(macOS 10.16, *)) {
|
||||
#ifdef USE_NEW_FILTERS
|
||||
NSMutableArray *contentTypes = [[NSMutableArray new] autorelease];
|
||||
for (NSString *filter in filterList) {
|
||||
UTType *t = [UTType typeWithFilenameExtension:filter];
|
||||
[contentTypes addObject:t];
|
||||
if (@available(macOS 11.0, *)) {
|
||||
UTType *t = [UTType typeWithFilenameExtension:filter];
|
||||
[contentTypes addObject:t];
|
||||
}
|
||||
}
|
||||
if (@available(macOS 11.0, *)) {
|
||||
[dialog setAllowedContentTypes:contentTypes];
|
||||
} else {
|
||||
[dialog setAllowedFileTypes:filterList];
|
||||
}
|
||||
#else
|
||||
[dialog setAllowedFileTypes:filterList];
|
||||
#endif
|
||||
} else {
|
||||
[dialog setAllowsOtherFileTypes:true];
|
||||
}
|
||||
@@ -536,6 +540,10 @@
|
||||
|
||||
// Setup callback handler
|
||||
[dialog beginSheetModalForWindow:self.mainWindow completionHandler:^(NSModalResponse returnCode) {
|
||||
if ( returnCode != NSModalResponseOK) {
|
||||
processOpenFileDialogResponse("[]");
|
||||
return;
|
||||
}
|
||||
NSMutableArray *arr = [NSMutableArray new];
|
||||
for (NSURL *url in [dialog URLs]) {
|
||||
[arr addObject:[url path]];
|
||||
@@ -554,7 +562,7 @@
|
||||
|
||||
|
||||
// Create the dialog
|
||||
NSSavePanel *dialog = [NSOpenPanel savePanel];
|
||||
NSSavePanel *dialog = [NSSavePanel savePanel];
|
||||
|
||||
// Valid but appears to do nothing.... :/
|
||||
if( title != nil ) {
|
||||
@@ -562,7 +570,7 @@
|
||||
}
|
||||
|
||||
// Filters - semicolon delimited list of file extensions
|
||||
if( filters != nil ) {
|
||||
if( filters != nil && [filters length] > 0) {
|
||||
filters = [filters stringByReplacingOccurrencesOfString:@"*." withString:@""];
|
||||
filters = [filters stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||||
NSArray *filterList = [filters componentsSeparatedByString:@";"];
|
||||
@@ -588,10 +596,12 @@
|
||||
|
||||
// Setup callback handler
|
||||
[dialog beginSheetModalForWindow:self.mainWindow completionHandler:^(NSModalResponse returnCode) {
|
||||
NSURL *url = [dialog URL];
|
||||
if ( url != nil ) {
|
||||
processSaveFileDialogResponse([url.path UTF8String]);
|
||||
return;
|
||||
if ( returnCode == NSModalResponseOK ) {
|
||||
NSURL *url = [dialog URL];
|
||||
if ( url != nil ) {
|
||||
processSaveFileDialogResponse([url.path UTF8String]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
processSaveFileDialogResponse("");
|
||||
}];
|
||||
|
||||
@@ -43,14 +43,16 @@
|
||||
- (WailsMenu*) initWithNSTitle:(NSString *)title {
|
||||
if( title != nil ) {
|
||||
[super initWithTitle:title];
|
||||
} else {
|
||||
[self init];
|
||||
}
|
||||
[self setAutoenablesItems:NO];
|
||||
return [self init];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) appendSubmenu :(WailsMenu*)child {
|
||||
NSMenuItem *childMenuItem = [[NSMenuItem new] autorelease];
|
||||
[childMenuItem setTitle:[child title]];
|
||||
[childMenuItem setTitle:child.title];
|
||||
[self addItem:childMenuItem];
|
||||
[childMenuItem setSubmenu:child];
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ func (f *Frontend) openDialog(options *frontend.OpenDialogOptions, multiple bool
|
||||
|
||||
// OpenFileDialog prompts the user to select a file
|
||||
func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, error) {
|
||||
results, err := f.openDialog(&options, false, options.AllowFiles, options.AllowDirectories)
|
||||
results, err := f.openDialog(&options, false, true, false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func (f *Frontend) OpenFileDialog(options frontend.OpenDialogOptions) (string, e
|
||||
|
||||
// OpenMultipleFilesDialog prompts the user to select a file
|
||||
func (f *Frontend) OpenMultipleFilesDialog(options frontend.OpenDialogOptions) ([]string, error) {
|
||||
return f.openDialog(&options, true, options.AllowFiles, options.AllowDirectories)
|
||||
return f.openDialog(&options, true, true, false)
|
||||
}
|
||||
|
||||
// SaveFileDialog prompts the user to select a file
|
||||
|
||||
@@ -5,7 +5,7 @@ package darwin
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -x objective-c
|
||||
#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit -framework UniformTypeIdentifiers
|
||||
#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Application.h"
|
||||
#import "WailsContext.h"
|
||||
|
||||
@@ -32,7 +32,8 @@ void processCallback(int callbackID) {
|
||||
void processURLRequest(void *ctx, const char* url) {
|
||||
NSLog(@"processURLRequest called");
|
||||
const char myByteArray[] = { 0x3c,0x68,0x31,0x3e,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,0x72,0x6c,0x64,0x21,0x3c,0x2f,0x68,0x31,0x3e };
|
||||
ProcessURLResponse(ctx, url, "text/html", (void*)myByteArray, 21);
|
||||
// void *inctx, const char *url, int statusCode, const char *contentType, void* data, int datalength
|
||||
ProcessURLResponse(ctx, url, 200, "text/html", (void*)myByteArray, 21);
|
||||
}
|
||||
|
||||
unsigned char _Users_username_Pictures_SaltBae_png[] = {
|
||||
|
||||
@@ -83,7 +83,7 @@ extern void processMessage(char*);
|
||||
|
||||
static void sendMessageToBackend(WebKitUserContentManager *contentManager,
|
||||
WebKitJavascriptResult *result,
|
||||
void*)
|
||||
void* data)
|
||||
{
|
||||
#if WEBKIT_MAJOR_VERSION >= 2 && WEBKIT_MINOR_VERSION >= 22
|
||||
JSCValue *value = webkit_javascript_result_get_js_value(result);
|
||||
@@ -145,7 +145,7 @@ void connectButtons(void* webview) {
|
||||
extern void processURLRequest(WebKitURISchemeRequest *request);
|
||||
|
||||
// This is called when the close button on the window is pressed
|
||||
gboolean close_button_pressed(GtkWidget *widget, GdkEvent *event, void*)
|
||||
gboolean close_button_pressed(GtkWidget *widget, GdkEvent *event, void* data)
|
||||
{
|
||||
processMessage("Q");
|
||||
return FALSE;
|
||||
|
||||
@@ -57,10 +57,10 @@ func NewWindow(parent winc.Controller, appoptions *options.App) *Window {
|
||||
result.SetText(appoptions.Title)
|
||||
if appoptions.Frameless == false && !appoptions.Fullscreen {
|
||||
result.EnableMaxButton(!appoptions.DisableResize)
|
||||
result.EnableSizable(!appoptions.DisableResize)
|
||||
result.SetMinSize(appoptions.MinWidth, appoptions.MinHeight)
|
||||
result.SetMaxSize(appoptions.MaxWidth, appoptions.MaxHeight)
|
||||
}
|
||||
result.EnableSizable(!appoptions.DisableResize)
|
||||
|
||||
if appoptions.Windows != nil {
|
||||
if appoptions.Windows.WindowIsTranslucent {
|
||||
|
||||
@@ -19,8 +19,6 @@ type OpenDialogOptions struct {
|
||||
DefaultFilename string
|
||||
Title string
|
||||
Filters []FileFilter
|
||||
AllowFiles bool
|
||||
AllowDirectories bool
|
||||
ShowHiddenFiles bool
|
||||
CanCreateDirectories bool
|
||||
ResolvesAliases bool
|
||||
|
||||
@@ -152,7 +152,7 @@ export function EventsEmit(eventName) {
|
||||
|
||||
export function EventsOff(eventName) {
|
||||
// Remove local listeners
|
||||
eventListeners.delete(eventName);
|
||||
delete eventListeners[eventName];
|
||||
|
||||
// Notify Go listeners
|
||||
window.WailsInvoke('EX' + eventName);
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,14 +1,14 @@
|
||||
interface Position {
|
||||
export interface Position {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
interface Size {
|
||||
export interface Size {
|
||||
w: number;
|
||||
h: number;
|
||||
}
|
||||
|
||||
interface RGBA {
|
||||
export interface RGBA {
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
@@ -16,7 +16,7 @@ interface RGBA {
|
||||
}
|
||||
|
||||
|
||||
interface runtime {
|
||||
export interface runtime {
|
||||
EventsEmit(eventName: string, data?: any): void;
|
||||
|
||||
EventsOn(eventName: string, callback: (data?: any) => void): void;
|
||||
@@ -83,5 +83,3 @@ declare global {
|
||||
runtime: runtime;
|
||||
}
|
||||
}
|
||||
|
||||
export { };
|
||||
|
||||
@@ -33,7 +33,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -97,7 +96,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -139,7 +137,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -180,7 +177,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -222,7 +218,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -264,7 +259,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -308,7 +302,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -353,7 +346,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -456,7 +448,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -498,7 +489,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -540,7 +530,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@@ -585,7 +574,6 @@ require (
|
||||
github.com/leaanthony/gosod v1.0.3 // indirect
|
||||
github.com/leaanthony/slicer v1.5.0 // indirect
|
||||
github.com/leaanthony/typescriptify-golang-structs v0.1.7 // indirect
|
||||
github.com/leaanthony/webview2runtime v1.1.0 // indirect
|
||||
github.com/leaanthony/winc v0.0.0-20210921073452-54963136bf18 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/leaanthony/webview2runtime"
|
||||
"github.com/leaanthony/go-webview2/webviewloader"
|
||||
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
|
||||
"github.com/wailsapp/wails/v2/internal/system/packagemanager"
|
||||
)
|
||||
@@ -28,11 +28,7 @@ func (i *Info) discover() error {
|
||||
|
||||
func checkWebView2() *packagemanager.Dependancy {
|
||||
|
||||
info := webview2runtime.GetInstalledVersion()
|
||||
version := ""
|
||||
if info != nil {
|
||||
version = info.Version
|
||||
}
|
||||
version, _ := webviewloader.GetInstalledVersion()
|
||||
installed := version != ""
|
||||
|
||||
return &packagemanager.Dependancy{
|
||||
|
||||
BIN
v2/internal/webview2runtime/MicrosoftEdgeWebview2Setup.exe
Normal file
BIN
v2/internal/webview2runtime/MicrosoftEdgeWebview2Setup.exe
Normal file
Binary file not shown.
232
v2/internal/webview2runtime/sudo_mattn.go
Normal file
232
v2/internal/webview2runtime/sudo_mattn.go
Normal file
@@ -0,0 +1,232 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
// Original File (c) 2017 Yasuhiro Matsumoto: https://github.com/mattn/sudo/blob/master/win32.go
|
||||
// License: https://github.com/mattn/sudo/blob/master/LICENSE
|
||||
|
||||
package webview2runtime
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
modshell32 = syscall.NewLazyDLL("shell32.dll")
|
||||
procShellExecuteEx = modshell32.NewProc("ShellExecuteExW")
|
||||
)
|
||||
|
||||
const (
|
||||
_SEE_MASK_DEFAULT = 0x00000000
|
||||
_SEE_MASK_CLASSNAME = 0x00000001
|
||||
_SEE_MASK_CLASSKEY = 0x00000003
|
||||
_SEE_MASK_IDLIST = 0x00000004
|
||||
_SEE_MASK_INVOKEIDLIST = 0x0000000C
|
||||
_SEE_MASK_ICON = 0x00000010
|
||||
_SEE_MASK_HOTKEY = 0x00000020
|
||||
_SEE_MASK_NOCLOSEPROCESS = 0x00000040
|
||||
_SEE_MASK_CONNECTNETDRV = 0x00000080
|
||||
_SEE_MASK_NOASYNC = 0x00000100
|
||||
_SEE_MASK_FLAG_DDEWAIT = 0x00000100
|
||||
_SEE_MASK_DOENVSUBST = 0x00000200
|
||||
_SEE_MASK_FLAG_NO_UI = 0x00000400
|
||||
_SEE_MASK_UNICODE = 0x00004000
|
||||
_SEE_MASK_NO_CONSOLE = 0x00008000
|
||||
_SEE_MASK_ASYNCOK = 0x00100000
|
||||
_SEE_MASK_NOQUERYCLASSSTORE = 0x01000000
|
||||
_SEE_MASK_HMONITOR = 0x00200000
|
||||
_SEE_MASK_NOZONECHECKS = 0x00800000
|
||||
_SEE_MASK_WAITFORINPUTIDLE = 0x02000000
|
||||
_SEE_MASK_FLAG_LOG_USAGE = 0x04000000
|
||||
_SEE_MASK_FLAG_HINST_IS_SITE = 0x08000000
|
||||
)
|
||||
|
||||
const (
|
||||
_ERROR_BAD_FORMAT = 11
|
||||
)
|
||||
|
||||
const (
|
||||
_SE_ERR_FNF = 2
|
||||
_SE_ERR_PNF = 3
|
||||
_SE_ERR_ACCESSDENIED = 5
|
||||
_SE_ERR_OOM = 8
|
||||
_SE_ERR_DLLNOTFOUND = 32
|
||||
_SE_ERR_SHARE = 26
|
||||
_SE_ERR_ASSOCINCOMPLETE = 27
|
||||
_SE_ERR_DDETIMEOUT = 28
|
||||
_SE_ERR_DDEFAIL = 29
|
||||
_SE_ERR_DDEBUSY = 30
|
||||
_SE_ERR_NOASSOC = 31
|
||||
)
|
||||
|
||||
type (
|
||||
dword uint32
|
||||
hinstance syscall.Handle
|
||||
hkey syscall.Handle
|
||||
hwnd syscall.Handle
|
||||
ulong uint32
|
||||
lpctstr uintptr
|
||||
lpvoid uintptr
|
||||
)
|
||||
|
||||
// SHELLEXECUTEINFO struct
|
||||
type _SHELLEXECUTEINFO struct {
|
||||
cbSize dword
|
||||
fMask ulong
|
||||
hwnd hwnd
|
||||
lpVerb lpctstr
|
||||
lpFile lpctstr
|
||||
lpParameters lpctstr
|
||||
lpDirectory lpctstr
|
||||
nShow int
|
||||
hInstApp hinstance
|
||||
lpIDList lpvoid
|
||||
lpClass lpctstr
|
||||
hkeyClass hkey
|
||||
dwHotKey dword
|
||||
hIconOrMonitor syscall.Handle
|
||||
hProcess syscall.Handle
|
||||
}
|
||||
|
||||
// ShellExecuteAndWait is version of ShellExecuteEx which want process
|
||||
func ShellExecuteAndWait(hwnd hwnd, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
|
||||
var lpctstrVerb, lpctstrParameters, lpctstrDirectory, lpctstrFile lpctstr
|
||||
var err error
|
||||
if len(lpOperation) != 0 {
|
||||
lpctstrVerb, err = toUTF16(lpOperation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(lpParameters) != 0 {
|
||||
lpctstrParameters, err = toUTF16(lpParameters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(lpDirectory) != 0 {
|
||||
lpctstrDirectory, err = toUTF16(lpDirectory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(lpDirectory) != 0 {
|
||||
lpctstrFile, err = toUTF16(lpFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
i := &_SHELLEXECUTEINFO{
|
||||
fMask: _SEE_MASK_NOCLOSEPROCESS,
|
||||
hwnd: hwnd,
|
||||
lpVerb: lpctstrVerb,
|
||||
lpFile: lpctstrFile,
|
||||
lpParameters: lpctstrParameters,
|
||||
lpDirectory: lpctstrDirectory,
|
||||
nShow: nShowCmd,
|
||||
}
|
||||
i.cbSize = dword(unsafe.Sizeof(*i))
|
||||
return ShellExecuteEx(i)
|
||||
}
|
||||
|
||||
func toUTF16(lpOperation string) (lpctstr, error) {
|
||||
result, err := syscall.UTF16PtrFromString(lpOperation)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return lpctstr(unsafe.Pointer(result)), nil
|
||||
}
|
||||
|
||||
// ShellExecuteNoWait is version of ShellExecuteEx which don't want process
|
||||
func ShellExecuteNowait(hwnd hwnd, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
|
||||
var lpctstrVerb, lpctstrParameters, lpctstrDirectory, lpctstrFile lpctstr
|
||||
var err error
|
||||
if len(lpOperation) != 0 {
|
||||
lpctstrVerb, err = toUTF16(lpOperation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(lpParameters) != 0 {
|
||||
lpctstrParameters, err = toUTF16(lpParameters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(lpDirectory) != 0 {
|
||||
lpctstrDirectory, err = toUTF16(lpDirectory)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(lpDirectory) != 0 {
|
||||
lpctstrFile, err = toUTF16(lpFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
i := &_SHELLEXECUTEINFO{
|
||||
fMask: _SEE_MASK_DEFAULT,
|
||||
hwnd: hwnd,
|
||||
lpVerb: lpctstrVerb,
|
||||
lpFile: lpctstrFile,
|
||||
lpParameters: lpctstrParameters,
|
||||
lpDirectory: lpctstrDirectory,
|
||||
nShow: nShowCmd,
|
||||
}
|
||||
i.cbSize = dword(unsafe.Sizeof(*i))
|
||||
return ShellExecuteEx(i)
|
||||
}
|
||||
|
||||
// ShellExecuteEx is Windows API
|
||||
func ShellExecuteEx(pExecInfo *_SHELLEXECUTEINFO) error {
|
||||
ret, _, _ := procShellExecuteEx.Call(uintptr(unsafe.Pointer(pExecInfo)))
|
||||
if ret == 1 && pExecInfo.fMask&_SEE_MASK_NOCLOSEPROCESS != 0 {
|
||||
s, e := syscall.WaitForSingleObject(pExecInfo.hProcess, syscall.INFINITE)
|
||||
switch s {
|
||||
case syscall.WAIT_OBJECT_0:
|
||||
break
|
||||
case syscall.WAIT_FAILED:
|
||||
return os.NewSyscallError("WaitForSingleObject", e)
|
||||
default:
|
||||
return errors.New("Unexpected result from WaitForSingleObject")
|
||||
}
|
||||
}
|
||||
errorMsg := ""
|
||||
if pExecInfo.hInstApp != 0 && pExecInfo.hInstApp <= 32 {
|
||||
switch int(pExecInfo.hInstApp) {
|
||||
case _SE_ERR_FNF:
|
||||
errorMsg = "The specified file was not found"
|
||||
case _SE_ERR_PNF:
|
||||
errorMsg = "The specified path was not found"
|
||||
case _ERROR_BAD_FORMAT:
|
||||
errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)"
|
||||
case _SE_ERR_ACCESSDENIED:
|
||||
errorMsg = "The operating system denied access to the specified file"
|
||||
case _SE_ERR_ASSOCINCOMPLETE:
|
||||
errorMsg = "The file name association is incomplete or invalid"
|
||||
case _SE_ERR_DDEBUSY:
|
||||
errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed"
|
||||
case _SE_ERR_DDEFAIL:
|
||||
errorMsg = "The DDE transaction failed"
|
||||
case _SE_ERR_DDETIMEOUT:
|
||||
errorMsg = "The DDE transaction could not be completed because the request timed out"
|
||||
case _SE_ERR_DLLNOTFOUND:
|
||||
errorMsg = "The specified DLL was not found"
|
||||
case _SE_ERR_NOASSOC:
|
||||
errorMsg = "There is no application associated with the given file name extension"
|
||||
case _SE_ERR_OOM:
|
||||
errorMsg = "There was not enough memory to complete the operation"
|
||||
case _SE_ERR_SHARE:
|
||||
errorMsg = "A sharing violation occurred"
|
||||
default:
|
||||
errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", pExecInfo.hInstApp)
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return errors.New(errorMsg)
|
||||
}
|
||||
168
v2/internal/webview2runtime/webview2runtime.go
Normal file
168
v2/internal/webview2runtime/webview2runtime.go
Normal file
@@ -0,0 +1,168 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package webview2runtime
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//go:embed MicrosoftEdgeWebview2Setup.exe
|
||||
var setupexe []byte
|
||||
|
||||
// Info contains all the information about an installation of the webview2 runtime.
|
||||
type Info struct {
|
||||
Location string
|
||||
Name string
|
||||
Version string
|
||||
SilentUninstall string
|
||||
}
|
||||
|
||||
// IsOlderThan returns true if the installed version is older than the given required version.
|
||||
// Returns error if something goes wrong.
|
||||
func (i *Info) IsOlderThan(requiredVersion string) (bool, error) {
|
||||
var mod = syscall.NewLazyDLL("WebView2Loader.dll")
|
||||
var CompareBrowserVersions = mod.NewProc("CompareBrowserVersions")
|
||||
v1, err := syscall.UTF16PtrFromString(i.Version)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v2, err := syscall.UTF16PtrFromString(requiredVersion)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
var result int = 9
|
||||
_, _, err = CompareBrowserVersions.Call(uintptr(unsafe.Pointer(v1)), uintptr(unsafe.Pointer(v2)), uintptr(unsafe.Pointer(&result)))
|
||||
if result < -1 || result > 1 {
|
||||
return false, err
|
||||
}
|
||||
return result == -1, nil
|
||||
}
|
||||
|
||||
func downloadBootstrapper() (string, error) {
|
||||
bootstrapperURL := `https://go.microsoft.com/fwlink/p/?LinkId=2124703`
|
||||
installer := filepath.Join(os.TempDir(), `MicrosoftEdgeWebview2Setup.exe`)
|
||||
|
||||
// Download installer
|
||||
out, err := os.Create(installer)
|
||||
defer out.Close()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
resp, err := http.Get(bootstrapperURL)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
err = out.Close()
|
||||
return "", err
|
||||
}
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return installer, nil
|
||||
}
|
||||
|
||||
// InstallUsingEmbeddedBootstrapper will download the bootstrapper from Microsoft and run it to install
|
||||
// the latest version of the runtime.
|
||||
// Returns true if the installer ran successfully.
|
||||
// Returns an error if something goes wrong
|
||||
func InstallUsingEmbeddedBootstrapper() (bool, error) {
|
||||
|
||||
installer := filepath.Join(os.TempDir(), `MicrosoftEdgeWebview2Setup.exe`)
|
||||
err := os.WriteFile(installer, setupexe, 0755)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
result, err := runInstaller(installer)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, os.Remove(installer)
|
||||
|
||||
}
|
||||
|
||||
// InstallUsingBootstrapper will extract the embedded bootstrapper from Microsoft and run it to install
|
||||
// the latest version of the runtime.
|
||||
// Returns true if the installer ran successfully.
|
||||
// Returns an error if something goes wrong
|
||||
func InstallUsingBootstrapper() (bool, error) {
|
||||
|
||||
installer, err := downloadBootstrapper()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
result, err := runInstaller(installer)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, os.Remove(installer)
|
||||
|
||||
}
|
||||
|
||||
func runInstaller(installer string) (bool, error) {
|
||||
err := ShellExecuteAndWait(0, "runas", installer, "", os.Getenv("TMP"), syscall.SW_NORMAL)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Confirm will prompt the user with a message and OK / CANCEL buttons.
|
||||
// Returns true if OK is selected by the user.
|
||||
// Returns an error if something went wrong.
|
||||
func Confirm(caption string, title string) (bool, error) {
|
||||
var flags uint = 0x00000001 // MB_OKCANCEL
|
||||
result, err := MessageBox(caption, title, flags)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return result == 1, nil
|
||||
}
|
||||
|
||||
// Error will an error message to the user.
|
||||
// Returns an error if something went wrong.
|
||||
func Error(caption string, title string) error {
|
||||
var flags uint = 0x00000010 // MB_ICONERROR
|
||||
_, err := MessageBox(caption, title, flags)
|
||||
return err
|
||||
}
|
||||
|
||||
// MessageBox prompts the user with the given caption and title.
|
||||
// Flags may be provided to customise the dialog.
|
||||
// Returns an error if something went wrong.
|
||||
func MessageBox(caption string, title string, flags uint) (int, error) {
|
||||
captionUTF16, err := syscall.UTF16PtrFromString(caption)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
titleUTF16, err := syscall.UTF16PtrFromString(title)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call(
|
||||
uintptr(0),
|
||||
uintptr(unsafe.Pointer(captionUTF16)),
|
||||
uintptr(unsafe.Pointer(titleUTF16)),
|
||||
uintptr(flags))
|
||||
|
||||
return int(ret), nil
|
||||
}
|
||||
|
||||
// OpenInstallerDownloadWebpage will open the browser on the WebView2 download page
|
||||
func OpenInstallerDownloadWebpage() error {
|
||||
cmd := exec.Command("rundll32", "url.dll,FileProtocolHandler", "https://developer.microsoft.com/en-us/microsoft-edge/webview2/")
|
||||
return cmd.Run()
|
||||
}
|
||||
@@ -7,8 +7,11 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/system"
|
||||
|
||||
"github.com/leaanthony/gosod"
|
||||
wailsRuntime "github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/runtime/wrapper"
|
||||
@@ -195,22 +198,24 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
||||
|
||||
verbose := options.Verbosity == VERBOSE
|
||||
// Run go mod tidy first
|
||||
cmd := exec.Command(options.Compiler, "mod", "tidy")
|
||||
cmd.Stderr = os.Stderr
|
||||
if verbose {
|
||||
println("")
|
||||
cmd.Stdout = os.Stdout
|
||||
}
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
if !options.SkipModTidy {
|
||||
cmd := exec.Command(options.Compiler, "mod", "tidy")
|
||||
cmd.Stderr = os.Stderr
|
||||
if verbose {
|
||||
println("")
|
||||
cmd.Stdout = os.Stdout
|
||||
}
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Default go build command
|
||||
commands := slicer.String([]string{"build"})
|
||||
|
||||
// Add better debugging flags
|
||||
if options.Mode == Dev {
|
||||
if options.Mode == Dev || options.Mode == Debug {
|
||||
commands.Add("-gcflags")
|
||||
commands.Add(`"all=-N -l"`)
|
||||
}
|
||||
@@ -228,7 +233,7 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
||||
tags.Add(options.WebView2Strategy)
|
||||
}
|
||||
|
||||
if options.Mode == Production {
|
||||
if options.Mode == Production || options.Mode == Debug {
|
||||
tags.Add("production")
|
||||
}
|
||||
|
||||
@@ -277,7 +282,7 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
||||
options.CompiledBinary = compiledBinary
|
||||
|
||||
// Create the command
|
||||
cmd = exec.Command(options.Compiler, commands.AsSlice()...)
|
||||
cmd := exec.Command(options.Compiler, commands.AsSlice()...)
|
||||
cmd.Stderr = os.Stderr
|
||||
if verbose {
|
||||
println(" Build command:", commands.Join(" "))
|
||||
@@ -319,11 +324,26 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
||||
return "1"
|
||||
})
|
||||
if options.Platform == "darwin" {
|
||||
// Determine version so we can link to newer frameworks
|
||||
// Why doesn't CGO have this option?!?!
|
||||
info, err := system.GetInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
versionSplit := strings.Split(info.OS.Version, ".")
|
||||
majorVersion, err := strconv.Atoi(versionSplit[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
addUTIFramework := majorVersion >= 11
|
||||
// Set the minimum Mac SDK to 10.13
|
||||
cmd.Env = upsertEnv(cmd.Env, "CGO_LDFLAGS", func(v string) string {
|
||||
if v != "" {
|
||||
v += " "
|
||||
}
|
||||
if addUTIFramework {
|
||||
v += "-framework UniformTypeIdentifiers "
|
||||
}
|
||||
v += "-mmacosx-version-min=10.13"
|
||||
|
||||
return v
|
||||
|
||||
@@ -23,6 +23,8 @@ const (
|
||||
Dev Mode = iota
|
||||
// Production mode
|
||||
Production
|
||||
// Debug build
|
||||
Debug
|
||||
)
|
||||
|
||||
// Options contains all the build options as well as the project data
|
||||
@@ -37,6 +39,7 @@ type Options struct {
|
||||
Platform string // The platform to build for
|
||||
Arch string // The architecture to build for
|
||||
Compiler string // The compiler command to use
|
||||
SkipModTidy bool // Skip mod tidy before compile
|
||||
IgnoreFrontend bool // Indicates if the frontend does not need building
|
||||
OutputFile string // Override the output filename
|
||||
BuildDirectory string // Directory to use for building the application
|
||||
|
||||
@@ -2,7 +2,9 @@ package runtime
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"github.com/wailsapp/wails/v2/internal/fs"
|
||||
)
|
||||
|
||||
// FileFilter defines a filter for dialog boxes
|
||||
@@ -29,24 +31,44 @@ type MessageDialogOptions = frontend.MessageDialogOptions
|
||||
// OpenDirectoryDialog prompts the user to select a directory
|
||||
func OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {
|
||||
appFrontend := getFrontend(ctx)
|
||||
if dialogOptions.DefaultDirectory != "" {
|
||||
if !fs.DirExists(dialogOptions.DefaultDirectory) {
|
||||
return "", fmt.Errorf("default directory '%s' does not exist", dialogOptions.DefaultDirectory)
|
||||
}
|
||||
}
|
||||
return appFrontend.OpenDirectoryDialog(dialogOptions)
|
||||
}
|
||||
|
||||
// OpenFileDialog prompts the user to select a file
|
||||
func OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error) {
|
||||
appFrontend := getFrontend(ctx)
|
||||
if dialogOptions.DefaultDirectory != "" {
|
||||
if !fs.DirExists(dialogOptions.DefaultDirectory) {
|
||||
return "", fmt.Errorf("default directory '%s' does not exist", dialogOptions.DefaultDirectory)
|
||||
}
|
||||
}
|
||||
return appFrontend.OpenFileDialog(dialogOptions)
|
||||
}
|
||||
|
||||
// OpenMultipleFilesDialog prompts the user to select a file
|
||||
func OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error) {
|
||||
appFrontend := getFrontend(ctx)
|
||||
if dialogOptions.DefaultDirectory != "" {
|
||||
if !fs.DirExists(dialogOptions.DefaultDirectory) {
|
||||
return nil, fmt.Errorf("default directory '%s' does not exist", dialogOptions.DefaultDirectory)
|
||||
}
|
||||
}
|
||||
return appFrontend.OpenMultipleFilesDialog(dialogOptions)
|
||||
}
|
||||
|
||||
// SaveFileDialog prompts the user to select a file
|
||||
func SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error) {
|
||||
appFrontend := getFrontend(ctx)
|
||||
if dialogOptions.DefaultDirectory != "" {
|
||||
if !fs.DirExists(dialogOptions.DefaultDirectory) {
|
||||
return "", fmt.Errorf("default directory '%s' does not exist", dialogOptions.DefaultDirectory)
|
||||
}
|
||||
}
|
||||
return appFrontend.SaveFileDialog(dialogOptions)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@ import (
|
||||
goruntime "runtime"
|
||||
)
|
||||
|
||||
const contextError = `An invalid context was passed. This method requires the specific context given in the lifecycle hooks:
|
||||
https://wails.io/docs/reference/runtime/intro`
|
||||
|
||||
func getFrontend(ctx context.Context) frontend.Frontend {
|
||||
if ctx == nil {
|
||||
pc, _, _, _ := goruntime.Caller(1)
|
||||
@@ -20,7 +23,7 @@ func getFrontend(ctx context.Context) frontend.Frontend {
|
||||
}
|
||||
pc, _, _, _ := goruntime.Caller(1)
|
||||
funcName := goruntime.FuncForPC(pc).Name()
|
||||
log.Fatalf("cannot call '%s': Application not initialised", funcName)
|
||||
log.Fatalf("cannot call '%s': %s", funcName, contextError)
|
||||
return nil
|
||||
}
|
||||
func getLogger(ctx context.Context) *logger.Logger {
|
||||
@@ -35,7 +38,7 @@ func getLogger(ctx context.Context) *logger.Logger {
|
||||
}
|
||||
pc, _, _, _ := goruntime.Caller(1)
|
||||
funcName := goruntime.FuncForPC(pc).Name()
|
||||
log.Fatalf("cannot call '%s': Application not initialised", funcName)
|
||||
log.Fatalf("cannot call '%s': %s", funcName, contextError)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -51,7 +54,7 @@ func getEvents(ctx context.Context) frontend.Events {
|
||||
}
|
||||
pc, _, _, _ := goruntime.Caller(1)
|
||||
funcName := goruntime.FuncForPC(pc).Name()
|
||||
log.Fatalf("cannot call '%s': Application not initialised", funcName)
|
||||
log.Fatalf("cannot call '%s': %s", funcName, contextError)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
19
website/docs/community/showcase/riftshare.mdx
Normal file
19
website/docs/community/showcase/riftshare.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
# RiftShare
|
||||
|
||||
<p style={{"text-align": "center"}}>
|
||||
<img src="/img/showcase/riftshare-main.webp"></img><br/>
|
||||
</p>
|
||||
|
||||
Easy, Secure, and Free file sharing for everyone. Learn more at [Riftshare.app](https://riftshare.app)
|
||||
|
||||
## Features
|
||||
|
||||
* Easy secure file sharing between computers both in the local network and through the internet
|
||||
* Supports sending files or directories securely through the [magic wormhole protocol](https://magic-wormhole.readthedocs.io/en/latest/)
|
||||
* Compatible with all other apps using magic wormhole (magic-wormhole or wormhole-william CLI, wormhole-gui, etc.)
|
||||
* Automatic zipping of multiple selected files to send at once
|
||||
* Full animations, progress bar, and cancellation support for sending and receiving
|
||||
* Native OS File Selection
|
||||
* Open files in one click once received
|
||||
* Auto Update - don't worry about having the latest release!
|
||||
@@ -28,3 +28,12 @@ Example: `wails init -n "Your Project Name" -t https://github.com/misitebao/wail
|
||||
## Angular
|
||||
|
||||
- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - Angular with TypeScript, Sass, Hot-Reload, Code-Splitting and i18n
|
||||
|
||||
## React
|
||||
|
||||
- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - A template using reactjs
|
||||
- [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development
|
||||
|
||||
## Svelte
|
||||
|
||||
- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - A template using Svelte
|
||||
|
||||
@@ -14,6 +14,13 @@ sidebar_position: 99
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
<p align="center">
|
||||
<a href="https://www.easywebadv.it/" style="width:100px;">
|
||||
<img src="/img/easyweb.png" width="200"/>
|
||||
</a>
|
||||
</p>
|
||||
<br/>
|
||||
<br/>
|
||||
<a href="https://github.com/sponsors/leaanthony" style="width:100px;">
|
||||
<img src="/img/silver%20sponsor.png" width="100"/>
|
||||
</a>
|
||||
@@ -84,9 +91,6 @@ sidebar_position: 99
|
||||
<a href="https://github.com/ilgityildirim" style="width:50px">
|
||||
<img src="https://github.com/ilgityildirim.png?size=50" width="50"/>
|
||||
</a>
|
||||
<a href="https://github.com/ondoki" style="width:65px">
|
||||
<img src="https://github.com/ondoki.png?size=65" width="65"/>
|
||||
</a>
|
||||
<a href="https://github.com/questrail" style="width:50px">
|
||||
<img src="https://github.com/questrail.png?size=50" width="50"/>
|
||||
</a>
|
||||
@@ -96,6 +100,18 @@ sidebar_position: 99
|
||||
<a href="https://github.com/taigrr" style="width:45px">
|
||||
<img src="https://github.com/taigrr.png?size=45" width="45"/>
|
||||
</a>
|
||||
<a href="https://github.com/charlie-dee" style="width:55px">
|
||||
<img src="https://github.com/charlie-dee.png?size=55" width="55"/>
|
||||
</a>
|
||||
<a href="https://github.com/EdenNetworkItalia" style="width:65px">
|
||||
<img src="https://github.com/EdenNetworkItalia.png?size=65" width="65"/>
|
||||
</a>
|
||||
<a href="https://github.com/michaelolson1996" style="width:55px">
|
||||
<img src="https://github.com/michaelolson1996.png?size=55" width="55"/>
|
||||
</a>
|
||||
<a href="https://github.com/GargantuaX" style="width:45px">
|
||||
<img src="https://github.com/GargantuaX.png?size=45" width="45"/>
|
||||
</a>
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -66,6 +66,8 @@ A list of community maintained templates can be found [here](/docs/community/tem
|
||||
| -upxflags | Flags to pass to upx | |
|
||||
| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 |
|
||||
| -webview2 | WebView2 installer strategy: download,embed,browser,error | download |
|
||||
| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | |
|
||||
| -debug | Retains debug information in the application | false |
|
||||
|
||||
For a detailed description of the `webview2` flag, please refer to the [Windows](/docs/guides/windows) Guide.
|
||||
|
||||
@@ -82,6 +84,12 @@ Example:
|
||||
|
||||
:::
|
||||
|
||||
:::info UPX on Windows
|
||||
|
||||
Some Antivirus vendors false positively mark `upx` compressed binaries as virus, see [issue](https://github.com/upx/upx/issues/437).
|
||||
|
||||
:::
|
||||
|
||||
## doctor
|
||||
|
||||
`wails doctor` will run diagnostics to ensure that your system is ready for development.
|
||||
|
||||
@@ -284,6 +284,7 @@ func (b *App) beforeClose(ctx context.Context) (prevent bool) {
|
||||
return false
|
||||
}
|
||||
return dialog != "Yes"
|
||||
}
|
||||
```
|
||||
|
||||
### WindowStartState
|
||||
|
||||
@@ -69,8 +69,6 @@ type OpenDialogOptions struct {
|
||||
DefaultFilename string
|
||||
Title string
|
||||
Filters []FileFilter
|
||||
AllowFiles bool
|
||||
AllowDirectories bool
|
||||
ShowHiddenFiles bool
|
||||
CanCreateDirectories bool
|
||||
ResolvesAliases bool
|
||||
@@ -83,8 +81,6 @@ type OpenDialogOptions struct {
|
||||
| DefaultFilename | The default filename | ✅ | ✅ |
|
||||
| Title | Title for the dialog | ✅ | ✅ |
|
||||
| [Filters](#filefilter) | A list of file filters | ✅ | ✅ |
|
||||
| AllowFiles | Allow files to be selected | | ✅ |
|
||||
| AllowDirectories | Allow directories to be selected | | ✅ |
|
||||
| ShowHiddenFiles | Show files hidden by the system | | ✅ |
|
||||
| CanCreateDirectories | Allow user to create directories | | ✅ |
|
||||
| ResolvesAliases | If true, returns the file not the alias | | ✅ |
|
||||
|
||||
@@ -8,7 +8,7 @@ The runtime is a library that provides utility methods for your application. The
|
||||
and the aim is to try and keep them at parity where possible.
|
||||
|
||||
The Go Runtime is available through importing `github.com/wailsapp/wails/v2/pkg/runtime`. All methods in this package
|
||||
take a context as the first parameter. This context can be obtained from the [OnStartup](/docs/reference/options#onstartup)
|
||||
take a context as the first parameter. This context should be obtained from the [OnStartup](/docs/reference/options#onstartup)
|
||||
or [OnDomReady](/docs/reference/options#ondomready) hooks.
|
||||
|
||||
:::info Note
|
||||
|
||||
@@ -27,3 +27,13 @@ sidebar_position: 1
|
||||
## Angular
|
||||
|
||||
- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - 带有 TypeScript, Sass, 热重载, 代码拆分和 i18n 的 Angular
|
||||
|
||||
## React
|
||||
|
||||
- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - 基于 reactjs 的模板
|
||||
- [wails-react-template](https://github.com/flin7/wails-react-template) - 基于 React 并支持实时开发模式的轻量级模板
|
||||
|
||||
## Svelte
|
||||
|
||||
- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - 基于 Svelte 的模板
|
||||
|
||||
|
||||
@@ -96,6 +96,9 @@ sidebar_position: 99
|
||||
<a href="https://github.com/taigrr" style="width:45px">
|
||||
<img src="https://github.com/taigrr.png?size=45" width="45"/>
|
||||
</a>
|
||||
<a href="https://github.com/charlie-dee" style="width:55px">
|
||||
<img src="https://github.com/charlie-dee.png?size=55" width="55"/>
|
||||
</a>
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -63,8 +63,6 @@ type OpenDialogOptions struct {
|
||||
DefaultFilename string
|
||||
Title string
|
||||
Filters []FileFilter
|
||||
AllowFiles bool
|
||||
AllowDirectories bool
|
||||
ShowHiddenFiles bool
|
||||
CanCreateDirectories bool
|
||||
ResolvesAliases bool
|
||||
@@ -78,8 +76,6 @@ type OpenDialogOptions struct {
|
||||
| DefaultFilename | 默认文件名 | ✅ | ✅ |
|
||||
| Title | 对话框的标题 | ✅ | ✅ |
|
||||
| [Filters](#文件过滤) | 文件过滤器列表 | ✅ | ✅ |
|
||||
| AllowFiles | 允许选择文件 | | ✅ |
|
||||
| AllowDirectories | 允许选择目录 | | ✅ |
|
||||
| ShowHiddenFiles | 显示系统隐藏的文件 | | ✅ |
|
||||
| CanCreateDirectories | 允许用户创建目录 | | ✅ |
|
||||
| ResolvesAliases | 如果为 true,则返回文件而不是别名 | | ✅ |
|
||||
|
||||
BIN
website/static/img/easyweb.png
Normal file
BIN
website/static/img/easyweb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
BIN
website/static/img/showcase/riftshare-main.webp
Normal file
BIN
website/static/img/showcase/riftshare-main.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Reference in New Issue
Block a user