diff --git a/binding_manager.go b/binding_manager.go index 6a9411b6..f6a04f8f 100644 --- a/binding_manager.go +++ b/binding_manager.go @@ -163,8 +163,71 @@ func (b *bindingManager) bind(object interface{}) { 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 -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) // 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 // a decent error message // TODO: DEBUG THIS! + defer func() { if r := recover(); r != nil { err = fmt.Errorf("%s", r.(string)) @@ -191,59 +251,14 @@ func (b *bindingManager) processCall(callData *callData) (interface{}, error) { switch dotCount { case 1: - 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 + result, err = b.processFunctionCall(callData) case 2: - // 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 - + result, err = b.processMethodCall(callData) 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 diff --git a/cmd/frontend.go b/cmd/helpers.go similarity index 65% rename from cmd/frontend.go rename to cmd/helpers.go index bc23e211..f7814c94 100644 --- a/cmd/frontend.go +++ b/cmd/helpers.go @@ -2,6 +2,11 @@ package cmd import ( "fmt" + "io/ioutil" + "os" + "path" + "path/filepath" + "runtime" "github.com/leaanthony/slicer" "github.com/leaanthony/spinner" @@ -98,6 +103,95 @@ func BuildFrontend(buildCommand string) error { return nil } +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 +} + +func InstallFrontendDeps(projectDir string, projectOptions *ProjectOptions, forceRebuild bool) 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" + + // 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 +} + // func CopyBridgeFile(projectDir string, projectOptions ProjectOptions, bridgeMode bool) error { // // Copy bridge to project // fs := NewFSHelper() diff --git a/cmd/templates/vuewebpack/frontend/src/assets/css/main.css b/cmd/templates/vuewebpack/frontend/src/assets/css/main.css index 1a5e18b9..0eacd14b 100644 --- a/cmd/templates/vuewebpack/frontend/src/assets/css/main.css +++ b/cmd/templates/vuewebpack/frontend/src/assets/css/main.css @@ -12,8 +12,8 @@ html { 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, #151515 5px, transparent 5px) 10px 0, + linear-gradient(27deg, #222 5px, transparent 5px) 0 10px, linear-gradient(207deg, #222 5px, transparent 5px) 10px 5px, linear-gradient(90deg, #1b1b1b 10px, transparent 10px), linear-gradient( @@ -46,10 +46,8 @@ html { format("woff2"), /* Super Modern Browsers */ url("../fonts/roboto/roboto-v18-latin-regular.woff") format("woff"), - /* Modern Browsers */ - url("../fonts/roboto/roboto-v18-latin-regular.ttf") + /* Modern Browsers */ url("../fonts/roboto/roboto-v18-latin-regular.ttf") format("truetype"), /* Safari, Android, iOS */ - url("../fonts/roboto/roboto-v18-latin-regular.svg#Roboto") - format("svg"); /* Legacy iOS */ -} \ No newline at end of file + url("../fonts/roboto/roboto-v18-latin-regular.svg#Roboto") format("svg"); /* Legacy iOS */ +} diff --git a/cmd/templates/vuewebpack/frontend/src/assets/css/quote.css b/cmd/templates/vuewebpack/frontend/src/assets/css/quote.css index edfc8d3f..8d8ed8df 100644 --- a/cmd/templates/vuewebpack/frontend/src/assets/css/quote.css +++ b/cmd/templates/vuewebpack/frontend/src/assets/css/quote.css @@ -18,8 +18,12 @@ body { border-color: #117; } -p { margin-bottom: 1.5em; } -p:last-child { margin-bottom: 0; } +p { + margin-bottom: 1.5em; +} +p:last-child { + margin-bottom: 0; +} blockquote { display: block; @@ -32,9 +36,9 @@ blockquote { color: #117; } blockquote:before { - content: '\201C'; + content: "\201C"; position: absolute; - top: 0em; + top: 0; left: 50%; transform: translate(-50%, -50%); background: #fff; @@ -54,22 +58,22 @@ blockquote:after { /* 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; + 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; + text-decoration: none; + font-family: "Roboto", sans-serif; + font-weight: 300; font-size: 1em; - color:#000; - text-align:center; + color: #000; + text-align: center; transition: all 0.2s; } -button:hover{ - color:#FFF; - background-color:#000; +button:hover { + color: #fff; + background-color: #000; cursor: pointer; -} \ No newline at end of file +} diff --git a/cmd/wails/0_setup.go b/cmd/wails/0_setup.go index 8874ed3a..3baca906 100644 --- a/cmd/wails/0_setup.go +++ b/cmd/wails/0_setup.go @@ -5,7 +5,6 @@ import ( "runtime" "github.com/leaanthony/spinner" - "github.com/wailsapp/wails/cmd" ) @@ -31,64 +30,29 @@ Create your first project by running 'wails init'.` if runtime.GOOS != "windows" { successMessage = "🚀 " + successMessage } - 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) - } - - logger.Yellow("Checking for prerequisites...") - // Check we have a cgo capable environment - - requiredPrograms, err := cmd.GetRequiredPrograms() + // Platform check + err = platformCheck() if err != nil { return 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) - } + + // Check we have a cgo capable environment + logger.Yellow("Checking for prerequisites...") + errors, err := checkRequiredPrograms() + if err != nil { + return err } // Linux has library deps - if runtime.GOOS == "linux" { - // Check library prerequisites - requiredLibraries, err := cmd.GetRequiredLibraries() - 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) - } - } + errors, err = checkLibraries() + if err != nil { + return err } // packr + err = cmd.CheckPackr() + + programHelper := cmd.NewProgramHelper() if !programHelper.IsInstalled("packr") { buildSpinner := spinner.New() buildSpinner.SetSpinSpeed(50) @@ -110,3 +74,65 @@ Create your first project by running 'wails init'.` 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 +} diff --git a/cmd/wails/4_build.go b/cmd/wails/4_build.go index 93a8c444..2bb85983 100644 --- a/cmd/wails/4_build.go +++ b/cmd/wails/4_build.go @@ -2,11 +2,7 @@ package main import ( "fmt" - "io/ioutil" "os" - "path" - "path/filepath" - "runtime" "github.com/leaanthony/spinner" "github.com/wailsapp/wails/cmd" @@ -66,14 +62,9 @@ func init() { } // 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() + err = cmd.CheckPackr() + if err != nil { + return err } // Save project directory @@ -81,71 +72,7 @@ func init() { // Install deps 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) - } - - 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 - err = cmd.BuildFrontend(projectOptions.FrontEnd.Build) + err = cmd.InstallFrontendDeps(projectDir, projectOptions, forceRebuild) if err != nil { return err }