commit 6868af5a8a169796590b2e7ff6595f2166445b77
parent 1b72b6aa385e027db5af090d15ef2a3295f3803b
Author: Jack Mordaunt <jackmordaunt@gmail.com>
Date: Thu, 15 Nov 2018 12:32:37 +1300
[+] Automatically open and keep open a browser window for the app.
Diffstat:
2 files changed, 109 insertions(+), 15 deletions(-)
diff --git a/cmd/desktop/browser.go b/cmd/desktop/browser.go
@@ -0,0 +1,72 @@
+package main
+
+import (
+ "fmt"
+ "os/exec"
+ "runtime"
+ "time"
+
+ "github.com/pkg/errors"
+)
+
+// Browser opens the default browser for a given url.
+type Browser struct {
+ OnErr func(error)
+ OnRestart func()
+ Loop bool
+ failed chan error
+}
+
+// Open a browser window, re-opening it when closed if Loop is true.
+// Note: open simply uses OS default application, which may not actually be a
+// web browser.
+func (b *Browser) Open(u string) error {
+ cmd := b.open(u)
+ if cmd == nil {
+ return fmt.Errorf("not implemented on this OS")
+ }
+ b.failed = make(chan error)
+ if b.OnErr == nil {
+ b.OnErr = func(error) {}
+ }
+ if b.OnRestart == nil {
+ b.OnRestart = func() {}
+ }
+ go func() {
+ for {
+ cmd := b.open(u)
+ if err := func() error {
+ if out, err := cmd.CombinedOutput(); err != nil {
+ return errors.Wrap(err, string(out))
+ }
+ return nil
+ }(); err != nil {
+ b.failed <- err
+ }
+ if !b.Loop {
+ break
+ }
+ time.Sleep(time.Millisecond * 200)
+ b.OnRestart()
+ }
+ }()
+ go func() {
+ for err := range b.failed {
+ b.OnErr(err)
+ }
+ }()
+ return nil
+}
+
+func (Browser) open(u string) *exec.Cmd {
+ var cmd *exec.Cmd
+ switch runtime.GOOS {
+ case "darwin":
+ cmd = exec.Command("open", u, "-W")
+ case "linux":
+ cmd = exec.Command("xdg-open", u)
+ case "windows":
+ cmd = exec.Command("start", "/wait", "", u)
+ }
+ return cmd
+}
diff --git a/cmd/desktop/main.go b/cmd/desktop/main.go
@@ -6,6 +6,7 @@ import (
"log"
"net/http"
"net/url"
+ "sync"
"time"
"github.com/jackmordaunt/giffer"
@@ -18,18 +19,22 @@ import (
)
var (
+ host string
port string
devServer string
verbose bool
headless bool
+ browser bool
static http.Handler // responsible for serving UI files.
)
func init() {
+ flag.StringVar(&host, "host", "localhost", "host address to serve on")
flag.StringVar(&port, "p", "8080", "port to serve on")
flag.StringVar(&devServer, "dev-proxy", "", "proxy to forward to (eg, yarn run serve)")
flag.BoolVar(&verbose, "v", false, "verbose mode")
flag.BoolVar(&headless, "headless", false, "headless mode; run only the server")
+ flag.BoolVar(&browser, "browser", false, "open in default browser instead of webview; overriden by [headless]")
flag.Parse()
if devServer != "" {
t, err := url.Parse(devServer)
@@ -60,29 +65,46 @@ func main() {
Verbose: verbose,
}
svr := &http.Server{
- Addr: fmt.Sprintf(":%s", port),
+ Addr: fmt.Sprintf("%s:%s", host, port),
Handler: ui,
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
- if headless {
+ backend := sync.WaitGroup{}
+ defer backend.Wait()
+ backend.Add(1)
+ go func() {
+ defer backend.Done()
if err := svr.ListenAndServe(); err != nil {
log.Fatalf("ui server: %v", err)
}
+ }()
+ if headless {
return
}
- go func() {
- if err := svr.ListenAndServe(); err != nil {
- log.Fatalf("ui server: %v", err)
+ url := fmt.Sprintf("http://%s:%s", host, port)
+ if browser {
+ b := &Browser{
+ OnErr: func(err error) {
+ log.Printf("browser: %v", err)
+ },
+ Loop: true,
+ OnRestart: func() {
+ log.Printf("restarting browser")
+ },
}
- }()
- view := webview.New(webview.Settings{
- Title: "Giffer",
- URL: fmt.Sprintf("http://localhost:%s", port),
- Width: 800,
- Height: 600,
- Resizable: true,
- Debug: true,
- })
- view.Run()
+ if err := b.Open(url); err != nil {
+ log.Fatalf("opening browser: %v", err)
+ }
+ } else {
+ view := webview.New(webview.Settings{
+ Title: "Giffer",
+ URL: url,
+ Width: 800,
+ Height: 600,
+ Resizable: true,
+ Debug: true,
+ })
+ view.Run()
+ }
}