diff --git a/.vscode/settings.json b/.vscode/settings.json index 9ad0ab8..6270cdc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "cSpell.words": ["dlperf", "vastly", "vmem"], + "cSpell.words": ["assetserver", "dlperf", "vastly", "vmem", "wailsapp"], "cSpell.ignorePaths": [ "package-lock.json", "node_modules", diff --git a/api/go.mod b/api/go.mod index 266e80a..d250ba8 100644 --- a/api/go.mod +++ b/api/go.mod @@ -2,11 +2,16 @@ module xevion.dev/vastly/api go 1.23.3 -require go.uber.org/zap v1.27.0 +require ( + github.com/prometheus-community/pro-bing v0.5.0 + go.uber.org/zap v1.27.0 +) require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/google/uuid v1.6.0 // indirect - github.com/prometheus-community/pro-bing v0.5.0 // indirect + github.com/redis/go-redis/v9 v9.7.0 // indirect go.uber.org/multierr v1.10.0 // indirect golang.org/x/net v0.32.0 // indirect golang.org/x/sync v0.10.0 // indirect diff --git a/api/go.sum b/api/go.sum index 64ef269..159ce2e 100644 --- a/api/go.sum +++ b/api/go.sum @@ -1,7 +1,21 @@ +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/prometheus-community/pro-bing v0.5.0 h1:Fq+4BUXKIvsPtXUY8K+04ud9dkAuFozqGmRAyNUpffY= github.com/prometheus-community/pro-bing v0.5.0/go.mod h1:1joR9oXdMEAcAJJvhs+8vNDvTg5thfAZcRFhcUozG2g= +github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= +github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= @@ -12,3 +26,5 @@ golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/api/latency.go b/api/latency.go index 5c47915..4dbbbb6 100644 --- a/api/latency.go +++ b/api/latency.go @@ -1,18 +1,105 @@ package api -import probing "github.com/prometheus-community/pro-bing" +import ( + "errors" + "net" + "time" + + probing "github.com/prometheus-community/pro-bing" + "github.com/redis/go-redis/v9" + "go.uber.org/zap" +) + +type LatencyRequest struct { + RequestTime int64 + Ip net.IPAddr +} + +type LatencyQueue struct { + processChannel chan LatencyRequest + stopChannel chan bool + logger *zap.SugaredLogger + redis *redis.Client + pinger *probing.Pinger + handlerChannel chan<- PingResult +} + +func NewLatencyQueue() *LatencyQueue { + logger, _ := zap.NewDevelopment() + pinger, err := probing.NewPinger("127.0.0.1") + if err != nil { + logger.Fatal("Failed to create pinger") + } + pinger.Count = 1 + pinger.Interval = time.Millisecond * 850 + return &LatencyQueue{ + processChannel: make(chan LatencyRequest, 1024), + logger: logger.Sugar(), + redis: redis.NewClient(&redis.Options{}), + pinger: pinger, + } +} + +type PingRequest struct { + Ip net.IPAddr +} type PingResult struct { - Ip string - Latency float64 + Ip net.IPAddr + Latency int64 } -func GetLatency(ip string) (float64, error) { - pinger, err := probing.NewPinger(ip) - if err != nil { - return 0, err +func (l *LatencyQueue) QueuePing(ip string) error { + // Parse the IP + parsedIp := net.ParseIP(ip) + if parsedIp == nil { + return errors.New("Invalid IP address") } - pinger - return 0, nil + // Create the request + request := LatencyRequest{ + RequestTime: time.Now().Unix(), + Ip: net.IPAddr{IP: parsedIp}, + } + + // Add the request to the queue + l.processChannel <- request + + return nil +} + +func (l *LatencyQueue) Start() { + for { + select { + case request := <-l.processChannel: + + ip := request.Ip.String() + l.pinger.SetIPAddr(&request.Ip) + + // Process the request + err := l.pinger.Run() + if err != nil { + l.logger.Errorf("Failed to ping %s: %s", ip, err) + continue + } + + // Get the results + results := l.pinger.Statistics() + if (l.handlerChannel) != nil { + l.handlerChannel <- PingResult{ + Ip: request.Ip, + Latency: results.AvgRtt.Milliseconds(), + } + } + + case <-l.stopChannel: + return + } + } +} + +func (l *LatencyQueue) Kill() error { + l.stopChannel <- true + err := l.redis.Close() + return err } diff --git a/api/score.go b/api/score.go index 2eeca1b..08c295e 100644 --- a/api/score.go +++ b/api/score.go @@ -18,6 +18,7 @@ type ScoredOffer struct { Offer Offer Score float64 Reasons []ScoreReason + Latency *int32 } var ( diff --git a/app.go b/app.go index c8bd865..56e20d0 100644 --- a/app.go +++ b/app.go @@ -2,7 +2,6 @@ package main import ( "context" - "fmt" "os" "github.com/joho/godotenv" @@ -12,56 +11,60 @@ import ( // App struct type App struct { - ctx context.Context + ctx context.Context + client *api.Client + logger *zap.SugaredLogger + latency *api.LatencyQueue } // NewApp creates a new App application struct func NewApp() *App { - return &App{} + logger, _ := zap.NewDevelopment() + return &App{ + logger: logger.Sugar(), + latency: api.NewLatencyQueue(), + } } // startup is called when the app starts. The context is saved // so we can call the runtime methods func (a *App) startup(ctx context.Context) { a.ctx = ctx -} -// Greet returns a greeting for the given name -func (a *App) Greet(name string) string { - return fmt.Sprintf("Hello %s, It's show time!", name) -} - -func (a *App) Search() []api.ScoredOffer { - logger, _ := zap.NewDevelopment() - defer logger.Sync() - - sugar := logger.Sugar() // Load .env file if err := godotenv.Load(); err != nil { - sugar.Fatal(err) + a.logger.Fatal(err) } // Get API key from environment apiKey := os.Getenv("VASTAI_API_KEY") if apiKey == "" { - sugar.Fatal("VASTAI_API_KEY not found in environment") + a.logger.Fatal("VASTAI_API_KEY not found in environment") } + a.client = api.NewClient(apiKey) - // Create client - client := api.NewClient(apiKey) + // Start latency queue + go a.latency.Start() +} + +func (a *App) beforeClose(ctx context.Context) bool { + a.latency.Kill() + return false +} + +func (a *App) Search() []api.ScoredOffer { + defer a.logger.Sync() // Create search search := api.NewSearch() search.AllocatedStorage = 39.94657756485159 search.Limit = 1000 - // search.Rentable = api.Pointer(true) - // search.CPUCores = api.Ge(8) // Perform search - sugar.Infow("Searching", "search", search) - resp, err := client.Search(search) + a.logger.Infow("Searching", "search", search) + resp, err := a.client.Search(search) if err != nil { - sugar.Fatal(err) + a.logger.Fatal(err) } return api.ScoreOffers(resp.Offers) diff --git a/frontend/src/components/Offer.tsx b/frontend/src/components/Offer.tsx index f5ce82c..18207e1 100644 --- a/frontend/src/components/Offer.tsx +++ b/frontend/src/components/Offer.tsx @@ -4,7 +4,7 @@ import { cn } from "@src/utils"; import { Tooltip } from "react-tooltip"; export default function Offer({ - offer: { Offer: offer, Score: score, Reasons: reasons }, + offer: { Offer: offer, Score: score, Reasons: reasons, Latency: latency }, }: { offer: api.ScoredOffer; }) { @@ -25,10 +25,14 @@ export default function Offer({ {score >= 10 ? Math.round(score) : score.toFixed(1)} - + {offer.num_gpus}x {offer.gpu_name}{" "} {mb_to_gb(offer.gpu_ram)} GB + + {latency ?? "?"} + ms +
${offer.search.totalHour.toFixed(2)}/hr diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 21a59cf..c9e122d 100644 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -2,6 +2,4 @@ // This file is automatically generated. DO NOT EDIT import {api} from '../models'; -export function Greet(arg1:string):Promise; - export function Search():Promise>; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index 9d57b50..ea76443 100644 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -2,10 +2,6 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT -export function Greet(arg1) { - return window['go']['main']['App']['Greet'](arg1); -} - export function Search() { return window['go']['main']['App']['Search'](); } diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index b45aa20..e87feb1 100644 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -198,6 +198,7 @@ export namespace api { Offer: Offer; Score: number; Reasons: ScoreReason[]; + Latency?: number; static createFrom(source: any = {}) { return new ScoredOffer(source); @@ -208,6 +209,7 @@ export namespace api { this.Offer = this.convertValues(source["Offer"], Offer); this.Score = source["Score"]; this.Reasons = this.convertValues(source["Reasons"], ScoreReason); + this.Latency = source["Latency"]; } convertValues(a: any, classs: any, asMap: boolean = false): any { diff --git a/go.mod b/go.mod index 2681be9..b28a8ed 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,19 @@ go 1.23.3 require github.com/wailsapp/wails/v2 v2.9.2 +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/prometheus-community/pro-bing v0.5.0 // indirect + github.com/redis/go-redis/v9 v9.7.0 // indirect + golang.org/x/sync v0.10.0 // indirect +) + require ( github.com/bep/debounce v1.2.1 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect github.com/joho/godotenv v1.5.1 github.com/labstack/echo/v4 v4.10.2 // indirect @@ -30,11 +38,11 @@ require ( github.com/wailsapp/mimetype v1.4.1 // indirect go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.23.0 // indirect + golang.org/x/crypto v0.30.0 // indirect golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/net v0.32.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect xevion.dev/vastly/api v0.0.0 ) diff --git a/go.sum b/go.sum index 6b70e2c..71429ad 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,22 @@ github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= @@ -43,6 +51,10 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/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/prometheus-community/pro-bing v0.5.0 h1:Fq+4BUXKIvsPtXUY8K+04ud9dkAuFozqGmRAyNUpffY= +github.com/prometheus-community/pro-bing v0.5.0/go.mod h1:1joR9oXdMEAcAJJvhs+8vNDvTg5thfAZcRFhcUozG2g= +github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= +github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -71,13 +83,15 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -88,12 +102,12 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index aef13a4..4f693fb 100644 --- a/main.go +++ b/main.go @@ -25,6 +25,7 @@ func main() { }, BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, OnStartup: app.startup, + OnBeforeClose: app.beforeClose, Bind: []interface{}{ app, },