Skip to content

Commit

Permalink
feat: embed icons into executable
Browse files Browse the repository at this point in the history
  • Loading branch information
dennis-tra committed Oct 22, 2022
1 parent d30c107 commit 5a20a39
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 28 deletions.
103 changes: 76 additions & 27 deletions gui/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ package main

import (
"context"
_ "embed"
"io"
"os"
"path"
"sync/atomic"
"time"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
Expand All @@ -19,10 +23,15 @@ import (
"github.com/dennis-tra/punchr/pkg/client"
)

//go:embed glove-active.png
var gloveActive []byte

//go:embed glove-inactive.png
var gloveInactive []byte

var (
gloveActiveEmoji, _ = fyne.LoadResourceFromPath("./gui/client/glove-active.png")
gloveInactiveEmoji, _ = fyne.LoadResourceFromPath("./gui/client/glove-inactive.png")
apiKeyURI = storage.NewFileURI("punchr-client-api-key.txt")
gloveActiveEmoji = fyne.NewStaticResource("glove-active", gloveActive)
gloveInactiveEmoji = fyne.NewStaticResource("glove-inactive", gloveInactive)

sysTrayMenu *fyne.Menu
menuItemStatus = fyne.NewMenuItem("", nil)
Expand All @@ -32,19 +41,20 @@ var (
)

func main() {
execPath, err := os.Executable()
a := app.New()

p, err := NewPunchr(a)
if err != nil {
log.WithError(err).Errorln("Could not determine executable path")
log.WithError(err).Errorln("Could not instantiate new punchr")
os.Exit(1)
}

autostartApp := &autostart.App{
Name: "com.protocol.ai.punchr",
DisplayName: "Punchr Client",
Exec: []string{execPath},
Exec: []string{p.execPath},
}

a := app.New()
a.SetIcon(gloveInactiveEmoji)

desk, isDesktopApp := a.(desktop.App)
Expand All @@ -53,12 +63,10 @@ func main() {
return
}

p := NewPunchr(a)

menuItemStatus.Disabled = true
menuItemToggle.Label = "Start Hole Punching"
menuItemToggle.Action = func() {
if p.isHolePunching {
if p.isHolePunching.Load() {
go p.StopHolePunching()
} else {
go p.StartHolePunching()
Expand Down Expand Up @@ -108,29 +116,42 @@ type Punchr struct {
app fyne.App
hpCtx context.Context
hpCtxCancel context.CancelFunc
isHolePunching bool
isHolePunching *atomic.Bool
apiKey string
execPath string
apiKeyURI fyne.URI
}

func NewPunchr(app fyne.App) *Punchr {
apiKey, err := loadApiKey()
func NewPunchr(app fyne.App) (*Punchr, error) {
execPath, err := os.Executable()
if err != nil {
log.WithError(err).Warnln("error loading api key")
return nil, errors.Wrap(err, "determine executable path")
}

apiKeyURI := storage.NewFileURI(path.Join(path.Dir(execPath), "api-key.txt"))

apiKey, err := loadApiKey(apiKeyURI)
if err != nil && !errors.Is(err, os.ErrNotExist) {
log.WithError(err).Warnln("Error loading API Key")
}

return &Punchr{
app: app,
isHolePunching: false,
isHolePunching: &atomic.Bool{},
apiKey: apiKey,
}
execPath: execPath,
apiKeyURI: apiKeyURI,
}, nil
}

func (p *Punchr) ShowApiKeyDialog() {
window := p.app.NewWindow("Punchr")
window.Resize(fyne.NewSize(300, 100))

entry := widget.NewEntry()
entry.SetPlaceHolder("Please enter your API-Key")
entry.SetText(p.apiKey)

btn := widget.NewButton("Save", func() {
p.SaveApiKey(entry.Text)
menuItemToggle.Disabled = false
Expand All @@ -144,15 +165,17 @@ func (p *Punchr) ShowApiKeyDialog() {
btn.Enable()
}
}

if p.apiKey == "" {
btn.Disable()
}

window.SetContent(container.New(layout.NewVBoxLayout(), entry, btn))
window.Show()
}

func (p *Punchr) SaveApiKey(apiKey string) {
rwc, err := storage.Writer(apiKeyURI)
rwc, err := storage.Writer(p.apiKeyURI)
if err != nil {
log.WithError(err).Warnln("error opening storage writer")
return
Expand All @@ -169,31 +192,57 @@ func (p *Punchr) SaveApiKey(apiKey string) {
}

func (p *Punchr) StartHolePunching() {
if p.isHolePunching.Swap(true) {
return
}

desk := p.app.(desktop.App)

p.isHolePunching = true
desk.SetSystemTrayIcon(gloveActiveEmoji)
menuItemStatus.Label = "🟢 Running..."
menuItemToggle.Label = "Stop Hole Punching"
sysTrayMenu.Refresh()

ctx, cancel := context.WithCancel(context.Background())
p.hpCtx = ctx
p.hpCtxCancel = cancel

err := client.App.RunContext(p.hpCtx, []string{"punchrclient", "--api-key", p.apiKey})
if err != nil && p.hpCtx.Err() != context.Canceled {
menuItemStatus.Label = "Error: " + err.Error()
} else {
menuItemStatus.Label = "API-Key: " + p.apiKey
LOOP:
for {
menuItemStatus.Label = "🟢 Running..."
sysTrayMenu.Refresh()

err := client.App.RunContext(p.hpCtx, []string{
"punchrclient",
"--api-key", p.apiKey,
"--key-file", path.Join(path.Dir(p.execPath), "punchrclient.keys"),
"telemetry-host", "",
"telemetry-port", "",
})

if err == nil || errors.Is(p.hpCtx.Err(), context.Canceled) {
menuItemStatus.Label = "API-Key: " + p.apiKey
break
}

menuItemStatus.Label = "🟠 Retrying: " + err.Error()
sysTrayMenu.Refresh()

select {
case <-time.After(10 * time.Second):
continue
case <-p.hpCtx.Done():
menuItemStatus.Label = "🔴 Error: " + err.Error()
break LOOP
}
}

p.hpCtx = nil
p.hpCtxCancel = nil

p.isHolePunching = false
desk.SetSystemTrayIcon(gloveInactiveEmoji)
menuItemToggle.Label = "Start Hole Punching"
sysTrayMenu.Refresh()

p.isHolePunching.Swap(false)
}

func (p *Punchr) StopHolePunching() {
Expand All @@ -202,7 +251,7 @@ func (p *Punchr) StopHolePunching() {
}
}

func loadApiKey() (string, error) {
func loadApiKey(apiKeyURI fyne.URI) (string, error) {
r, err := storage.Reader(apiKeyURI)
if err != nil {
return "", errors.Wrap(err, "storage reader")
Expand Down
3 changes: 3 additions & 0 deletions pkg/client/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ func RootAction(c *cli.Context) error {
// serveTelemetry starts an HTTP server for the prometheus and pprof handler.
func serveTelemetry(c *cli.Context) {
addr := fmt.Sprintf("%s:%s", c.String("telemetry-host"), c.String("telemetry-port"))
if addr == ":" {
return
}
log.WithField("addr", addr).Debugln("Starting prometheus endpoint")

mux := http.NewServeMux()
Expand Down
2 changes: 1 addition & 1 deletion pkg/client/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (h *Host) Bootstrap(ctx context.Context) error {
errCount := 0
var lastErr error
for _, bp := range h.bpAddrInfos {
log.WithField("remoteID", util.FmtPeerID(bp.ID)).Info("Connecting to bootstrap peer...")
log.WithField("remoteID", util.FmtPeerID(bp.ID)).WithField("hostID", util.FmtPeerID(h.ID())).Info("Connecting to bootstrap peer...")
if err := h.Connect(ctx, bp); err != nil {
log.Warn("Error connecting to bootstrap peer ", bp)
errCount++
Expand Down

0 comments on commit 5a20a39

Please sign in to comment.