mirror of
https://github.com/taigrr/wails.git
synced 2026-04-14 02:48:21 -07:00
Compare commits
31 Commits
Make-Serve
...
ignore-pac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ffb517183 | ||
|
|
27f852ac6a | ||
|
|
20c0b48634 | ||
|
|
6cf01b4239 | ||
|
|
3ae88f8822 | ||
|
|
5994eb605f | ||
|
|
9694dc57aa | ||
|
|
b5b78fddee | ||
|
|
c905185467 | ||
|
|
47ca7879cd | ||
|
|
6202b3bf3e | ||
|
|
ea94c2de1f | ||
|
|
eb0d4bc42f | ||
|
|
b323c3db20 | ||
|
|
1670ac6567 | ||
|
|
c941176018 | ||
|
|
a060d9dcc0 | ||
|
|
ba208dce44 | ||
|
|
9bbac46b3f | ||
|
|
d8c591e64c | ||
|
|
2c28a8f550 | ||
|
|
d6c5586159 | ||
|
|
08a7893b1d | ||
|
|
fa6cf17079 | ||
|
|
fe2a20f92a | ||
|
|
b713d57168 | ||
|
|
17ca06693e | ||
|
|
243d738d64 | ||
|
|
f0d8ce99a1 | ||
|
|
a51e127309 | ||
|
|
9393b08c3f |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -14,4 +14,5 @@
|
|||||||
examples/**/example*
|
examples/**/example*
|
||||||
!examples/**/*.*
|
!examples/**/*.*
|
||||||
cmd/wails/wails
|
cmd/wails/wails
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
tmp
|
||||||
10
app.go
10
app.go
@@ -6,8 +6,8 @@ import (
|
|||||||
|
|
||||||
// -------------------------------- Compile time Flags ------------------------------
|
// -------------------------------- Compile time Flags ------------------------------
|
||||||
|
|
||||||
// DebugMode indicates if we are in debug Mode
|
// BuildMode indicates what mode we are in
|
||||||
var DebugMode = "true"
|
var BuildMode = cmd.BuildModeProd
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
|
|||||||
result.config = appconfig
|
result.config = appconfig
|
||||||
|
|
||||||
// Set up the CLI if not in release mode
|
// Set up the CLI if not in release mode
|
||||||
if DebugMode == "true" {
|
if BuildMode != cmd.BuildModeProd {
|
||||||
result.cli = result.setupCli()
|
result.cli = result.setupCli()
|
||||||
} else {
|
} else {
|
||||||
// Disable Inspector in release mode
|
// Disable Inspector in release mode
|
||||||
@@ -65,7 +65,7 @@ func CreateApp(optionalConfig ...*AppConfig) *App {
|
|||||||
|
|
||||||
// Run the app
|
// Run the app
|
||||||
func (a *App) Run() error {
|
func (a *App) Run() error {
|
||||||
if DebugMode == "true" {
|
if BuildMode != cmd.BuildModeProd {
|
||||||
return a.cli.Run()
|
return a.cli.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ func (a *App) start() error {
|
|||||||
a.log.Info("Starting")
|
a.log.Info("Starting")
|
||||||
|
|
||||||
// Check if we are to run in headless mode
|
// Check if we are to run in headless mode
|
||||||
if DebugMode == "true" {
|
if BuildMode == cmd.BuildModeBridge {
|
||||||
a.renderer = &Headless{}
|
a.renderer = &Headless{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ window.wailsbridge = {
|
|||||||
overlayCSS:
|
overlayCSS:
|
||||||
".wails-reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.6);font-family:sans-serif;display:none;z-index:999999}.wails-reconnect-overlay-content{padding:20px 30px;text-align:center;width:20em;position:relative;height:14em;border-radius:1em;margin:5% auto 0;background-color:#fff;box-shadow:1px 1px 20px 3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAqFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAEBAQAAAAAAAAAAAAEBAQEBAQDAwMBAQEAAAABAQEAAAAAAAAAAAABAQEAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWKCj6oAAAAN3RSTlMALiIqDhkGBAswJjP0GxP6NR4W9/ztjRDMhWU50G9g5eHXvbZ9XEI9xZTcqZl2aldKo55QwoCvZUgzhAAAAs9JREFUSMeNleeWqjAUhU0BCaH3Itiw9zKT93+zG02QK1hm/5HF+jzZJ6fQe6cyXE+jg9X7o9wxuylIIf4Tv2V3+bOrEXnf8dwQ/KQIGDN2/S+4OmVCVXL/ScBnfibxURqIByP/hONE8r8T+bDMlQ98KSl7Y8hzjpS8v1qtDh8u5f8KQpGpfnPPhqG8JeogN37Hq9eaN2xRhIwAaGnvws8F1ShxqK5ob2twYi1FAMD4rXsYtnC/JEiRbl4cUrCWhnMCLRFemXezXbb59QK4WASOsm6n2W1+4CBT2JmtzQ6fsrbGubR/NFbd2g5Y179+5w/GEHaKsHjYCet7CgrXU3txarNC7YxOVJtIj4/ERzMdZfzc31hp+8cD6eGILgarZY9uZ12hAs03vfBD9C171gS5Omz7OcvxALQIn4u8RRBBBcsi9WW2woO9ipLgfzpYlggg3ZRdROUC8KT7QLqq3W9KB5BbdFVg4929kdwp6+qaZnMCCNBdj+NyN1W885Ry/AL3D4AQbsVV4noCiM/C83kyYq80XlDAYQtralOiDzoRAHlotWl8q2tjvYlOgcg1A8jEApZa+C06TBdAz2Qv0wu11I/zZOyJQ6EwGez2P2b8PIQr1hwwnAZsAxwA4UAYOyXUxM/xp6tHAn4GUmPGM9R28oVxgC0e/zQJJI6DyhyZ1r7uzRQhpcW7x7vTaWSzKSG6aep77kroTEl3U81uSVaUTtgEINfC8epx+Q4F9SpplHG84Ek6m4RAq9/TLkOBrxyeuddZhHvGIp1XXfFy3Z3vtwNblKGiDn+J+92vwwABHghj7HnzlS1H5kB49AZvdGCFgiBPq69qfXPr3y++yilF0ON4R8eR7spAsLpZ95NqAW5tab1c4vkZm6aleajchMwYTdILQQTwE2OV411ZM9WztDjPql12caBi6gDpUKmDd4U1XNdQxZ4LIXQ5/Tr4P7I9tYcFrDK3AAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center}.wails-reconnect-overlay-title{font-size:2em}.wails-reconnect-overlay-message{font-size:1.3em}.wails-reconnect-overlay-loadingspinner{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#3E67EC #eee #eee;border-radius:50%;animation:loadingspin 1s linear infinite;margin:auto;padding:2.5em}@keyframes loadingspin{100%{transform:rotate(360deg)}}",
|
".wails-reconnect-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.6);font-family:sans-serif;display:none;z-index:999999}.wails-reconnect-overlay-content{padding:20px 30px;text-align:center;width:20em;position:relative;height:14em;border-radius:1em;margin:5% auto 0;background-color:#fff;box-shadow:1px 1px 20px 3px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAuCAMAAACPpbA7AAAAqFBMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQAAAAAAAAEBAQAAAAAAAAAAAAEBAQEBAQDAwMBAQEAAAABAQEAAAAAAAAAAAABAQEAAAAAAAACAgICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAABAQEAAAACAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQWKCj6oAAAAN3RSTlMALiIqDhkGBAswJjP0GxP6NR4W9/ztjRDMhWU50G9g5eHXvbZ9XEI9xZTcqZl2aldKo55QwoCvZUgzhAAAAs9JREFUSMeNleeWqjAUhU0BCaH3Itiw9zKT93+zG02QK1hm/5HF+jzZJ6fQe6cyXE+jg9X7o9wxuylIIf4Tv2V3+bOrEXnf8dwQ/KQIGDN2/S+4OmVCVXL/ScBnfibxURqIByP/hONE8r8T+bDMlQ98KSl7Y8hzjpS8v1qtDh8u5f8KQpGpfnPPhqG8JeogN37Hq9eaN2xRhIwAaGnvws8F1ShxqK5ob2twYi1FAMD4rXsYtnC/JEiRbl4cUrCWhnMCLRFemXezXbb59QK4WASOsm6n2W1+4CBT2JmtzQ6fsrbGubR/NFbd2g5Y179+5w/GEHaKsHjYCet7CgrXU3txarNC7YxOVJtIj4/ERzMdZfzc31hp+8cD6eGILgarZY9uZ12hAs03vfBD9C171gS5Omz7OcvxALQIn4u8RRBBBcsi9WW2woO9ipLgfzpYlggg3ZRdROUC8KT7QLqq3W9KB5BbdFVg4929kdwp6+qaZnMCCNBdj+NyN1W885Ry/AL3D4AQbsVV4noCiM/C83kyYq80XlDAYQtralOiDzoRAHlotWl8q2tjvYlOgcg1A8jEApZa+C06TBdAz2Qv0wu11I/zZOyJQ6EwGez2P2b8PIQr1hwwnAZsAxwA4UAYOyXUxM/xp6tHAn4GUmPGM9R28oVxgC0e/zQJJI6DyhyZ1r7uzRQhpcW7x7vTaWSzKSG6aep77kroTEl3U81uSVaUTtgEINfC8epx+Q4F9SpplHG84Ek6m4RAq9/TLkOBrxyeuddZhHvGIp1XXfFy3Z3vtwNblKGiDn+J+92vwwABHghj7HnzlS1H5kB49AZvdGCFgiBPq69qfXPr3y++yilF0ON4R8eR7spAsLpZ95NqAW5tab1c4vkZm6aleajchMwYTdILQQTwE2OV411ZM9WztDjPql12caBi6gDpUKmDd4U1XNdQxZ4LIXQ5/Tr4P7I9tYcFrDK3AAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:center}.wails-reconnect-overlay-title{font-size:2em}.wails-reconnect-overlay-message{font-size:1.3em}.wails-reconnect-overlay-loadingspinner{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#3E67EC #eee #eee;border-radius:50%;animation:loadingspin 1s linear infinite;margin:auto;padding:2.5em}@keyframes loadingspin{100%{transform:rotate(360deg)}}",
|
||||||
log: function(message) {
|
log: function(message) {
|
||||||
|
// eslint-disable-next-line
|
||||||
console.log(
|
console.log(
|
||||||
"%c wails bridge %c " + message + " ",
|
"%c wails bridge %c " + message + " ",
|
||||||
"background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem",
|
"background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem",
|
||||||
@@ -188,7 +189,7 @@ function startBridge() {
|
|||||||
// Call back
|
// Call back
|
||||||
case "c":
|
case "c":
|
||||||
var callbackData = message.data.slice(1);
|
var callbackData = message.data.slice(1);
|
||||||
log("Callback = " + callbackData);
|
window.wailsbridge.log("Callback = " + callbackData);
|
||||||
window.wails._.callback(callbackData);
|
window.wails._.callback(callbackData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default {
|
|||||||
// Passes the main Wails object to the callback if given.
|
// Passes the main Wails object to the callback if given.
|
||||||
Start: function(callback) {
|
Start: function(callback) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
window.wails.events.on("wails:ready", callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -163,8 +163,71 @@ func (b *bindingManager) bind(object interface{}) {
|
|||||||
b.objectsToBind = append(b.objectsToBind, object)
|
b.objectsToBind = append(b.objectsToBind, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *bindingManager) processFunctionCall(callData *callData) (interface{}, error) {
|
||||||
|
// Return values
|
||||||
|
var result []reflect.Value
|
||||||
|
var err error
|
||||||
|
|
||||||
|
function := b.functions[callData.BindingName]
|
||||||
|
if function == nil {
|
||||||
|
return nil, fmt.Errorf("Invalid function name '%s'", callData.BindingName)
|
||||||
|
}
|
||||||
|
result, err = function.call(callData.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have an error return type?
|
||||||
|
if function.hasErrorReturnType {
|
||||||
|
// We do - last result is an error type
|
||||||
|
// Check if the last result was nil
|
||||||
|
b.log.Debugf("# of return types: %d", len(function.returnTypes))
|
||||||
|
b.log.Debugf("# of results: %d", len(result))
|
||||||
|
errorResult := result[len(function.returnTypes)-1]
|
||||||
|
if !errorResult.IsNil() {
|
||||||
|
// It wasn't - we have an error
|
||||||
|
return nil, errorResult.Interface().(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result[0].Interface(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bindingManager) processMethodCall(callData *callData) (interface{}, error) {
|
||||||
|
// Return values
|
||||||
|
var result []reflect.Value
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// do we have this method?
|
||||||
|
method := b.methods[callData.BindingName]
|
||||||
|
if method == nil {
|
||||||
|
return nil, fmt.Errorf("Invalid method name '%s'", callData.BindingName)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = method.call(callData.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have an error return type?
|
||||||
|
if method.hasErrorReturnType {
|
||||||
|
// We do - last result is an error type
|
||||||
|
// Check if the last result was nil
|
||||||
|
b.log.Debugf("# of return types: %d", len(method.returnTypes))
|
||||||
|
b.log.Debugf("# of results: %d", len(result))
|
||||||
|
errorResult := result[len(method.returnTypes)-1]
|
||||||
|
if !errorResult.IsNil() {
|
||||||
|
// It wasn't - we have an error
|
||||||
|
return nil, errorResult.Interface().(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if result != nil {
|
||||||
|
return result[0].Interface(), nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// process an incoming call request
|
// process an incoming call request
|
||||||
func (b *bindingManager) processCall(callData *callData) (interface{}, error) {
|
func (b *bindingManager) processCall(callData *callData) (result interface{}, err error) {
|
||||||
b.log.Debugf("Wanting to call %s", callData.BindingName)
|
b.log.Debugf("Wanting to call %s", callData.BindingName)
|
||||||
|
|
||||||
// Determine if this is function call or method call by the number of
|
// Determine if this is function call or method call by the number of
|
||||||
@@ -176,13 +239,10 @@ func (b *bindingManager) processCall(callData *callData) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return values
|
|
||||||
var result []reflect.Value
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// We need to catch reflect related panics and return
|
// We need to catch reflect related panics and return
|
||||||
// a decent error message
|
// a decent error message
|
||||||
// TODO: DEBUG THIS!
|
// TODO: DEBUG THIS!
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
err = fmt.Errorf("%s", r.(string))
|
err = fmt.Errorf("%s", r.(string))
|
||||||
@@ -191,59 +251,14 @@ func (b *bindingManager) processCall(callData *callData) (interface{}, error) {
|
|||||||
|
|
||||||
switch dotCount {
|
switch dotCount {
|
||||||
case 1:
|
case 1:
|
||||||
function := b.functions[callData.BindingName]
|
result, err = b.processFunctionCall(callData)
|
||||||
if function == nil {
|
|
||||||
return nil, fmt.Errorf("Invalid function name '%s'", callData.BindingName)
|
|
||||||
}
|
|
||||||
result, err = function.call(callData.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do we have an error return type?
|
|
||||||
if function.hasErrorReturnType {
|
|
||||||
// We do - last result is an error type
|
|
||||||
// Check if the last result was nil
|
|
||||||
b.log.Debugf("# of return types: %d", len(function.returnTypes))
|
|
||||||
b.log.Debugf("# of results: %d", len(result))
|
|
||||||
errorResult := result[len(function.returnTypes)-1]
|
|
||||||
if !errorResult.IsNil() {
|
|
||||||
// It wasn't - we have an error
|
|
||||||
return nil, errorResult.Interface().(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result[0].Interface(), nil
|
|
||||||
case 2:
|
case 2:
|
||||||
// do we have this method?
|
result, err = b.processMethodCall(callData)
|
||||||
method := b.methods[callData.BindingName]
|
|
||||||
if method == nil {
|
|
||||||
return nil, fmt.Errorf("Invalid method name '%s'", callData.BindingName)
|
|
||||||
}
|
|
||||||
result, err = method.call(callData.Data)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do we have an error return type?
|
|
||||||
if method.hasErrorReturnType {
|
|
||||||
// We do - last result is an error type
|
|
||||||
// Check if the last result was nil
|
|
||||||
b.log.Debugf("# of return types: %d", len(method.returnTypes))
|
|
||||||
b.log.Debugf("# of results: %d", len(result))
|
|
||||||
errorResult := result[len(method.returnTypes)-1]
|
|
||||||
if !errorResult.IsNil() {
|
|
||||||
// It wasn't - we have an error
|
|
||||||
return nil, errorResult.Interface().(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if result != nil {
|
|
||||||
return result[0].Interface(), nil
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Invalid binding name '%s'", callData.BindingName)
|
result = nil
|
||||||
|
err = fmt.Errorf("Invalid binding name '%s'", callData.BindingName)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// callWailsInitMethods calls all of the WailsInit methods that were
|
// callWailsInitMethods calls all of the WailsInit methods that were
|
||||||
|
|||||||
10
cmd/build.go
Normal file
10
cmd/build.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
const (
|
||||||
|
// BuildModeProd indicates we are building for prod mode
|
||||||
|
BuildModeProd = "prod"
|
||||||
|
// BuildModeDebug indicates we are building for debug mode
|
||||||
|
BuildModeDebug = "debug"
|
||||||
|
// BuildModeBridge indicates we are building for bridge mode
|
||||||
|
BuildModeBridge = "bridge"
|
||||||
|
)
|
||||||
236
cmd/helpers.go
Normal file
236
cmd/helpers.go
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/leaanthony/slicer"
|
||||||
|
"github.com/leaanthony/spinner"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ValidateFrontendConfig checks if the frontend config is valid
|
||||||
|
func ValidateFrontendConfig(projectOptions *ProjectOptions) error {
|
||||||
|
if projectOptions.FrontEnd.Dir == "" {
|
||||||
|
return fmt.Errorf("Frontend directory not set in project.json")
|
||||||
|
}
|
||||||
|
if projectOptions.FrontEnd.Build == "" {
|
||||||
|
return fmt.Errorf("Frontend build command not set in project.json")
|
||||||
|
}
|
||||||
|
if projectOptions.FrontEnd.Install == "" {
|
||||||
|
return fmt.Errorf("Frontend install command not set in project.json")
|
||||||
|
}
|
||||||
|
if projectOptions.FrontEnd.Bridge == "" {
|
||||||
|
return fmt.Errorf("Frontend bridge config not set in project.json")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstallGoDependencies will run go get in the current directory
|
||||||
|
func InstallGoDependencies() error {
|
||||||
|
depSpinner := spinner.New("Installing Dependencies...")
|
||||||
|
depSpinner.SetSpinSpeed(50)
|
||||||
|
depSpinner.Start()
|
||||||
|
err := NewProgramHelper().RunCommand("go get")
|
||||||
|
if err != nil {
|
||||||
|
depSpinner.Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
depSpinner.Success()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildApplication will attempt to build the project based on the given inputs
|
||||||
|
func BuildApplication(binaryName string, forceRebuild bool, buildMode string) error {
|
||||||
|
compileMessage := "Packing + Compiling project"
|
||||||
|
|
||||||
|
if buildMode == BuildModeDebug {
|
||||||
|
compileMessage += " (Debug Mode)"
|
||||||
|
}
|
||||||
|
|
||||||
|
packSpinner := spinner.New(compileMessage + "...")
|
||||||
|
packSpinner.SetSpinSpeed(50)
|
||||||
|
packSpinner.Start()
|
||||||
|
|
||||||
|
buildCommand := slicer.String()
|
||||||
|
buildCommand.AddSlice([]string{"packr", "build"})
|
||||||
|
|
||||||
|
if binaryName != "" {
|
||||||
|
buildCommand.Add("-o")
|
||||||
|
buildCommand.Add(binaryName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are forcing a rebuild
|
||||||
|
if forceRebuild {
|
||||||
|
buildCommand.Add("-a")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup ld flags
|
||||||
|
ldflags := "-w -s "
|
||||||
|
if buildMode == BuildModeDebug {
|
||||||
|
ldflags = ""
|
||||||
|
}
|
||||||
|
ldflags += "-X github.com/wailsapp/wails.BuildMode=" + buildMode
|
||||||
|
|
||||||
|
buildCommand.AddSlice([]string{"-ldflags", ldflags})
|
||||||
|
err := NewProgramHelper().RunCommandArray(buildCommand.AsSlice())
|
||||||
|
if err != nil {
|
||||||
|
packSpinner.Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
packSpinner.Success()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackageApplication will attempt to package the application in a pltform dependent way
|
||||||
|
func PackageApplication(projectOptions *ProjectOptions) error {
|
||||||
|
// Package app
|
||||||
|
packageSpinner := spinner.New("Packaging Application")
|
||||||
|
packageSpinner.SetSpinSpeed(50)
|
||||||
|
packageSpinner.Start()
|
||||||
|
err := NewPackageHelper().Package(projectOptions)
|
||||||
|
if err != nil {
|
||||||
|
packageSpinner.Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
packageSpinner.Success()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildFrontend runs the given build command
|
||||||
|
func BuildFrontend(buildCommand string) error {
|
||||||
|
buildFESpinner := spinner.New("Building frontend...")
|
||||||
|
buildFESpinner.SetSpinSpeed(50)
|
||||||
|
buildFESpinner.Start()
|
||||||
|
err := NewProgramHelper().RunCommand(buildCommand)
|
||||||
|
if err != nil {
|
||||||
|
buildFESpinner.Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buildFESpinner.Success()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckPackr checks if packr is installed and if not, attempts to fetch it
|
||||||
|
func CheckPackr() (err error) {
|
||||||
|
programHelper := NewProgramHelper()
|
||||||
|
if !programHelper.IsInstalled("packr") {
|
||||||
|
buildSpinner := spinner.New()
|
||||||
|
buildSpinner.SetSpinSpeed(50)
|
||||||
|
buildSpinner.Start("Installing packr...")
|
||||||
|
err := programHelper.InstallGoPackage("github.com/gobuffalo/packr/...")
|
||||||
|
if err != nil {
|
||||||
|
buildSpinner.Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buildSpinner.Success()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstallFrontendDeps attempts to install the frontend dependencies based on the given options
|
||||||
|
func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forceRebuild bool, caller string) error {
|
||||||
|
|
||||||
|
// Install frontend deps
|
||||||
|
err := os.Chdir(projectOptions.FrontEnd.Dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if frontend deps have been updated
|
||||||
|
feSpinner := spinner.New("Installing frontend dependencies (This may take a while)...")
|
||||||
|
feSpinner.SetSpinSpeed(50)
|
||||||
|
feSpinner.Start()
|
||||||
|
|
||||||
|
requiresNPMInstall := true
|
||||||
|
|
||||||
|
// Read in package.json MD5
|
||||||
|
fs := NewFSHelper()
|
||||||
|
packageJSONMD5, err := fs.FileMD5("package.json")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const md5sumFile = "package.json.md5"
|
||||||
|
|
||||||
|
// If we aren't forcing the install and the md5sum file exists
|
||||||
|
if !forceRebuild && fs.FileExists(md5sumFile) {
|
||||||
|
// Yes - read contents
|
||||||
|
savedMD5sum, err := fs.LoadAsString(md5sumFile)
|
||||||
|
// File exists
|
||||||
|
if err == nil {
|
||||||
|
// Compare md5
|
||||||
|
if savedMD5sum == packageJSONMD5 {
|
||||||
|
// Same - no need for reinstall
|
||||||
|
requiresNPMInstall = false
|
||||||
|
feSpinner.Success("Skipped frontend dependencies (-f to force rebuild)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Md5 sum package.json
|
||||||
|
// Different? Build
|
||||||
|
if requiresNPMInstall || forceRebuild {
|
||||||
|
// Install dependencies
|
||||||
|
err = NewProgramHelper().RunCommand(projectOptions.FrontEnd.Install)
|
||||||
|
if err != nil {
|
||||||
|
feSpinner.Error()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
feSpinner.Success()
|
||||||
|
|
||||||
|
// Update md5sum file
|
||||||
|
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
bridgeFile := "wailsbridge.prod.js"
|
||||||
|
if caller == "serve" {
|
||||||
|
bridgeFile = "wailsbridge.js"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy bridge to project
|
||||||
|
_, filename, _, _ := runtime.Caller(1)
|
||||||
|
bridgeFileSource := filepath.Join(path.Dir(filename), "..", "..", "assets", "default", bridgeFile)
|
||||||
|
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, projectOptions.FrontEnd.Bridge, "wailsbridge.js")
|
||||||
|
err = fs.CopyFile(bridgeFileSource, bridgeFileTarget)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build frontend
|
||||||
|
err = BuildFrontend(projectOptions.FrontEnd.Build)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeProject attempts to serve up the current project so that it may be connected to
|
||||||
|
// via the Wails bridge
|
||||||
|
func ServeProject(projectOptions *ProjectOptions, logger *Logger) error {
|
||||||
|
go func() {
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
logger.Green(">>>>> To connect, you will need to run '" + projectOptions.FrontEnd.Serve + "' in the '" + projectOptions.FrontEnd.Dir + "' directory <<<<<")
|
||||||
|
}()
|
||||||
|
location, err := filepath.Abs(projectOptions.BinaryName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Yellow("Serving Application: " + location)
|
||||||
|
cmd := exec.Command(location)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -116,6 +116,7 @@ func (p *ProgramHelper) RunCommandArray(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
|
// fmt.Printf("RunCommandArray = %s %+v\n", program, args)
|
||||||
_, stderr, err := p.shell.Run(program, args...)
|
_, stderr, err := p.shell.Run(program, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(stderr)
|
fmt.Println(stderr)
|
||||||
|
|||||||
148
cmd/project.go
148
cmd/project.go
@@ -178,40 +178,14 @@ func (po *ProjectOptions) Defaults() {
|
|||||||
func (po *ProjectOptions) PromptForInputs() error {
|
func (po *ProjectOptions) PromptForInputs() error {
|
||||||
|
|
||||||
var questions []*survey.Question
|
var questions []*survey.Question
|
||||||
fs := NewFSHelper()
|
|
||||||
|
|
||||||
if po.Name == "" {
|
processProjectName(po.Name, &questions)
|
||||||
questions = append(questions, InputQuestion("Name", "The name of the project", "My Project", true))
|
|
||||||
} else {
|
|
||||||
fmt.Println("Project Name: " + po.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if po.BinaryName == "" {
|
processBinaryName(po.BinaryName, po.Name, &questions)
|
||||||
var binaryNameComputed string
|
|
||||||
if po.Name != "" {
|
|
||||||
binaryNameComputed = strings.ToLower(po.Name)
|
|
||||||
binaryNameComputed = strings.Replace(binaryNameComputed, " ", "-", -1)
|
|
||||||
binaryNameComputed = strings.Replace(binaryNameComputed, string(filepath.Separator), "-", -1)
|
|
||||||
binaryNameComputed = strings.Replace(binaryNameComputed, ":", "-", -1)
|
|
||||||
}
|
|
||||||
questions = append(questions, InputQuestion("BinaryName", "The output binary name", binaryNameComputed, true))
|
|
||||||
} else {
|
|
||||||
fmt.Println("Output binary Name: " + po.BinaryName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if po.OutputDirectory != "" {
|
err := processOutputDirectory(po.OutputDirectory, &questions)
|
||||||
projectPath, err := filepath.Abs(po.OutputDirectory)
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if fs.DirExists(projectPath) {
|
|
||||||
return fmt.Errorf("directory '%s' already exists", projectPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Project Directory: " + po.OutputDirectory)
|
|
||||||
} else {
|
|
||||||
questions = append(questions, InputQuestion("OutputDirectory", "Project directory name", "", true))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
templateDetails, err := po.templates.GetTemplateDetails()
|
templateDetails, err := po.templates.GetTemplateDetails()
|
||||||
@@ -259,35 +233,10 @@ func (po *ProjectOptions) PromptForInputs() error {
|
|||||||
|
|
||||||
// Populate template details
|
// Populate template details
|
||||||
templateMetadata := templateDetails[po.Template].Metadata
|
templateMetadata := templateDetails[po.Template].Metadata
|
||||||
if templateMetadata["frontenddir"] != nil {
|
|
||||||
po.FrontEnd = &frontend{}
|
|
||||||
po.FrontEnd.Dir = templateMetadata["frontenddir"].(string)
|
|
||||||
}
|
|
||||||
if templateMetadata["install"] != nil {
|
|
||||||
if po.FrontEnd == nil {
|
|
||||||
return fmt.Errorf("install set in template metadata but not frontenddir")
|
|
||||||
}
|
|
||||||
po.FrontEnd.Install = templateMetadata["install"].(string)
|
|
||||||
}
|
|
||||||
if templateMetadata["build"] != nil {
|
|
||||||
if po.FrontEnd == nil {
|
|
||||||
return fmt.Errorf("build set in template metadata but not frontenddir")
|
|
||||||
}
|
|
||||||
po.FrontEnd.Build = templateMetadata["build"].(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
if templateMetadata["bridge"] != nil {
|
err = processTemplateMetadata(templateMetadata, po)
|
||||||
if po.FrontEnd == nil {
|
if err != nil {
|
||||||
return fmt.Errorf("bridge set in template metadata but not frontenddir")
|
return err
|
||||||
}
|
|
||||||
po.FrontEnd.Bridge = templateMetadata["bridge"].(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
if templateMetadata["serve"] != nil {
|
|
||||||
if po.FrontEnd == nil {
|
|
||||||
return fmt.Errorf("serve set in template metadata but not frontenddir")
|
|
||||||
}
|
|
||||||
po.FrontEnd.Serve = templateMetadata["serve"].(string)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -320,3 +269,84 @@ func (po *ProjectOptions) LoadConfig(projectDir string) error {
|
|||||||
}
|
}
|
||||||
return json.Unmarshal(rawBytes, po)
|
return json.Unmarshal(rawBytes, po)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func computeBinaryName(projectName string) string {
|
||||||
|
if projectName == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var binaryNameComputed = strings.ToLower(projectName)
|
||||||
|
binaryNameComputed = strings.Replace(binaryNameComputed, " ", "-", -1)
|
||||||
|
binaryNameComputed = strings.Replace(binaryNameComputed, string(filepath.Separator), "-", -1)
|
||||||
|
binaryNameComputed = strings.Replace(binaryNameComputed, ":", "-", -1)
|
||||||
|
return binaryNameComputed
|
||||||
|
}
|
||||||
|
|
||||||
|
func processOutputDirectory(outputDirectory string, questions *[]*survey.Question) error {
|
||||||
|
|
||||||
|
if outputDirectory != "" {
|
||||||
|
projectPath, err := filepath.Abs(outputDirectory)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if NewFSHelper().DirExists(projectPath) {
|
||||||
|
return fmt.Errorf("directory '%s' already exists", projectPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Project Directory: " + outputDirectory)
|
||||||
|
} else {
|
||||||
|
*questions = append(*questions, InputQuestion("OutputDirectory", "Project directory name", "", true))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func processProjectName(name string, questions *[]*survey.Question) {
|
||||||
|
if name == "" {
|
||||||
|
*questions = append(*questions, InputQuestion("Name", "The name of the project", "My Project", true))
|
||||||
|
} else {
|
||||||
|
fmt.Println("Project Name: " + name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func processBinaryName(binaryName string, name string, questions *[]*survey.Question) {
|
||||||
|
if binaryName == "" {
|
||||||
|
var binaryNameComputed = computeBinaryName(name)
|
||||||
|
*questions = append(*questions, InputQuestion("BinaryName", "The output binary name", binaryNameComputed, true))
|
||||||
|
} else {
|
||||||
|
fmt.Println("Output binary Name: " + binaryName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func processTemplateMetadata(templateMetadata map[string]interface{}, po *ProjectOptions) error {
|
||||||
|
if templateMetadata["frontenddir"] != nil {
|
||||||
|
po.FrontEnd = &frontend{}
|
||||||
|
po.FrontEnd.Dir = templateMetadata["frontenddir"].(string)
|
||||||
|
}
|
||||||
|
if templateMetadata["install"] != nil {
|
||||||
|
if po.FrontEnd == nil {
|
||||||
|
return fmt.Errorf("install set in template metadata but not frontenddir")
|
||||||
|
}
|
||||||
|
po.FrontEnd.Install = templateMetadata["install"].(string)
|
||||||
|
}
|
||||||
|
if templateMetadata["build"] != nil {
|
||||||
|
if po.FrontEnd == nil {
|
||||||
|
return fmt.Errorf("build set in template metadata but not frontenddir")
|
||||||
|
}
|
||||||
|
po.FrontEnd.Build = templateMetadata["build"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if templateMetadata["bridge"] != nil {
|
||||||
|
if po.FrontEnd == nil {
|
||||||
|
return fmt.Errorf("bridge set in template metadata but not frontenddir")
|
||||||
|
}
|
||||||
|
po.FrontEnd.Bridge = templateMetadata["bridge"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if templateMetadata["serve"] != nil {
|
||||||
|
if po.FrontEnd == nil {
|
||||||
|
return fmt.Errorf("serve set in template metadata but not frontenddir")
|
||||||
|
}
|
||||||
|
po.FrontEnd.Serve = templateMetadata["serve"].(string)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,29 +1,35 @@
|
|||||||
# frontend
|
# vue basic
|
||||||
|
|
||||||
## Project setup
|
## Project setup
|
||||||
|
|
||||||
```
|
```
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compiles and hot-reloads for development
|
### Compiles and hot-reloads for development
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run serve
|
npm run serve
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compiles and minifies for production
|
### Compiles and minifies for production
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run your tests
|
### Run your tests
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run test
|
npm run test
|
||||||
```
|
```
|
||||||
|
|
||||||
### Lints and fixes files
|
### Lints and fixes files
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run lint
|
npm run lint
|
||||||
```
|
```
|
||||||
|
|
||||||
### Customize configuration
|
### Customize configuration
|
||||||
|
|
||||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||||
11109
cmd/templates/vuebasic/frontend/package-lock.json
generated
Normal file
11109
cmd/templates/vuebasic/frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
1
cmd/templates/vuebasic/frontend/package.json.md5
Normal file
1
cmd/templates/vuebasic/frontend/package.json.md5
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2b79f883dc856221fc3265755d610e40
|
||||||
49
cmd/templates/vuebasic/frontend/package.json.template
Normal file
49
cmd/templates/vuebasic/frontend/package.json.template
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"name": "{{.NPMProjectName}}",
|
||||||
|
"author": "{{.Author.Name}}<{{.Author.Email}}>",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"serve": "vue-cli-service serve",
|
||||||
|
"build": "vue-cli-service build",
|
||||||
|
"lint": "vue-cli-service lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": "^2.6.4",
|
||||||
|
"vue": "^2.5.22"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vue/cli-plugin-babel": "^3.4.0",
|
||||||
|
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||||
|
"@vue/cli-service": "^3.4.0",
|
||||||
|
"babel-eslint": "^10.0.1",
|
||||||
|
"eslint": "^5.8.0",
|
||||||
|
"eslint-plugin-vue": "^5.0.0",
|
||||||
|
"eventsource-polyfill": "^0.9.6",
|
||||||
|
"vue-template-compiler": "^2.5.21",
|
||||||
|
"webpack-hot-middleware": "^2.24.3"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"env": {
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:vue/essential",
|
||||||
|
"eslint:recommended"
|
||||||
|
],
|
||||||
|
"rules": {},
|
||||||
|
"parserOptions": {
|
||||||
|
"parser": "babel-eslint"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"postcss": {
|
||||||
|
"plugins": {
|
||||||
|
"autoprefixer": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 1%",
|
||||||
|
"last 2 versions",
|
||||||
|
"not ie <= 8"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -5,11 +5,11 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
<title>frontend</title>
|
<title>my-vue-app-01</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
<strong>We're sorry but frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
<strong>We're sorry but my-vue-app-01 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
@@ -1,22 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<img alt="Wails logo" src="./assets/images/logo.png" class="logo zoomIn">
|
<img alt="Wails logo" src="./assets/images/logo.png" class="logo zoomIn">
|
||||||
<HelloWorld msg="Welcome to Your Wails App!"/>
|
<HelloWorld/>
|
||||||
<Quote/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import HelloWorld from "./components/HelloWorld.vue";
|
import HelloWorld from "./components/HelloWorld.vue";
|
||||||
import Quote from "./components/Quote.vue";
|
|
||||||
import "./assets/css/main.css";
|
import "./assets/css/main.css";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "app",
|
name: "app",
|
||||||
components: {
|
components: {
|
||||||
HelloWorld,
|
HelloWorld
|
||||||
Quote
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -10,21 +10,6 @@
|
|||||||
html {
|
html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
/* https://leaverou.github.io/css3patterns/#carbon */
|
|
||||||
background: linear-gradient(27deg, #151515 5px, transparent 5px) 0 5px,
|
|
||||||
linear-gradient(207deg, #151515 5px, transparent 5px) 10px 0px,
|
|
||||||
linear-gradient(27deg, #222 5px, transparent 5px) 0px 10px,
|
|
||||||
linear-gradient(207deg, #222 5px, transparent 5px) 10px 5px,
|
|
||||||
linear-gradient(90deg, #1b1b1b 10px, transparent 10px),
|
|
||||||
linear-gradient(
|
|
||||||
#1d1d1d 25%,
|
|
||||||
#1a1a1a 25%,
|
|
||||||
#1a1a1a 50%,
|
|
||||||
transparent 50%,
|
|
||||||
transparent 75%,
|
|
||||||
#242424 75%,
|
|
||||||
#242424
|
|
||||||
);
|
|
||||||
background-color: #131313;
|
background-color: #131313;
|
||||||
background-size: 20px 20px;
|
background-size: 20px 20px;
|
||||||
}
|
}
|
||||||
@@ -46,10 +31,8 @@ html {
|
|||||||
format("woff2"),
|
format("woff2"),
|
||||||
/* Super Modern Browsers */
|
/* Super Modern Browsers */
|
||||||
url("../fonts/roboto/roboto-v18-latin-regular.woff") format("woff"),
|
url("../fonts/roboto/roboto-v18-latin-regular.woff") format("woff"),
|
||||||
/* Modern Browsers */
|
/* Modern Browsers */ url("../fonts/roboto/roboto-v18-latin-regular.ttf")
|
||||||
url("../fonts/roboto/roboto-v18-latin-regular.ttf")
|
|
||||||
format("truetype"),
|
format("truetype"),
|
||||||
/* Safari, Android, iOS */
|
/* Safari, Android, iOS */
|
||||||
url("../fonts/roboto/roboto-v18-latin-regular.svg#Roboto")
|
url("../fonts/roboto/roboto-v18-latin-regular.svg#Roboto") format("svg"); /* Legacy iOS */
|
||||||
format("svg"); /* Legacy iOS */
|
}
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 301 KiB After Width: | Height: | Size: 301 KiB |
@@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<h1>{{message}}</h1>
|
||||||
|
<a @click="getMessage">Press Me!</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
message: " "
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getMessage: function() {
|
||||||
|
var self = this;
|
||||||
|
window.backend.basic().then(result => {
|
||||||
|
self.message = result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
h1 {
|
||||||
|
margin-top: 2em;
|
||||||
|
position: relative;
|
||||||
|
min-height: 5rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
font-size: 1.7em;
|
||||||
|
border-color: blue;
|
||||||
|
background-color: blue;
|
||||||
|
color: white;
|
||||||
|
border: 3px solid white;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 9px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 500ms;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
font-size: 1.7em;
|
||||||
|
border-color: white;
|
||||||
|
background-color: #121212;
|
||||||
|
color: white;
|
||||||
|
border: 3px solid white;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 9px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
12
cmd/templates/vuebasic/frontend/src/main.js
Normal file
12
cmd/templates/vuebasic/frontend/src/main.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import Vue from "vue";
|
||||||
|
import App from "./App.vue";
|
||||||
|
|
||||||
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
|
import Bridge from "./wailsbridge";
|
||||||
|
|
||||||
|
Bridge.Start(() => {
|
||||||
|
new Vue({
|
||||||
|
render: h => h(App)
|
||||||
|
}).$mount("#app");
|
||||||
|
});
|
||||||
17
cmd/templates/vuebasic/frontend/src/wailsbridge.js
Normal file
17
cmd/templates/vuebasic/frontend/src/wailsbridge.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
Wails Bridge (c) 2019-present Lea Anthony
|
||||||
|
|
||||||
|
This prod version is to get around having to rewrite your code
|
||||||
|
for production. When doing a release build, this file will be used
|
||||||
|
instead of the full version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// The main function
|
||||||
|
// Passes the main Wails object to the callback if given.
|
||||||
|
Start: function(callback) {
|
||||||
|
if (callback) {
|
||||||
|
window.wails.events.on("wails:ready", callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
43
cmd/templates/vuebasic/frontend/vue.config.js
Normal file
43
cmd/templates/vuebasic/frontend/vue.config.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
let cssConfig = {};
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV == "production") {
|
||||||
|
cssConfig = {
|
||||||
|
extract: {
|
||||||
|
filename: "[name].css",
|
||||||
|
chunkFilename: "[name].css"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
chainWebpack: config => {
|
||||||
|
let limit = 9999999999999999;
|
||||||
|
config.module
|
||||||
|
.rule("images")
|
||||||
|
.test(/\.(png|gif|jpg)(\?.*)?$/i)
|
||||||
|
.use("url-loader")
|
||||||
|
.loader("url-loader")
|
||||||
|
.tap(options => Object.assign(options, { limit: limit }));
|
||||||
|
config.module
|
||||||
|
.rule("fonts")
|
||||||
|
.test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
|
||||||
|
.use("url-loader")
|
||||||
|
.loader("url-loader")
|
||||||
|
.options({
|
||||||
|
limit: limit
|
||||||
|
});
|
||||||
|
},
|
||||||
|
css: cssConfig,
|
||||||
|
configureWebpack: {
|
||||||
|
output: {
|
||||||
|
filename: "[name].js"
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
splitChunks: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
disableHostCheck: true,
|
||||||
|
host: "localhost"
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -5,6 +5,10 @@ import (
|
|||||||
"github.com/wailsapp/wails"
|
"github.com/wailsapp/wails"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func basic() string {
|
||||||
|
return "Hello World!"
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
assets := packr.NewBox("./frontend/dist")
|
assets := packr.NewBox("./frontend/dist")
|
||||||
@@ -16,6 +20,6 @@ func main() {
|
|||||||
JS: wails.BoxString(&assets, "app.js"),
|
JS: wails.BoxString(&assets, "app.js"),
|
||||||
CSS: wails.BoxString(&assets, "app.css"),
|
CSS: wails.BoxString(&assets, "app.css"),
|
||||||
})
|
})
|
||||||
app.Bind(newQuotesCollection())
|
app.Bind(basic)
|
||||||
app.Run()
|
app.Run()
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "Vue2/Webpack",
|
"name": "Vue2/Webpack Basic",
|
||||||
"shortdescription": "A basic Vue2/WebPack4 template",
|
"shortdescription": "A basic Vue2/WebPack4 template",
|
||||||
"description": "A basic template using Vue 2 and bundled using Webpack 4",
|
"description": "A basic template using Vue 2 and bundled using Webpack 4",
|
||||||
"author": "Lea Anthony<lea.anthony@gmail.com>",
|
"author": "Lea Anthony<lea.anthony@gmail.com>",
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
> 1%
|
|
||||||
last 2 versions
|
|
||||||
not ie <= 8
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "{{.NPMProjectName}}",
|
|
||||||
"author": "{{.Author.Name}}<{{.Author.Email}}>",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"serve": "vue-cli-service serve",
|
|
||||||
"build": "vue-cli-service build"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"vue": "^2.5.17"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@vue/cli-plugin-babel": "^3.1.1",
|
|
||||||
"@vue/cli-service": "^3.1.4",
|
|
||||||
"vue-template-compiler": "^2.5.17"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
autoprefixer: {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
/**
|
|
||||||
Credit: https://codepen.io/harmputman/pen/IpAnb
|
|
||||||
**/
|
|
||||||
|
|
||||||
body {
|
|
||||||
font: normal 300 1em/1.5em sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
background: #fff;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 480px;
|
|
||||||
min-width: 320px;
|
|
||||||
margin: 2em auto 0;
|
|
||||||
padding: 1.5em;
|
|
||||||
opacity: 0.8;
|
|
||||||
border-radius: 1em;
|
|
||||||
border-color: #117;
|
|
||||||
}
|
|
||||||
|
|
||||||
p { margin-bottom: 1.5em; }
|
|
||||||
p:last-child { margin-bottom: 0; }
|
|
||||||
|
|
||||||
blockquote {
|
|
||||||
display: block;
|
|
||||||
border-width: 2px 0;
|
|
||||||
border-style: solid;
|
|
||||||
border-color: #eee;
|
|
||||||
padding: 1.5em 0 0.5em;
|
|
||||||
margin: 1.5em 0;
|
|
||||||
position: relative;
|
|
||||||
color: #117;
|
|
||||||
}
|
|
||||||
blockquote:before {
|
|
||||||
content: '\201C';
|
|
||||||
position: absolute;
|
|
||||||
top: 0em;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
background: #fff;
|
|
||||||
width: 3rem;
|
|
||||||
height: 2rem;
|
|
||||||
font: 6em/1.08em sans-serif;
|
|
||||||
color: #666;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
blockquote:after {
|
|
||||||
content: "\2013 \2003" attr(cite);
|
|
||||||
display: block;
|
|
||||||
text-align: right;
|
|
||||||
font-size: 0.875em;
|
|
||||||
color: #e70000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* https://fdossena.com/?p=html5cool/buttons/i.frag */
|
|
||||||
button {
|
|
||||||
display:inline-block;
|
|
||||||
padding:0.35em 1.2em;
|
|
||||||
border:0.1em solid #000;
|
|
||||||
margin:0 0.3em 0.3em 0;
|
|
||||||
border-radius:0.12em;
|
|
||||||
box-sizing: border-box;
|
|
||||||
text-decoration:none;
|
|
||||||
font-family:'Roboto',sans-serif;
|
|
||||||
font-weight:300;
|
|
||||||
font-size: 1em;
|
|
||||||
color:#000;
|
|
||||||
text-align:center;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
button:hover{
|
|
||||||
color:#FFF;
|
|
||||||
background-color:#000;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="hello">
|
|
||||||
<h1>{{ msg }}</h1>
|
|
||||||
<p></p>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "HelloWorld",
|
|
||||||
props: {
|
|
||||||
msg: String
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
||||||
<style scoped>
|
|
||||||
.hello {
|
|
||||||
margin-top: 2em;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
margin: 40px 0 0;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: gold;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="container">
|
|
||||||
<blockquote v-if="quote != null" :cite="quote.person">{{ quote.text }}</blockquote>
|
|
||||||
<p></p>
|
|
||||||
<button @click="getNewQuote()">Get new Quote</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import "../assets/css/quote.css";
|
|
||||||
import { eventBus } from "../main";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
quote: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getNewQuote: function() {
|
|
||||||
var self = this;
|
|
||||||
backend.QuotesCollection.GetQuote().then(result => {
|
|
||||||
self.quote = result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
if( !backend ) {
|
|
||||||
eventBus.$on("ready", this.getNewQuote);
|
|
||||||
} else {
|
|
||||||
this.getNewQuote();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
||||||
<style scoped>
|
|
||||||
.hello {
|
|
||||||
margin-top: 2em;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
margin: 40px 0 0;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: gold;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import Vue from "vue";
|
|
||||||
export const eventBus = new Vue();
|
|
||||||
|
|
||||||
import App from "./App.vue";
|
|
||||||
new Vue({
|
|
||||||
render: h => h(App)
|
|
||||||
}).$mount("#app");
|
|
||||||
|
|
||||||
import Bridge from "./wailsbridge";
|
|
||||||
Bridge.OnReady(() => {
|
|
||||||
eventBus.$emit("ready");
|
|
||||||
});
|
|
||||||
Bridge.Start();
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
|
|
||||||
module.exports = {
|
|
||||||
chainWebpack: (config) => {
|
|
||||||
let limit = 9999999999999999;
|
|
||||||
config.module
|
|
||||||
.rule('images')
|
|
||||||
.test(/\.(png|gif|jpg)(\?.*)?$/i)
|
|
||||||
.use('url-loader')
|
|
||||||
.loader('url-loader')
|
|
||||||
.tap(options => Object.assign(options, { limit: limit }));
|
|
||||||
config.module
|
|
||||||
.rule('fonts')
|
|
||||||
.test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
|
|
||||||
.use('url-loader')
|
|
||||||
.loader('url-loader')
|
|
||||||
.options({
|
|
||||||
limit: limit,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
css: {
|
|
||||||
extract: {
|
|
||||||
filename: '[name].css',
|
|
||||||
chunkFilename: '[name].css',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
configureWebpack: {
|
|
||||||
output: {
|
|
||||||
filename: '[name].js',
|
|
||||||
},
|
|
||||||
optimization: {
|
|
||||||
splitChunks: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Quote holds a single quote and the person who said it
|
|
||||||
type Quote struct {
|
|
||||||
Text string `json:"text"`
|
|
||||||
Person string `json:"person"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// QuotesCollection holds a collection of quotes!
|
|
||||||
type QuotesCollection struct {
|
|
||||||
quotes []*Quote
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddQuote creates a Quote object with the given inputs and
|
|
||||||
// adds it to the Quotes collection
|
|
||||||
func (Q *QuotesCollection) AddQuote(text, person string) {
|
|
||||||
Q.quotes = append(Q.quotes, &Quote{Text: text, Person: person})
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetQuote returns a random Quote object from the Quotes collection
|
|
||||||
func (Q *QuotesCollection) GetQuote() *Quote {
|
|
||||||
return Q.quotes[rand.Intn(len(Q.quotes))]
|
|
||||||
}
|
|
||||||
|
|
||||||
// newQuotesCollection creates a new QuotesCollection
|
|
||||||
func newQuotesCollection() *QuotesCollection {
|
|
||||||
result := &QuotesCollection{}
|
|
||||||
rand.Seed(time.Now().Unix())
|
|
||||||
result.AddQuote("Age is an issue of mind over matter. If you don't mind, it doesn't matter", "Mark Twain")
|
|
||||||
result.AddQuote("Anyone who stops learning is old, whether at twenty or eighty. Anyone who keeps learning stays young. The greatest thing in life is to keep your mind young", "Henry Ford")
|
|
||||||
result.AddQuote("Wrinkles should merely indicate where smiles have been", "Mark Twain")
|
|
||||||
result.AddQuote("True terror is to wake up one morning and discover that your high school class is running the country", "Kurt Vonnegut")
|
|
||||||
result.AddQuote("A diplomat is a man who always remembers a woman's birthday but never remembers her age", "Robert Frost")
|
|
||||||
result.AddQuote("As I grow older, I pay less attention to what men say. I just watch what they do", "Andrew Carnegie")
|
|
||||||
result.AddQuote("How incessant and great are the ills with which a prolonged old age is replete", "C. S. Lewis")
|
|
||||||
result.AddQuote("Old age, believe me, is a good and pleasant thing. It is true you are gently shouldered off the stage, but then you are given such a comfortable front stall as spectator", "Confucius")
|
|
||||||
result.AddQuote("Old age has deformities enough of its own. It should never add to them the deformity of vice", "Eleanor Roosevelt")
|
|
||||||
result.AddQuote("Nobody grows old merely by living a number of years. We grow old by deserting our ideals. Years may wrinkle the skin, but to give up enthusiasm wrinkles the soul", "Samuel Ullman")
|
|
||||||
result.AddQuote("An archaeologist is the best husband a woman can have. The older she gets the more interested he is in her", "Agatha Christie")
|
|
||||||
result.AddQuote("All diseases run into one, old age", "Ralph Waldo Emerson")
|
|
||||||
result.AddQuote("Bashfulness is an ornament to youth, but a reproach to old age", "Aristotle")
|
|
||||||
result.AddQuote("Like everyone else who makes the mistake of getting older, I begin each day with coffee and obituaries", "Bill Cosby")
|
|
||||||
result.AddQuote("Age appears to be best in four things old wood best to burn, old wine to drink, old friends to trust, and old authors to read", "Francis Bacon")
|
|
||||||
result.AddQuote("None are so old as those who have outlived enthusiasm", "Henry David Thoreau")
|
|
||||||
result.AddQuote("Every man over forty is a scoundrel", "George Bernard Shaw")
|
|
||||||
result.AddQuote("Forty is the old age of youth fifty the youth of old age", "Victor Hugo")
|
|
||||||
result.AddQuote("You can't help getting older, but you don't have to get old", "George Burns")
|
|
||||||
result.AddQuote("Alas, after a certain age every man is responsible for his face", "Albert Camus")
|
|
||||||
result.AddQuote("Youth is when you're allowed to stay up late on New Year's Eve. Middle age is when you're forced to", "Bill Vaughan")
|
|
||||||
result.AddQuote("Old age is like everything else. To make a success of it, you've got to start young", "Theodore Roosevelt")
|
|
||||||
result.AddQuote("A comfortable old age is the reward of a well-spent youth. Instead of its bringing sad and melancholy prospects of decay, it would give us hopes of eternal youth in a better world", "Maurice Chevalier")
|
|
||||||
result.AddQuote("A man growing old becomes a child again", "Sophocles")
|
|
||||||
result.AddQuote("I will never be an old man. To me, old age is always 15 years older than I am", "Francis Bacon")
|
|
||||||
result.AddQuote("Age considers youth ventures", "Rabindranath Tagore")
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
@@ -2,4 +2,4 @@ package cmd
|
|||||||
|
|
||||||
// Version - Wails version
|
// Version - Wails version
|
||||||
// ...oO(There must be a better way)
|
// ...oO(There must be a better way)
|
||||||
const Version = "v0.5.0"
|
const Version = "v0.9.0"
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/leaanthony/spinner"
|
"github.com/leaanthony/spinner"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -31,64 +30,29 @@ Create your first project by running 'wails init'.`
|
|||||||
if runtime.GOOS != "windows" {
|
if runtime.GOOS != "windows" {
|
||||||
successMessage = "🚀 " + successMessage
|
successMessage = "🚀 " + successMessage
|
||||||
}
|
}
|
||||||
switch runtime.GOOS {
|
// Platform check
|
||||||
case "darwin":
|
err = platformCheck()
|
||||||
logger.Yellow("Detected Platform: OSX")
|
|
||||||
case "windows":
|
|
||||||
logger.Yellow("Detected Platform: Windows")
|
|
||||||
case "linux":
|
|
||||||
logger.Yellow("Detected Platform: Linux")
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Platform %s is currently not supported", runtime.GOOS)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Yellow("Checking for prerequisites...")
|
|
||||||
// Check we have a cgo capable environment
|
|
||||||
|
|
||||||
requiredPrograms, err := cmd.GetRequiredPrograms()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
errors := false
|
|
||||||
programHelper := cmd.NewProgramHelper()
|
// Check we have a cgo capable environment
|
||||||
for _, program := range *requiredPrograms {
|
logger.Yellow("Checking for prerequisites...")
|
||||||
bin := programHelper.FindProgram(program.Name)
|
errors, err := checkRequiredPrograms()
|
||||||
if bin == nil {
|
if err != nil {
|
||||||
errors = true
|
return err
|
||||||
logger.Red("Program '%s' not found. %s", program.Name, program.Help)
|
|
||||||
} else {
|
|
||||||
logger.Green("Program '%s' found: %s", program.Name, bin.Path)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Linux has library deps
|
// Linux has library deps
|
||||||
if runtime.GOOS == "linux" {
|
errors, err = checkLibraries()
|
||||||
// Check library prerequisites
|
if err != nil {
|
||||||
requiredLibraries, err := cmd.GetRequiredLibraries()
|
return err
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
distroInfo := cmd.GetLinuxDistroInfo()
|
|
||||||
for _, library := range *requiredLibraries {
|
|
||||||
switch distroInfo.Distribution {
|
|
||||||
case cmd.Ubuntu:
|
|
||||||
installed, err := cmd.DpkgInstalled(library.Name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !installed {
|
|
||||||
errors = true
|
|
||||||
logger.Red("Library '%s' not found. %s", library.Name, library.Help)
|
|
||||||
} else {
|
|
||||||
logger.Green("Library '%s' installed.", library.Name)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unable to check libraries on distribution '%s'. Please ensure that the '%s' equivalent is installed", distroInfo.DistributorID, library.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// packr
|
// packr
|
||||||
|
err = cmd.CheckPackr()
|
||||||
|
|
||||||
|
programHelper := cmd.NewProgramHelper()
|
||||||
if !programHelper.IsInstalled("packr") {
|
if !programHelper.IsInstalled("packr") {
|
||||||
buildSpinner := spinner.New()
|
buildSpinner := spinner.New()
|
||||||
buildSpinner.SetSpinSpeed(50)
|
buildSpinner.SetSpinSpeed(50)
|
||||||
@@ -110,3 +74,65 @@ Create your first project by running 'wails init'.`
|
|||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func platformCheck() error {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
logger.Yellow("Detected Platform: OSX")
|
||||||
|
case "windows":
|
||||||
|
logger.Yellow("Detected Platform: Windows")
|
||||||
|
case "linux":
|
||||||
|
logger.Yellow("Detected Platform: Linux")
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Platform %s is currently not supported", runtime.GOOS)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkLibraries() (errors bool, err error) {
|
||||||
|
if runtime.GOOS == "linux" {
|
||||||
|
// Check library prerequisites
|
||||||
|
requiredLibraries, err := cmd.GetRequiredLibraries()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
distroInfo := cmd.GetLinuxDistroInfo()
|
||||||
|
for _, library := range *requiredLibraries {
|
||||||
|
switch distroInfo.Distribution {
|
||||||
|
case cmd.Ubuntu:
|
||||||
|
installed, err := cmd.DpkgInstalled(library.Name)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if !installed {
|
||||||
|
errors = true
|
||||||
|
logger.Red("Library '%s' not found. %s", library.Name, library.Help)
|
||||||
|
} else {
|
||||||
|
logger.Green("Library '%s' installed.", library.Name)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false, fmt.Errorf("unable to check libraries on distribution '%s'. Please ensure that the '%s' equivalent is installed", distroInfo.DistributorID, library.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkRequiredPrograms() (errors bool, err error) {
|
||||||
|
requiredPrograms, err := cmd.GetRequiredPrograms()
|
||||||
|
if err != nil {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
errors = false
|
||||||
|
programHelper := cmd.NewProgramHelper()
|
||||||
|
for _, program := range *requiredPrograms {
|
||||||
|
bin := programHelper.FindProgram(program.Name)
|
||||||
|
if bin == nil {
|
||||||
|
errors = true
|
||||||
|
logger.Red("Program '%s' not found. %s", program.Name, program.Help)
|
||||||
|
} else {
|
||||||
|
logger.Green("Program '%s' found: %s", program.Name, bin.Path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,13 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/leaanthony/slicer"
|
|
||||||
"github.com/leaanthony/spinner"
|
"github.com/leaanthony/spinner"
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
)
|
)
|
||||||
@@ -17,6 +12,7 @@ func init() {
|
|||||||
|
|
||||||
var packageApp = false
|
var packageApp = false
|
||||||
var forceRebuild = false
|
var forceRebuild = false
|
||||||
|
var debugMode = false
|
||||||
buildSpinner := spinner.NewSpinner()
|
buildSpinner := spinner.NewSpinner()
|
||||||
buildSpinner.SetSpinSpeed(50)
|
buildSpinner.SetSpinSpeed(50)
|
||||||
|
|
||||||
@@ -24,7 +20,9 @@ func init() {
|
|||||||
initCmd := app.Command("build", "Builds your Wails project").
|
initCmd := app.Command("build", "Builds your Wails project").
|
||||||
LongDescription(commandDescription).
|
LongDescription(commandDescription).
|
||||||
BoolFlag("p", "Package application on successful build", &packageApp).
|
BoolFlag("p", "Package application on successful build", &packageApp).
|
||||||
BoolFlag("f", "Force rebuild of application components", &forceRebuild)
|
BoolFlag("f", "Force rebuild of application components", &forceRebuild).
|
||||||
|
BoolFlag("d", "Build in Debug mode", &debugMode)
|
||||||
|
|
||||||
initCmd.Action(func() error {
|
initCmd.Action(func() error {
|
||||||
log := cmd.NewLogger()
|
log := cmd.NewLogger()
|
||||||
message := "Building Application"
|
message := "Building Application"
|
||||||
@@ -46,24 +44,11 @@ func init() {
|
|||||||
|
|
||||||
// Validate config
|
// Validate config
|
||||||
// Check if we have a frontend
|
// Check if we have a frontend
|
||||||
if projectOptions.FrontEnd != nil {
|
err = cmd.ValidateFrontendConfig(projectOptions)
|
||||||
if projectOptions.FrontEnd.Dir == "" {
|
if err != nil {
|
||||||
return fmt.Errorf("Frontend directory not set in project.json")
|
return err
|
||||||
}
|
|
||||||
if projectOptions.FrontEnd.Build == "" {
|
|
||||||
return fmt.Errorf("Frontend build command not set in project.json")
|
|
||||||
}
|
|
||||||
if projectOptions.FrontEnd.Install == "" {
|
|
||||||
return fmt.Errorf("Frontend install command not set in project.json")
|
|
||||||
}
|
|
||||||
if projectOptions.FrontEnd.Bridge == "" {
|
|
||||||
return fmt.Errorf("Frontend bridge config not set in project.json")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check pre-requisites are installed
|
|
||||||
|
|
||||||
// Program checker
|
// Program checker
|
||||||
program := cmd.NewProgramHelper()
|
program := cmd.NewProgramHelper()
|
||||||
|
|
||||||
@@ -74,170 +59,56 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// packr
|
// Check Packr is installed
|
||||||
if !program.IsInstalled("packr") {
|
err = cmd.CheckPackr()
|
||||||
buildSpinner.Start("Installing packr...")
|
if err != nil {
|
||||||
err := program.InstallGoPackage("github.com/gobuffalo/packr/...")
|
return err
|
||||||
if err != nil {
|
|
||||||
buildSpinner.Error()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
buildSpinner.Success()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save project directory
|
// Save project directory
|
||||||
projectDir := fs.Cwd()
|
projectDir := fs.Cwd()
|
||||||
|
|
||||||
// Install backend deps - needed?
|
// Install deps
|
||||||
if projectOptions.FrontEnd != nil {
|
if projectOptions.FrontEnd != nil {
|
||||||
// Install frontend deps
|
err = cmd.InstallFrontendDeps(projectDir, projectOptions, forceRebuild, "build")
|
||||||
err = os.Chdir(projectOptions.FrontEnd.Dir)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if frontend deps have been updated
|
|
||||||
feSpinner := spinner.New("Installing frontend dependencies (This may take a while)...")
|
|
||||||
feSpinner.SetSpinSpeed(50)
|
|
||||||
feSpinner.Start()
|
|
||||||
|
|
||||||
requiresNPMInstall := true
|
|
||||||
|
|
||||||
// Read in package.json MD5
|
|
||||||
packageJSONMD5, err := fs.FileMD5("package.json")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
const md5sumFile = "package.json.md5"
|
|
||||||
|
|
||||||
// If we aren't forcing the install and the md5sum file exists
|
|
||||||
if !forceRebuild && fs.FileExists(md5sumFile) {
|
|
||||||
// Yes - read contents
|
|
||||||
savedMD5sum, err := fs.LoadAsString(md5sumFile)
|
|
||||||
// File exists
|
|
||||||
if err == nil {
|
|
||||||
// Compare md5
|
|
||||||
if savedMD5sum == packageJSONMD5 {
|
|
||||||
// Same - no need for reinstall
|
|
||||||
requiresNPMInstall = false
|
|
||||||
feSpinner.Success("Skipped frontend dependencies (-f to force rebuild)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Md5 sum package.json
|
|
||||||
// Different? Build
|
|
||||||
if requiresNPMInstall || forceRebuild {
|
|
||||||
// Install dependencies
|
|
||||||
err = program.RunCommand(projectOptions.FrontEnd.Install)
|
|
||||||
if err != nil {
|
|
||||||
feSpinner.Error()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
feSpinner.Success()
|
|
||||||
|
|
||||||
// Update md5sum file
|
|
||||||
ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine which wails bridge to install
|
|
||||||
bridgeFile := "wailsbridge.prod.js"
|
|
||||||
|
|
||||||
// Copy bridge to project
|
|
||||||
_, filename, _, _ := runtime.Caller(1)
|
|
||||||
bridgeFileSource := filepath.Join(path.Dir(filename), "..", "assets", "default", bridgeFile)
|
|
||||||
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, projectOptions.FrontEnd.Bridge, "wailsbridge.js")
|
|
||||||
err = fs.CopyFile(bridgeFileSource, bridgeFileTarget)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build frontend
|
|
||||||
buildFESpinner := spinner.New("Building frontend...")
|
|
||||||
buildFESpinner.SetSpinSpeed(50)
|
|
||||||
buildFESpinner.Start()
|
|
||||||
err = program.RunCommand(projectOptions.FrontEnd.Build)
|
|
||||||
if err != nil {
|
|
||||||
buildFESpinner.Error()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
buildFESpinner.Success()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run packr in project directory
|
// Move to project directory
|
||||||
err = os.Chdir(projectDir)
|
err = os.Chdir(projectDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support build tags
|
// Install dependencies
|
||||||
buildTags := []string{}
|
err = cmd.InstallGoDependencies()
|
||||||
|
|
||||||
depSpinner := spinner.New("Installing Dependencies...")
|
|
||||||
depSpinner.SetSpinSpeed(50)
|
|
||||||
depSpinner.Start()
|
|
||||||
installCommand := "go get"
|
|
||||||
err = program.RunCommand(installCommand)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
depSpinner.Error()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
depSpinner.Success()
|
|
||||||
|
|
||||||
compileMessage := "Packing + Compiling project"
|
|
||||||
|
|
||||||
packSpinner := spinner.New(compileMessage + "...")
|
|
||||||
packSpinner.SetSpinSpeed(50)
|
|
||||||
packSpinner.Start()
|
|
||||||
|
|
||||||
buildCommand := slicer.String()
|
|
||||||
buildCommand.AddSlice([]string{"packr", "build"})
|
|
||||||
|
|
||||||
// Add build tags
|
|
||||||
if len(buildTags) > 0 {
|
|
||||||
buildCommand.Add("--tags")
|
|
||||||
buildCommand.AddSlice(buildTags)
|
|
||||||
|
|
||||||
|
// Build application
|
||||||
|
buildMode := cmd.BuildModeProd
|
||||||
|
if debugMode {
|
||||||
|
buildMode = cmd.BuildModeDebug
|
||||||
}
|
}
|
||||||
|
err = cmd.BuildApplication(projectOptions.BinaryName, forceRebuild, buildMode)
|
||||||
if projectOptions.BinaryName != "" {
|
|
||||||
buildCommand.Add("-o")
|
|
||||||
buildCommand.Add(projectOptions.BinaryName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are forcing a rebuild
|
|
||||||
if forceRebuild {
|
|
||||||
buildCommand.Add("-a")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release mode
|
|
||||||
buildCommand.AddSlice([]string{"-ldflags", "-X github.com/wailsapp/wails.DebugMode=false"})
|
|
||||||
|
|
||||||
err = program.RunCommandArray(buildCommand.AsSlice())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
packSpinner.Error()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
packSpinner.Success()
|
|
||||||
|
|
||||||
if packageApp == false {
|
// Package application
|
||||||
logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
|
if packageApp {
|
||||||
return nil
|
err = cmd.PackageApplication(projectOptions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Package app
|
|
||||||
packageSpinner := spinner.New("Packaging Application")
|
|
||||||
packageSpinner.SetSpinSpeed(50)
|
|
||||||
packageSpinner.Start()
|
|
||||||
packager := cmd.NewPackageHelper()
|
|
||||||
err = packager.Package(projectOptions)
|
|
||||||
if err != nil {
|
|
||||||
packageSpinner.Error()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
packageSpinner.Success()
|
|
||||||
logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
|
logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/leaanthony/slicer"
|
|
||||||
"github.com/leaanthony/spinner"
|
"github.com/leaanthony/spinner"
|
||||||
"github.com/wailsapp/wails/cmd"
|
"github.com/wailsapp/wails/cmd"
|
||||||
)
|
)
|
||||||
@@ -20,7 +15,7 @@ func init() {
|
|||||||
buildSpinner.SetSpinSpeed(50)
|
buildSpinner.SetSpinSpeed(50)
|
||||||
|
|
||||||
commandDescription := `This command builds then serves your application in bridge mode. Useful for developing your app in a browser.`
|
commandDescription := `This command builds then serves your application in bridge mode. Useful for developing your app in a browser.`
|
||||||
initCmd := app.Command("serve", "Runs your Wails project in bridge mode").
|
initCmd := app.Command("serve", "Run your Wails project in bridge mode.").
|
||||||
LongDescription(commandDescription).
|
LongDescription(commandDescription).
|
||||||
BoolFlag("f", "Force rebuild of application components", &forceRebuild)
|
BoolFlag("f", "Force rebuild of application components", &forceRebuild)
|
||||||
|
|
||||||
@@ -43,124 +38,41 @@ func init() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Validate config
|
// Validate config
|
||||||
// // Check if we have a frontend
|
// Check if we have a frontend
|
||||||
// if projectOptions.FrontEnd != nil {
|
err = cmd.ValidateFrontendConfig(projectOptions)
|
||||||
// if projectOptions.FrontEnd.Dir == "" {
|
|
||||||
// return fmt.Errorf("Frontend directory not set in project.json")
|
|
||||||
// }
|
|
||||||
// if projectOptions.FrontEnd.Build == "" {
|
|
||||||
// return fmt.Errorf("Frontend build command not set in project.json")
|
|
||||||
// }
|
|
||||||
// if projectOptions.FrontEnd.Install == "" {
|
|
||||||
// return fmt.Errorf("Frontend install command not set in project.json")
|
|
||||||
// }
|
|
||||||
// if projectOptions.FrontEnd.Bridge == "" {
|
|
||||||
// return fmt.Errorf("Frontend bridge config not set in project.json")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Check pre-requisites are installed
|
|
||||||
|
|
||||||
// Program checker
|
|
||||||
program := cmd.NewProgramHelper()
|
|
||||||
|
|
||||||
// if projectOptions.FrontEnd != nil {
|
|
||||||
// // npm
|
|
||||||
// if !program.IsInstalled("npm") {
|
|
||||||
// return fmt.Errorf("it appears npm is not installed. Please install and run again")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// packr
|
|
||||||
if !program.IsInstalled("packr") {
|
|
||||||
buildSpinner.Start("Installing packr...")
|
|
||||||
err := program.InstallGoPackage("github.com/gobuffalo/packr/...")
|
|
||||||
if err != nil {
|
|
||||||
buildSpinner.Error()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
buildSpinner.Success()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save project directory
|
|
||||||
projectDir := fs.Cwd()
|
|
||||||
|
|
||||||
// Install backend deps - needed?
|
|
||||||
// if projectOptions.FrontEnd != nil {
|
|
||||||
// // Install frontend deps
|
|
||||||
// err = os.Chdir(projectOptions.FrontEnd.Dir)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Check if frontend deps have been updated
|
|
||||||
// feSpinner := spinner.New("Installing frontend dependencies (This may take a while)...")
|
|
||||||
// feSpinner.SetSpinSpeed(50)
|
|
||||||
// feSpinner.Start()
|
|
||||||
|
|
||||||
// requiresNPMInstall := true
|
|
||||||
|
|
||||||
// // Read in package.json MD5
|
|
||||||
// packageJSONMD5, err := fs.FileMD5("package.json")
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const md5sumFile = "package.json.md5"
|
|
||||||
|
|
||||||
// // If we aren't forcing the install and the md5sum file exists
|
|
||||||
// if !forceRebuild && fs.FileExists(md5sumFile) {
|
|
||||||
// // Yes - read contents
|
|
||||||
// savedMD5sum, err := fs.LoadAsString(md5sumFile)
|
|
||||||
// // File exists
|
|
||||||
// if err == nil {
|
|
||||||
// // Compare md5
|
|
||||||
// if savedMD5sum == packageJSONMD5 {
|
|
||||||
// // Same - no need for reinstall
|
|
||||||
// requiresNPMInstall = false
|
|
||||||
// feSpinner.Success("Skipped frontend dependencies (-f to force rebuild)")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Md5 sum package.json
|
|
||||||
// // Different? Build
|
|
||||||
// if requiresNPMInstall || forceRebuild {
|
|
||||||
// // Install dependencies
|
|
||||||
// err = program.RunCommand(projectOptions.FrontEnd.Install)
|
|
||||||
// if err != nil {
|
|
||||||
// feSpinner.Error()
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// feSpinner.Success()
|
|
||||||
|
|
||||||
// // Update md5sum file
|
|
||||||
// ioutil.WriteFile(md5sumFile, []byte(packageJSONMD5), 0644)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Copy bridge to project
|
|
||||||
var bridgeFile = "wailsbridge.js"
|
|
||||||
_, filename, _, _ := runtime.Caller(1)
|
|
||||||
bridgeFileSource := filepath.Join(path.Dir(filename), "..", "assets", "default", bridgeFile)
|
|
||||||
bridgeFileTarget := filepath.Join(projectDir, projectOptions.FrontEnd.Dir, projectOptions.FrontEnd.Bridge, "wailsbridge.js")
|
|
||||||
err = fs.CopyFile(bridgeFileSource, bridgeFileTarget)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Build frontend
|
// Program checker
|
||||||
// buildFESpinner := spinner.New("Building frontend...")
|
program := cmd.NewProgramHelper()
|
||||||
// buildFESpinner.SetSpinSpeed(50)
|
|
||||||
// buildFESpinner.Start()
|
if projectOptions.FrontEnd != nil {
|
||||||
// err = program.RunCommand(projectOptions.FrontEnd.Build)
|
// npm
|
||||||
// if err != nil {
|
if !program.IsInstalled("npm") {
|
||||||
// buildFESpinner.Error()
|
return fmt.Errorf("it appears npm is not installed. Please install and run again")
|
||||||
// return err
|
}
|
||||||
// }
|
}
|
||||||
// buildFESpinner.Success()
|
|
||||||
// }
|
// Check Packr is installed
|
||||||
|
err = cmd.CheckPackr()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save project directory
|
||||||
|
// TODO: Remove compiling frontend once packr
|
||||||
|
// allows optional boxes
|
||||||
|
projectDir := fs.Cwd()
|
||||||
|
|
||||||
|
// Install deps
|
||||||
|
if projectOptions.FrontEnd != nil {
|
||||||
|
err = cmd.InstallFrontendDeps(projectDir, projectOptions, forceRebuild, "serve")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Run packr in project directory
|
// Run packr in project directory
|
||||||
err = os.Chdir(projectDir)
|
err = os.Chdir(projectDir)
|
||||||
@@ -168,69 +80,19 @@ func init() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support build tags
|
// Install dependencies
|
||||||
buildTags := []string{}
|
err = cmd.InstallGoDependencies()
|
||||||
|
|
||||||
depSpinner := spinner.New("Installing Dependencies...")
|
|
||||||
depSpinner.SetSpinSpeed(50)
|
|
||||||
depSpinner.Start()
|
|
||||||
installCommand := "go get"
|
|
||||||
err = program.RunCommand(installCommand)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
depSpinner.Error()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
depSpinner.Success()
|
|
||||||
|
|
||||||
compileMessage := "Packing + Compiling project"
|
buildMode := cmd.BuildModeBridge
|
||||||
|
err = cmd.BuildApplication(projectOptions.BinaryName, forceRebuild, buildMode)
|
||||||
packSpinner := spinner.New(compileMessage + "...")
|
|
||||||
packSpinner.SetSpinSpeed(50)
|
|
||||||
packSpinner.Start()
|
|
||||||
|
|
||||||
buildCommand := slicer.String()
|
|
||||||
buildCommand.AddSlice([]string{"packr", "build"})
|
|
||||||
|
|
||||||
// Add build tags
|
|
||||||
if len(buildTags) > 0 {
|
|
||||||
buildCommand.Add("--tags")
|
|
||||||
buildCommand.AddSlice(buildTags)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if projectOptions.BinaryName != "" {
|
|
||||||
buildCommand.Add("-o")
|
|
||||||
buildCommand.Add(projectOptions.BinaryName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are forcing a rebuild
|
|
||||||
if forceRebuild {
|
|
||||||
buildCommand.Add("-a")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = program.RunCommandArray(buildCommand.AsSlice())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
packSpinner.Error()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
packSpinner.Success()
|
|
||||||
|
|
||||||
// Run the App
|
|
||||||
logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
|
logger.Yellow("Awesome! Project '%s' built!", projectOptions.Name)
|
||||||
go func() {
|
return cmd.ServeProject(projectOptions, logger)
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
logger.Green(">>>>> To connect, you will need to run '" + projectOptions.FrontEnd.Serve + "' in the '" + projectOptions.FrontEnd.Dir + "' directory <<<<<")
|
|
||||||
}()
|
|
||||||
logger.Yellow("Serving Application: " + projectOptions.BinaryName)
|
|
||||||
cmd := exec.Command(projectOptions.BinaryName)
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err = cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
5
go.mod
5
go.mod
@@ -14,14 +14,11 @@ require (
|
|||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||||
github.com/leaanthony/slicer v0.0.0-20190110113548-aa9ea12f976a
|
github.com/leaanthony/slicer v0.0.0-20190110113548-aa9ea12f976a
|
||||||
github.com/leaanthony/spinner v0.5.0
|
github.com/leaanthony/spinner v0.5.0
|
||||||
github.com/leaanthony/synx v0.0.0-20180923230033-60efbd9984b0 // indirect
|
|
||||||
github.com/leaanthony/wincursor v0.0.0-20180705115120-056510f32d15 // indirect
|
|
||||||
github.com/mattn/go-colorable v0.0.9 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.4 // indirect
|
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||||
github.com/mitchellh/go-homedir v1.0.0
|
github.com/mitchellh/go-homedir v1.0.0
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||||
github.com/sirupsen/logrus v1.2.0
|
github.com/sirupsen/logrus v1.2.0
|
||||||
|
github.com/wailsapp/webview v0.2.0
|
||||||
golang.org/x/net v0.0.0-20190107155100-1a61f4433d85 // indirect
|
golang.org/x/net v0.0.0-20190107155100-1a61f4433d85 // indirect
|
||||||
gopkg.in/AlecAivazis/survey.v1 v1.7.1 // indirect
|
gopkg.in/AlecAivazis/survey.v1 v1.7.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
35
go.sum
35
go.sum
@@ -3,7 +3,6 @@ github.com/AlecAivazis/survey v1.7.1/go.mod h1:MVECab6WqEH1aXhj8nKIwF7HEAJAj2bhh
|
|||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||||
@@ -13,7 +12,6 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
|
|||||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc h1:VBS1z48BFEe00G81z8MKOtwX7f/ISkuH38NscT8iVPw=
|
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc h1:VBS1z48BFEe00G81z8MKOtwX7f/ISkuH38NscT8iVPw=
|
||||||
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc/go.mod h1:ABJPuor7YlcsHmvJ1QxX38e2NcufLY3hm0yXv+cy9sI=
|
github.com/dchest/cssmin v0.0.0-20151210170030-fb8d9b44afdc/go.mod h1:ABJPuor7YlcsHmvJ1QxX38e2NcufLY3hm0yXv+cy9sI=
|
||||||
@@ -188,6 +186,8 @@ github.com/gobuffalo/x v0.0.0-20181007152206-913e47c59ca7/go.mod h1:9rDPXaB3kXdK
|
|||||||
github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||||
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
|
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
|
||||||
@@ -212,7 +212,6 @@ github.com/karrick/godirwalk v1.7.7/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46s
|
|||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
@@ -220,14 +219,11 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/leaanthony/slicer v0.0.0-20190110113548-aa9ea12f976a h1:+nH6CKt4ZdMj+AabQrU0SLtZWYyQ1ovzLCA21se+raw=
|
github.com/leaanthony/slicer v0.0.0-20190110113548-aa9ea12f976a h1:+nH6CKt4ZdMj+AabQrU0SLtZWYyQ1ovzLCA21se+raw=
|
||||||
github.com/leaanthony/slicer v0.0.0-20190110113548-aa9ea12f976a/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ=
|
github.com/leaanthony/slicer v0.0.0-20190110113548-aa9ea12f976a/go.mod h1:VMB/HGvr3uR3MRpFWHWAm0w+DHQLzPHYe2pKfpFlQIQ=
|
||||||
github.com/leaanthony/spinner v0.4.0 h1:y/7FqQqqObRKYI+33bg9DGhHIY7cQHicm+Vz0Uda0Ik=
|
github.com/leaanthony/spinner v0.5.0 h1:HQykt/iTy7fmINEREtRbWrt+8j4MxC8dtvWBxEWM9oA=
|
||||||
github.com/leaanthony/spinner v0.4.0/go.mod h1:2Mmv+8Brcw3NwPT1DdOLmW6+zWpSamDDFFsUvVHo2cc=
|
github.com/leaanthony/spinner v0.5.0/go.mod h1:8TSFz9SL1AUC4XSbEFYE6SfN5Mlus51qYluVGrie9ww=
|
||||||
github.com/leaanthony/spinner v0.5.0 h1:OJKn+0KP6ilHxwCEOv5Lo0wPM4PgWZWLJTeUprGJK0g=
|
github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8=
|
||||||
github.com/leaanthony/spinner v0.5.0/go.mod h1:2Mmv+8Brcw3NwPT1DdOLmW6+zWpSamDDFFsUvVHo2cc=
|
github.com/leaanthony/synx v0.1.0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs=
|
||||||
github.com/leaanthony/synx v0.0.0-20180923230033-60efbd9984b0 h1:1bGojw4YacLY5bqQalojiQ7mSfQbe4WIWCEgPZagowU=
|
github.com/leaanthony/wincursor v0.1.0/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE=
|
||||||
github.com/leaanthony/synx v0.0.0-20180923230033-60efbd9984b0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs=
|
|
||||||
github.com/leaanthony/wincursor v0.0.0-20180705115120-056510f32d15 h1:166LIty6ldcyOc7tbgfu5smsGATvEo0JZV6bnbzyEc4=
|
|
||||||
github.com/leaanthony/wincursor v0.0.0-20180705115120-056510f32d15/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE=
|
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/markbates/deplist v1.0.4/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM=
|
github.com/markbates/deplist v1.0.4/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM=
|
||||||
@@ -253,6 +249,7 @@ github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRU
|
|||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
@@ -265,6 +262,7 @@ github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGE
|
|||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
|
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
|
||||||
|
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
@@ -273,8 +271,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
|
|||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/ribice/glice v0.0.0-20181011133736-685f13fa9b12/go.mod h1:A+ednilkKNW0CJGLsrLkq0D49M4EhlCi8gvnkwoZFn0=
|
||||||
github.com/rogpeppe/go-internal v1.0.0 h1:o4VLZ5jqHE+HahLT6drNtSGTrrUA3wPBmtpgqtdbClo=
|
github.com/rogpeppe/go-internal v1.0.0 h1:o4VLZ5jqHE+HahLT6drNtSGTrrUA3wPBmtpgqtdbClo=
|
||||||
github.com/rogpeppe/go-internal v1.0.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.0.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
@@ -304,13 +302,16 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
|||||||
github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI=
|
github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI=
|
||||||
github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
github.com/unrolled/secure v0.0.0-20180918153822-f340ee86eb8b/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA=
|
github.com/unrolled/secure v0.0.0-20180918153822-f340ee86eb8b/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA=
|
||||||
github.com/unrolled/secure v0.0.0-20181005190816-ff9db2ff917f/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA=
|
github.com/unrolled/secure v0.0.0-20181005190816-ff9db2ff917f/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA=
|
||||||
github.com/wailsapp/wails v0.0.0-20181215232634-5de8efff325d h1:lk91T4sKD98eGcaz/xC6ER+3o9Kaun7Mk8e/cNZOPMc=
|
github.com/wailsapp/webview v0.0.0-20190206214557-b5fea5042a9e h1:ZT5ZZWHIKrzXWAPME5rcbt1G4sgFyPF9FucugY60jV0=
|
||||||
|
github.com/wailsapp/webview v0.0.0-20190206214557-b5fea5042a9e/go.mod h1:XO9HJbKWokDxUYTWQEBCYg95n/To1v7PxvanDNVf8hY=
|
||||||
|
github.com/wailsapp/webview v0.2.0 h1:V3j112ECWIo6LSspWKyiBlEbQAhEPu+bnT1AK8eFNr4=
|
||||||
|
github.com/wailsapp/webview v0.2.0/go.mod h1:XO9HJbKWokDxUYTWQEBCYg95n/To1v7PxvanDNVf8hY=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
github.com/zserge/webview v0.0.0-20190123072648-16c93bcaeaeb/go.mod h1:a1CV8KR4Dd1eP2g+mEijGOp+HKczwdKHWyx0aPHKvo4=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
@@ -336,10 +337,11 @@ golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73r
|
|||||||
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181207154023-610586996380 h1:zPQexyRtNYBc7bcHmehl1dH6TB3qn8zytv8cBGLDNY0=
|
|
||||||
golang.org/x/net v0.0.0-20181207154023-610586996380/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181207154023-610586996380/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190107155100-1a61f4433d85 h1:3DfFuyqY+mca6oIDfim5rft3+Kl/CHLe7RdPrUMzwv0=
|
golang.org/x/net v0.0.0-20190107155100-1a61f4433d85 h1:3DfFuyqY+mca6oIDfim5rft3+Kl/CHLe7RdPrUMzwv0=
|
||||||
golang.org/x/net v0.0.0-20190107155100-1a61f4433d85/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190107155100-1a61f4433d85/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -358,8 +360,9 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||||||
golang.org/x/sys v0.0.0-20181106135930-3a76605856fd/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181106135930-3a76605856fd/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e h1:njOxP/wVblhCLIUhjHXf6X+dzTt5OQ3vMQo9mkOIKIo=
|
|
||||||
golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb h1:pf3XwC90UUdNPYWZdFjhGBE7DUFuK3Ct1zWmZ65QN30=
|
||||||
|
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181003024731-2f84ea8ef872/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181003024731-2f84ea8ef872/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ func (h *Headless) wsBridgeHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
|
http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
h.theConnection = conn
|
h.theConnection = conn
|
||||||
h.log.Infof("Connection from frontend accepted.", h.theConnection)
|
h.log.Infof("Connection from frontend accepted [%p].", h.theConnection)
|
||||||
conn.SetCloseHandler(func(int, string) error {
|
conn.SetCloseHandler(func(int, string) error {
|
||||||
h.log.Infof("Connection dropped [%p].", h.theConnection)
|
h.log.Infof("Connection dropped [%p].", h.theConnection)
|
||||||
h.theConnection = nil
|
h.theConnection = nil
|
||||||
@@ -118,11 +118,6 @@ func (h *Headless) start(conn *websocket.Conn) {
|
|||||||
wailsRuntime := BoxString(&defaultAssets, "wails.js")
|
wailsRuntime := BoxString(&defaultAssets, "wails.js")
|
||||||
h.evalJS(wailsRuntime, wailsRuntimeMessage)
|
h.evalJS(wailsRuntime, wailsRuntimeMessage)
|
||||||
|
|
||||||
// Inject the initial JS
|
|
||||||
for _, js := range h.initialisationJS {
|
|
||||||
h.sendMessage(h.theConnection, js)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inject bindings
|
// Inject bindings
|
||||||
for _, binding := range h.bindingCache {
|
for _, binding := range h.bindingCache {
|
||||||
h.evalJS(binding, bindingMessage)
|
h.evalJS(binding, bindingMessage)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/go-playground/colors"
|
"github.com/go-playground/colors"
|
||||||
"github.com/gobuffalo/packr"
|
"github.com/gobuffalo/packr"
|
||||||
"github.com/wailsapp/wails/webview"
|
"github.com/wailsapp/webview"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Window defines the main application window
|
// Window defines the main application window
|
||||||
|
|||||||
5
utils.go
5
utils.go
@@ -4,6 +4,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/cmd"
|
||||||
|
|
||||||
"github.com/gobuffalo/packr"
|
"github.com/gobuffalo/packr"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,6 +20,9 @@ func escapeJS(js string) (string, error) {
|
|||||||
func BoxString(box *packr.Box, filename string) string {
|
func BoxString(box *packr.Box, filename string) string {
|
||||||
result, err := box.FindString(filename)
|
result, err := box.FindString(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if BuildMode == cmd.BuildModeBridge {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2017 Serge Zaitsev
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -1,372 +0,0 @@
|
|||||||
// Package wails implements Go bindings to https://github.com/zserge/webview C library.
|
|
||||||
// It is a modified version of webview.go from that repository
|
|
||||||
|
|
||||||
// Bindings closely repeat the C APIs and include both, a simplified
|
|
||||||
// single-function API to just open a full-screen webview window, and a more
|
|
||||||
// advanced and featureful set of APIs, including Go-to-JavaScript bindings.
|
|
||||||
//
|
|
||||||
// The library uses gtk-webkit, Cocoa/Webkit and MSHTML (IE8..11) as a browser
|
|
||||||
// engine and supports Linux, MacOS and Windows 7..10 respectively.
|
|
||||||
//
|
|
||||||
package webview
|
|
||||||
|
|
||||||
/*
|
|
||||||
#cgo linux openbsd freebsd CFLAGS: -DWEBVIEW_GTK=1
|
|
||||||
#cgo linux openbsd freebsd pkg-config: gtk+-3.0 webkit2gtk-4.0
|
|
||||||
|
|
||||||
#cgo windows CFLAGS: -DWEBVIEW_WINAPI=1
|
|
||||||
#cgo windows LDFLAGS: -lole32 -lcomctl32 -loleaut32 -luuid -lgdi32
|
|
||||||
|
|
||||||
#cgo darwin CFLAGS: -DWEBVIEW_COCOA=1 -x objective-c
|
|
||||||
#cgo darwin LDFLAGS: -framework Cocoa -framework WebKit
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#define WEBVIEW_STATIC
|
|
||||||
#define WEBVIEW_IMPLEMENTATION
|
|
||||||
#include "webview.h"
|
|
||||||
|
|
||||||
extern void _webviewExternalInvokeCallback(void *, void *);
|
|
||||||
|
|
||||||
static inline void CgoWebViewFree(void *w) {
|
|
||||||
free((void *)((struct webview *)w)->title);
|
|
||||||
free((void *)((struct webview *)w)->url);
|
|
||||||
free(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void *CgoWebViewCreate(int width, int height, char *title, char *url, int resizable, int debug) {
|
|
||||||
struct webview *w = (struct webview *) calloc(1, sizeof(*w));
|
|
||||||
w->width = width;
|
|
||||||
w->height = height;
|
|
||||||
w->title = title;
|
|
||||||
w->url = url;
|
|
||||||
w->resizable = resizable;
|
|
||||||
w->debug = debug;
|
|
||||||
w->external_invoke_cb = (webview_external_invoke_cb_t) _webviewExternalInvokeCallback;
|
|
||||||
if (webview_init(w) != 0) {
|
|
||||||
CgoWebViewFree(w);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return (void *)w;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int CgoWebViewLoop(void *w, int blocking) {
|
|
||||||
return webview_loop((struct webview *)w, blocking);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void CgoWebViewTerminate(void *w) {
|
|
||||||
webview_terminate((struct webview *)w);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void CgoWebViewExit(void *w) {
|
|
||||||
webview_exit((struct webview *)w);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void CgoWebViewSetTitle(void *w, char *title) {
|
|
||||||
webview_set_title((struct webview *)w, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void CgoWebViewSetFullscreen(void *w, int fullscreen) {
|
|
||||||
webview_set_fullscreen((struct webview *)w, fullscreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void CgoWebViewSetColor(void *w, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
|
||||||
webview_set_color((struct webview *)w, r, g, b, a);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void CgoDialog(void *w, int dlgtype, int flags,
|
|
||||||
char *title, char *arg, char *res, size_t ressz) {
|
|
||||||
webview_dialog(w, dlgtype, flags,
|
|
||||||
(const char*)title, (const char*) arg, res, ressz);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int CgoWebViewEval(void *w, char *js) {
|
|
||||||
return webview_eval((struct webview *)w, js);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void CgoWebViewInjectCSS(void *w, char *css) {
|
|
||||||
webview_inject_css((struct webview *)w, css);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void _webviewDispatchGoCallback(void *);
|
|
||||||
static inline void _webview_dispatch_cb(struct webview *w, void *arg) {
|
|
||||||
_webviewDispatchGoCallback(arg);
|
|
||||||
}
|
|
||||||
static inline void CgoWebViewDispatch(void *w, uintptr_t arg) {
|
|
||||||
webview_dispatch((struct webview *)w, _webview_dispatch_cb, (void *)arg);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Ensure that main.main is called from the main thread
|
|
||||||
runtime.LockOSThread()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open is a simplified API to open a single native window with a full-size webview in
|
|
||||||
// it. It can be helpful if you want to communicate with the core app using XHR
|
|
||||||
// or WebSockets (as opposed to using JavaScript bindings).
|
|
||||||
//
|
|
||||||
// Window appearance can be customized using title, width, height and resizable parameters.
|
|
||||||
// URL must be provided and can user either a http or https protocol, or be a
|
|
||||||
// local file:// URL. On some platforms "data:" URLs are also supported
|
|
||||||
// (Linux/MacOS).
|
|
||||||
func Open(title, url string, w, h int, resizable bool) error {
|
|
||||||
titleStr := C.CString(title)
|
|
||||||
defer C.free(unsafe.Pointer(titleStr))
|
|
||||||
urlStr := C.CString(url)
|
|
||||||
defer C.free(unsafe.Pointer(urlStr))
|
|
||||||
resize := C.int(0)
|
|
||||||
if resizable {
|
|
||||||
resize = C.int(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
r := C.webview(titleStr, urlStr, C.int(w), C.int(h), resize)
|
|
||||||
if r != 0 {
|
|
||||||
return errors.New("failed to create webview")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExternalInvokeCallbackFunc is a function type that is called every time
|
|
||||||
// "window.external.invoke()" is called from JavaScript. Data is the only
|
|
||||||
// obligatory string parameter passed into the "invoke(data)" function from
|
|
||||||
// JavaScript. To pass more complex data serialized JSON or base64 encoded
|
|
||||||
// string can be used.
|
|
||||||
type ExternalInvokeCallbackFunc func(w WebView, data string)
|
|
||||||
|
|
||||||
// Settings is a set of parameters to customize the initial WebView appearance
|
|
||||||
// and behavior. It is passed into the webview.New() constructor.
|
|
||||||
type Settings struct {
|
|
||||||
// WebView main window title
|
|
||||||
Title string
|
|
||||||
// URL to open in a webview
|
|
||||||
URL string
|
|
||||||
// Window width in pixels
|
|
||||||
Width int
|
|
||||||
// Window height in pixels
|
|
||||||
Height int
|
|
||||||
// Allows/disallows window resizing
|
|
||||||
Resizable bool
|
|
||||||
// Enable debugging tools (Linux/BSD/MacOS, on Windows use Firebug)
|
|
||||||
Debug bool
|
|
||||||
// A callback that is executed when JavaScript calls "window.external.invoke()"
|
|
||||||
ExternalInvokeCallback ExternalInvokeCallbackFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebView is an interface that wraps the basic methods for controlling the UI
|
|
||||||
// loop, handling multithreading and providing JavaScript bindings.
|
|
||||||
type WebView interface {
|
|
||||||
// Run() starts the main UI loop until the user closes the webview window or
|
|
||||||
// Terminate() is called.
|
|
||||||
Run()
|
|
||||||
// Loop() runs a single iteration of the main UI.
|
|
||||||
Loop(blocking bool) bool
|
|
||||||
// SetTitle() changes window title. This method must be called from the main
|
|
||||||
// thread only. See Dispatch() for more details.
|
|
||||||
SetTitle(title string)
|
|
||||||
// SetFullscreen() controls window full-screen mode. This method must be
|
|
||||||
// called from the main thread only. See Dispatch() for more details.
|
|
||||||
SetFullscreen(fullscreen bool)
|
|
||||||
// SetColor() changes window background color. This method must be called from
|
|
||||||
// the main thread only. See Dispatch() for more details.
|
|
||||||
SetColor(r, g, b, a uint8)
|
|
||||||
// Eval() evaluates an arbitrary JS code inside the webview. This method must
|
|
||||||
// be called from the main thread only. See Dispatch() for more details.
|
|
||||||
Eval(js string) error
|
|
||||||
// InjectJS() injects an arbitrary block of CSS code using the JS API. This
|
|
||||||
// method must be called from the main thread only. See Dispatch() for more
|
|
||||||
// details.
|
|
||||||
InjectCSS(css string)
|
|
||||||
// Dialog() opens a system dialog of the given type and title. String
|
|
||||||
// argument can be provided for certain dialogs, such as alert boxes. For
|
|
||||||
// alert boxes argument is a message inside the dialog box.
|
|
||||||
Dialog(dlgType DialogType, flags int, title string, arg string) string
|
|
||||||
// Terminate() breaks the main UI loop. This method must be called from the main thread
|
|
||||||
// only. See Dispatch() for more details.
|
|
||||||
Terminate()
|
|
||||||
// Dispatch() schedules some arbitrary function to be executed on the main UI
|
|
||||||
// thread. This may be helpful if you want to run some JavaScript from
|
|
||||||
// background threads/goroutines, or to terminate the app.
|
|
||||||
Dispatch(func())
|
|
||||||
// Exit() closes the window and cleans up the resources. Use Terminate() to
|
|
||||||
// forcefully break out of the main UI loop.
|
|
||||||
Exit()
|
|
||||||
}
|
|
||||||
|
|
||||||
// DialogType is an enumeration of all supported system dialog types
|
|
||||||
type DialogType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
// DialogTypeOpen is a system file open dialog
|
|
||||||
DialogTypeOpen DialogType = iota
|
|
||||||
// DialogTypeSave is a system file save dialog
|
|
||||||
DialogTypeSave
|
|
||||||
// DialogTypeAlert is a system alert dialog (message box)
|
|
||||||
DialogTypeAlert
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// DialogFlagFile is a normal file picker dialog
|
|
||||||
DialogFlagFile = C.WEBVIEW_DIALOG_FLAG_FILE
|
|
||||||
// DialogFlagDirectory is an open directory dialog
|
|
||||||
DialogFlagDirectory = C.WEBVIEW_DIALOG_FLAG_DIRECTORY
|
|
||||||
// DialogFlagInfo is an info alert dialog
|
|
||||||
DialogFlagInfo = C.WEBVIEW_DIALOG_FLAG_INFO
|
|
||||||
// DialogFlagWarning is a warning alert dialog
|
|
||||||
DialogFlagWarning = C.WEBVIEW_DIALOG_FLAG_WARNING
|
|
||||||
// DialogFlagError is an error dialog
|
|
||||||
DialogFlagError = C.WEBVIEW_DIALOG_FLAG_ERROR
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
m sync.Mutex
|
|
||||||
index uintptr
|
|
||||||
fns = map[uintptr]func(){}
|
|
||||||
cbs = map[WebView]ExternalInvokeCallbackFunc{}
|
|
||||||
)
|
|
||||||
|
|
||||||
type webview struct {
|
|
||||||
w unsafe.Pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ WebView = &webview{}
|
|
||||||
|
|
||||||
func boolToInt(b bool) int {
|
|
||||||
if b {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWebview creates and opens a new webview window using the given settings. The
|
|
||||||
// returned object implements the WebView interface. This function returns nil
|
|
||||||
// if a window can not be created.
|
|
||||||
func NewWebview(settings Settings) WebView {
|
|
||||||
if settings.Width == 0 {
|
|
||||||
settings.Width = 640
|
|
||||||
}
|
|
||||||
if settings.Height == 0 {
|
|
||||||
settings.Height = 480
|
|
||||||
}
|
|
||||||
if settings.Title == "" {
|
|
||||||
settings.Title = "WebView"
|
|
||||||
}
|
|
||||||
w := &webview{}
|
|
||||||
w.w = C.CgoWebViewCreate(C.int(settings.Width), C.int(settings.Height),
|
|
||||||
C.CString(settings.Title), C.CString(settings.URL),
|
|
||||||
C.int(boolToInt(settings.Resizable)), C.int(boolToInt(settings.Debug)))
|
|
||||||
m.Lock()
|
|
||||||
if settings.ExternalInvokeCallback != nil {
|
|
||||||
cbs[w] = settings.ExternalInvokeCallback
|
|
||||||
} else {
|
|
||||||
cbs[w] = func(w WebView, data string) {}
|
|
||||||
}
|
|
||||||
m.Unlock()
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *webview) Loop(blocking bool) bool {
|
|
||||||
block := C.int(0)
|
|
||||||
if blocking {
|
|
||||||
block = 1
|
|
||||||
}
|
|
||||||
return C.CgoWebViewLoop(w.w, block) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *webview) Run() {
|
|
||||||
for w.Loop(true) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *webview) Exit() {
|
|
||||||
C.CgoWebViewExit(w.w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *webview) Dispatch(f func()) {
|
|
||||||
m.Lock()
|
|
||||||
for ; fns[index] != nil; index++ {
|
|
||||||
}
|
|
||||||
fns[index] = f
|
|
||||||
m.Unlock()
|
|
||||||
C.CgoWebViewDispatch(w.w, C.uintptr_t(index))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *webview) SetTitle(title string) {
|
|
||||||
p := C.CString(title)
|
|
||||||
defer C.free(unsafe.Pointer(p))
|
|
||||||
C.CgoWebViewSetTitle(w.w, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *webview) SetColor(r, g, b, a uint8) {
|
|
||||||
C.CgoWebViewSetColor(w.w, C.uint8_t(r), C.uint8_t(g), C.uint8_t(b), C.uint8_t(a))
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
const maxPath = 4096
|
|
||||||
titlePtr := C.CString(title)
|
|
||||||
defer C.free(unsafe.Pointer(titlePtr))
|
|
||||||
argPtr := C.CString(arg)
|
|
||||||
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))
|
|
||||||
C.CgoDialog(w.w, C.int(dlgType), C.int(flags), titlePtr,
|
|
||||||
argPtr, resultPtr, C.size_t(maxPath))
|
|
||||||
return C.GoString(resultPtr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *webview) Eval(js string) error {
|
|
||||||
p := C.CString(js)
|
|
||||||
defer C.free(unsafe.Pointer(p))
|
|
||||||
switch C.CgoWebViewEval(w.w, p) {
|
|
||||||
case -1:
|
|
||||||
return errors.New("evaluation failed")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *webview) InjectCSS(css string) {
|
|
||||||
p := C.CString(css)
|
|
||||||
defer C.free(unsafe.Pointer(p))
|
|
||||||
C.CgoWebViewInjectCSS(w.w, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *webview) Terminate() {
|
|
||||||
C.CgoWebViewTerminate(w.w)
|
|
||||||
}
|
|
||||||
|
|
||||||
//export _webviewDispatchGoCallback
|
|
||||||
func _webviewDispatchGoCallback(index unsafe.Pointer) {
|
|
||||||
var f func()
|
|
||||||
m.Lock()
|
|
||||||
f = fns[uintptr(index)]
|
|
||||||
delete(fns, uintptr(index))
|
|
||||||
m.Unlock()
|
|
||||||
f()
|
|
||||||
}
|
|
||||||
|
|
||||||
//export _webviewExternalInvokeCallback
|
|
||||||
func _webviewExternalInvokeCallback(w unsafe.Pointer, data unsafe.Pointer) {
|
|
||||||
m.Lock()
|
|
||||||
var (
|
|
||||||
cb ExternalInvokeCallbackFunc
|
|
||||||
wv WebView
|
|
||||||
)
|
|
||||||
for wv, cb = range cbs {
|
|
||||||
if wv.(*webview).w == w {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Unlock()
|
|
||||||
cb(wv, C.GoString((*C.char)(data)))
|
|
||||||
}
|
|
||||||
1927
webview/webview.h
1927
webview/webview.h
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user