From bf2ddf6d7c87896cdfb9c4a6540220a6d71edc6d Mon Sep 17 00:00:00 2001 From: Todd G Date: Tue, 6 Oct 2020 18:34:57 -0600 Subject: [PATCH 01/11] Make tx output fields read-only, hunting a deadlock remove some superfluous mutexes, un-buffer a few channels --- cmd/cryptonym-wallet/main.go | 4 +-- init.go | 2 +- key-generator.go | 4 +-- tx-result.go | 61 ++++++++++++++++++++++-------------- 4 files changed, 42 insertions(+), 29 deletions(-) diff --git a/cmd/cryptonym-wallet/main.go b/cmd/cryptonym-wallet/main.go index 29d8d41..11bf9ba 100644 --- a/cmd/cryptonym-wallet/main.go +++ b/cmd/cryptonym-wallet/main.go @@ -64,7 +64,7 @@ var ( uriContent = uriInput(true) uriContainer = &fyne.Container{} ready = false - connectedChan = make(chan bool, 1) + connectedChan = make(chan bool) p = message.NewPrinter(language.English) keyBox = &widget.Box{} serverInfoCh = make(chan explorer.ServerInfo) @@ -382,7 +382,7 @@ func refreshInfo(deadline time.Duration) (string, bool) { d := time.Now().Add(deadline) ctx, cancel := context.WithDeadline(context.Background(), d) defer cancel() - resultChan := make(chan string, 1) + resultChan := make(chan string) go func() { clientMux.Lock() defer clientMux.Unlock() diff --git a/init.go b/init.go index c28acf0..7d1bdab 100644 --- a/init.go +++ b/init.go @@ -35,7 +35,7 @@ var ( actionEndPointActive = "/v1/chain/push_transaction" apiEndPointActive = "/v1/chain/get_info" p = message.NewPrinter(language.English) - RepaintChan = make(chan bool, 1) + RepaintChan = make(chan bool) PasswordVisible bool SettingsLoaded = make(chan *FioSettings) Settings = DefaultSettings() diff --git a/key-generator.go b/key-generator.go index 7e55979..41858de 100644 --- a/key-generator.go +++ b/key-generator.go @@ -35,7 +35,7 @@ var imageSize = func() (size int) { return }() -var RefreshQr = make(chan bool, 1) +var RefreshQr = make(chan bool) func KeyGenTab() *widget.Box { @@ -46,7 +46,7 @@ func KeyGenTab() *widget.Box { var showingPriv bool var err error - vanityQuit := make(chan bool, 1) + vanityQuit := make(chan bool) vanityOpt := &vanityOptions{} vanityOpt.threads = runtime.NumCPU() vanitySearch := widget.NewSelect([]string{"Actor", "Pubkey", "Either"}, func(s string) { diff --git a/tx-result.go b/tx-result.go index dda6e49..1867806 100644 --- a/tx-result.go +++ b/tx-result.go @@ -125,38 +125,29 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou tick := time.NewTicker(time.Second) update := false updateBalance := false - mux := sync.Mutex{} successCount := 0 failedCount := 0 for { select { case <-tick.C: if updateBalance { - mux.Lock() BalanceChan <- true updateBalance = false - mux.Unlock() } if update { - mux.Lock() successLabel.SetText(p.Sprintf("%d", successCount)) failedLabel.SetText(p.Sprintf("%d", failedCount)) successLabel.Refresh() failedLabel.Refresh() update = false - mux.Unlock() } case <-f: - mux.Lock() update = true failedCount = failedCount + 1 - mux.Unlock() case <-s: - mux.Lock() update = true updateBalance = true successCount = successCount + 1 - mux.Unlock() } } }(successChan, failedChan) @@ -191,6 +182,28 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou ShowFullRequest(Results[fullResponseIndex].FullReq, win.window) }) + textUpdateDone := make(chan interface{}) + textUpdateReq := make(chan string) + textUpdateResp := make(chan string) + go func() { + for { + select { + case <-textUpdateDone: + return + case s := <-textUpdateReq: + requestText.OnChanged = func(string) { + requestText.SetText(s) + } + requestText.SetText(s) + case s := <-textUpdateResp: + responseText.OnChanged = func(string) { + responseText.SetText(s) + } + responseText.SetText(s) + } + } + }() + setGrid := func() { grid = fyne.NewContainerWithLayout(layout.NewHBoxLayout(), fyne.NewContainerWithLayout(layout.NewGridLayoutWithRows(1), @@ -219,10 +232,8 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou Results = make([]TxResult, 0) summaryGroup = widget.NewGroupWithScroller("Transaction Result") summaryGroup.Refresh() - responseText.SetText("") - responseText.Refresh() - requestText.SetText("") - requestText.Refresh() + textUpdateResp <- "" + textUpdateReq <-"" setGrid() mux.Unlock() } @@ -305,13 +316,11 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou select { case q := <-rq: mux.Lock() - requestText.SetText(trimDisplayed(q)) - requestText.Refresh() + textUpdateReq <-trimDisplayed(q) mux.Unlock() case s := <-rs: mux.Lock() - responseText.SetText(trimDisplayed(s)) - responseText.Refresh() + textUpdateResp <-trimDisplayed(s) mux.Unlock() case fullResponseIndex = <-frs: } @@ -366,7 +375,6 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou reqChan <- string(Results[i].Req) respChan <- string(Results[i].Resp) fullRespChan <- i - repaint() }) summaryGroup.Append(b) mux.Unlock() @@ -658,23 +666,22 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou time.Sleep(250 * time.Millisecond) setGrid() if len(Results) > 0 && !win.hideFail && !win.hideSucc { - responseText.SetText(trimDisplayed(string(Results[0].Resp))) - requestText.SetText(trimDisplayed(string(Results[0].Req))) + textUpdateResp <-trimDisplayed(string(Results[0].Resp)) + textUpdateReq <-trimDisplayed(string(Results[0].Req)) } if !running { stopButton.Disable() } repaint() win.window.SetOnClosed(func() { + close(textUpdateDone) win.gone = true exit = true win.window = App.NewWindow("Tx Results") win.window.Resize(fyne.NewSize(txW, txH)) win.window.Hide() - requestText.SetText("") - requestText.Refresh() - responseText.SetText("") - responseText.Refresh() + textUpdateReq <-"" + textUpdateResp <-"" for i := 0; i < 10; i++ { if bombsAway.Disabled() { exit = true @@ -720,6 +727,9 @@ func ShowFullResponse(b []byte, win fyne.Window) { }() }) set := func(s string) { + FullResponseText.OnChanged = func(string) { + FullResponseText.SetText(s) + } FullResponseText.SetText(s) FullResponseText.Refresh() FullActionRespWin.Show() @@ -770,6 +780,9 @@ func ShowFullRequest(b []byte, win fyne.Window) { }() }) set := func(s string) { + fullRequestText.OnChanged = func(string) { + fullRequestText.SetText(s) + } fullRequestText.SetText(s) fullRequestText.Refresh() fullActionRespWin.Show() From 8d13b98887f1416753e5006ac47905d20bdfe19a Mon Sep 17 00:00:00 2001 From: Todd G Date: Tue, 6 Oct 2020 18:46:39 -0600 Subject: [PATCH 02/11] more mutex cleanup, update time format --- tx-result.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tx-result.go b/tx-result.go index 1867806..37a6445 100644 --- a/tx-result.go +++ b/tx-result.go @@ -315,13 +315,9 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou for { select { case q := <-rq: - mux.Lock() textUpdateReq <-trimDisplayed(q) - mux.Unlock() case s := <-rs: - mux.Lock() textUpdateResp <-trimDisplayed(s) - mux.Unlock() case fullResponseIndex = <-frs: } } @@ -362,7 +358,6 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou if len(Results) > 256 { clear() } - mux.Lock() icon := theme.ConfirmIcon() if failed { icon = theme.CancelIcon() @@ -377,7 +372,6 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou fullRespChan <- i }) summaryGroup.Append(b) - mux.Unlock() repaint() } @@ -432,7 +426,7 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou return } output := TxResult{ - Summary: fmt.Sprintf("%s", time.Now().Format("05.000")), + Summary: fmt.Sprintf("%s", time.Now().Format("15:04:05.000")), Index: i, } e := FormState.GeneratePayloads(account) @@ -596,7 +590,7 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou continue } output.Resp = []byte(err.Error()) - output.Summary = fmt.Sprintf("%s", time.Now().Format("05.000")) + output.Summary = fmt.Sprintf("%s", time.Now().Format("15:04:05.000")) buf := bytes.Buffer{} zWriter, _ := zlib.NewWriterLevel(&buf, zlib.BestCompression) if len(result) > 0 { @@ -620,7 +614,7 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou if err != nil { errs.ErrChan <- err.Error() output.Resp = []byte(err.Error()) - output.Summary = fmt.Sprintf("%s", time.Now().Format("05.000")) + output.Summary = fmt.Sprintf("%s", time.Now().Format("15:04:05.000")) if win.hideFail { failedChan <- true continue From 3578137a0a8340d33bc8c9191f45e5be971f7d40 Mon Sep 17 00:00:00 2001 From: Todd G Date: Tue, 6 Oct 2020 20:13:13 -0600 Subject: [PATCH 03/11] trying to fix occasional blank tx window --- action-form.go | 4 ++-- tx-result.go | 65 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/action-form.go b/action-form.go index 1dd6d4e..28a37b3 100644 --- a/action-form.go +++ b/action-form.go @@ -29,7 +29,7 @@ var ( func ResetTxResult() { if txWindowOpts.window != nil && !txWindowOpts.gone { - txWindowOpts.window.Close() + txWindowOpts.window.Hide() } txWindowOpts.window = nil txWindowOpts.window = App.NewWindow("Tx Results") @@ -37,7 +37,7 @@ func ResetTxResult() { txWindowOpts.window.SetContent(layout.NewSpacer()) txWindowOpts.window.Show() go func() { - time.Sleep(time.Second) + time.Sleep(100*time.Millisecond) txWindowOpts.window.Hide() }() } diff --git a/tx-result.go b/tx-result.go index 37a6445..c51f493 100644 --- a/tx-result.go +++ b/tx-result.go @@ -95,11 +95,28 @@ type txResultOpts struct { } func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, account *fio.Account) { - //var window fyne.Window if win.window == nil { win.window = App.NewWindow("TX Result") } + // this is a workaround for fyne sometimes showing blank black windows, resizing fixes + // but when it happens the window still doesn't work correctly. It will show up, but does not + // refresh. Beats a black window, and at least the close button works. + resizeTrigger := make(chan interface{}) + go func() { + for { + select { + case <- resizeTrigger: + if win.window == nil || !win.window.Content().Visible() { + continue + } + win.window.Resize(fyne.NewSize(txW, txH)) + time.Sleep(100*time.Millisecond) + win.window.Resize(win.window.Content().MinSize()) + } + } + }() + workers, e := strconv.Atoi(win.threads) if e != nil { workers = 1 @@ -222,33 +239,32 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou responseText, ), ) - win.window.Resize(fyne.NewSize(txW, txH)) + win.window.SetContent(grid) - //win.window.CenterOnScreen() + win.window.Resize(win.window.Content().MinSize()) } clear := func() { - mux.Lock() Results = make([]TxResult, 0) summaryGroup = widget.NewGroupWithScroller("Transaction Result") summaryGroup.Refresh() textUpdateResp <- "" textUpdateReq <-"" setGrid() - mux.Unlock() } closeButton := widget.NewButtonWithIcon( "close", theme.DeleteIcon(), func() { - if running { - stopRequested <- true - } - win.gone = true - clear() - //Win.RequestFocus() - win.window.Close() + go func() { + clear() + if running { + stopRequested <- true + } + win.gone = true + win.window.Close() + }() }, ) resendButton := widget.NewButtonWithIcon("resend", theme.ViewRefreshIcon(), func() { @@ -659,6 +675,7 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou } time.Sleep(250 * time.Millisecond) setGrid() + if len(Results) > 0 && !win.hideFail && !win.hideSucc { textUpdateResp <-trimDisplayed(string(Results[0].Resp)) textUpdateReq <-trimDisplayed(string(Results[0].Req)) @@ -668,27 +685,23 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou } repaint() win.window.SetOnClosed(func() { - close(textUpdateDone) win.gone = true exit = true - win.window = App.NewWindow("Tx Results") - win.window.Resize(fyne.NewSize(txW, txH)) + close(textUpdateDone) win.window.Hide() - textUpdateReq <-"" - textUpdateResp <-"" - for i := 0; i < 10; i++ { - if bombsAway.Disabled() { - exit = true - time.Sleep(500 * time.Millisecond) - } else { - Win.RequestFocus() - return - } - } + win.window = App.NewWindow("Tx Results") + win.window.SetContent(fyne.NewContainer()) + win.window.Resize(win.window.Content().MinSize()) + go func() { + Win.RequestFocus() + time.Sleep(100*time.Millisecond) + win.window.Hide() + }() }) if win.gone { win.gone = false win.window.Show() + resizeTrigger <- true } else { repaint() } From b9a59dcc4df89ed93b1015ea0a919854b067cb32 Mon Sep 17 00:00:00 2001 From: Todd G Date: Tue, 6 Oct 2020 20:14:33 -0600 Subject: [PATCH 04/11] gofmt --- action-form.go | 2 +- fuzzer/simple.go | 2 +- requests-form.go | 104 +++++++++++++++++++++++------------------------ tx-result.go | 16 ++++---- 4 files changed, 60 insertions(+), 64 deletions(-) diff --git a/action-form.go b/action-form.go index 28a37b3..c7c2fbe 100644 --- a/action-form.go +++ b/action-form.go @@ -37,7 +37,7 @@ func ResetTxResult() { txWindowOpts.window.SetContent(layout.NewSpacer()) txWindowOpts.window.Show() go func() { - time.Sleep(100*time.Millisecond) + time.Sleep(100 * time.Millisecond) txWindowOpts.window.Hide() }() } diff --git a/fuzzer/simple.go b/fuzzer/simple.go index 82fd662..1b26e29 100644 --- a/fuzzer/simple.go +++ b/fuzzer/simple.go @@ -8,9 +8,9 @@ import ( "encoding/base64" "encoding/hex" "fmt" + errs "github.com/blockpane/cryptonym/errLog" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil" - errs "github.com/blockpane/cryptonym/errLog" "github.com/ethereum/go-ethereum/crypto" "github.com/fioprotocol/fio-go" "github.com/fioprotocol/fio-go/eos" diff --git a/requests-form.go b/requests-form.go index 7eac788..1476bba 100644 --- a/requests-form.go +++ b/requests-form.go @@ -29,10 +29,10 @@ func RequestContent(reqContent chan fyne.CanvasObject, refresh chan bool) { go func() { for { select { - case <- refresh: + case <-refresh: content, err := GetPending(refresh, Account, Api) if err != nil { - errs.ErrChan <-err.Error() + errs.ErrChan <- err.Error() continue } reqContent <- content @@ -51,7 +51,7 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form Win, ) go func() { - <- closed + <-closed d.Hide() }() d.SetOnClosed(func() { @@ -64,7 +64,7 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form layout.NewSpacer(), topDesc, widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), func() { - refreshChan <-true + refreshChan <- true }), sendNew, layout.NewSpacer(), @@ -78,7 +78,7 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form return widget.NewVBox(top, widget.NewLabel("No pending requests.")), err } howMany := len(pending.Requests) - topDesc.SetText(fmt.Sprint(howMany)+" pending requests.") + topDesc.SetText(fmt.Sprint(howMany) + " pending requests.") if howMany > 100 { topDesc.SetText("More than 100 pending requests.") } @@ -98,9 +98,9 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form sort.Slice(pending.Requests, func(i, j int) bool { return pending.Requests[i].FioRequestId < pending.Requests[j].FioRequestId }) - for _, req := range pending.Requests{ + for _, req := range pending.Requests { func(req fio.RequestStatus) { - id := widget.NewLabelWithStyle(fmt.Sprintf("%d | " + req.TimeStamp.Local().Format(time.Stamp), req.FioRequestId), fyne.TextAlignCenter, fyne.TextStyle{}) + id := widget.NewLabelWithStyle(fmt.Sprintf("%d | "+req.TimeStamp.Local().Format(time.Stamp), req.FioRequestId), fyne.TextAlignCenter, fyne.TextStyle{}) payer := req.PayerFioAddress if len(payer) > 32 { payer = payer[:29] + "..." @@ -109,9 +109,9 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form if len(payee) > 32 { payee = payee[:29] + "..." } - fr := widget.NewLabelWithStyle(payee, fyne.TextAlignTrailing, fyne.TextStyle{Bold:true}) + fr := widget.NewLabelWithStyle(payee, fyne.TextAlignTrailing, fyne.TextStyle{Bold: true}) to := widget.NewLabelWithStyle(payer, fyne.TextAlignLeading, fyne.TextStyle{}) - view := widget.NewButtonWithIcon("View", theme.VisibilityIcon(),func() { + view := widget.NewButtonWithIcon("View", theme.VisibilityIcon(), func() { closed := make(chan interface{}) d := dialog.NewCustom( fmt.Sprintf("FIO Request ID %d (%s)", req.FioRequestId, req.PayeeFioAddress), @@ -120,9 +120,9 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form Win, ) go func() { - <- closed + <-closed d.Hide() - refreshChan <-true + refreshChan <- true }() d.Show() }) @@ -132,8 +132,8 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form errs.ErrChan <- err.Error() return } - errs.ErrChan <-"rejected request id: " + strconv.FormatUint(req.FioRequestId, 10) - refreshChan <-true + errs.ErrChan <- "rejected request id: " + strconv.FormatUint(req.FioRequestId, 10) + refreshChan <- true }) rejectBtn.HideShadow = true requests.AddObject(widget.NewHBox(view, layout.NewSpacer())) @@ -145,21 +145,21 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form if err != nil { view.Hide() summary = "invalid content" - errs.ErrChan <-err.Error() + errs.ErrChan <- err.Error() } else { summary = obt.Request.ChainCode if obt.Request.ChainCode != obt.Request.TokenCode { - summary += "/"+obt.Request.TokenCode + summary += "/" + obt.Request.TokenCode } summary += fmt.Sprintf(" (%s) %q", obt.Request.Amount, obt.Request.Memo) if len(summary) > 32 { summary = summary[:29] + "..." } } - requests.AddObject(widget.NewHBox(layout.NewSpacer(), widget.NewLabelWithStyle(summary, fyne.TextAlignTrailing, fyne.TextStyle{Italic:true}), rejectBtn)) + requests.AddObject(widget.NewHBox(layout.NewSpacer(), widget.NewLabelWithStyle(summary, fyne.TextAlignTrailing, fyne.TextStyle{Italic: true}), rejectBtn)) }(req) } - form = fyne.NewContainerWithLayout(layout.NewVBoxLayout(),top, requests) + form = fyne.NewContainerWithLayout(layout.NewVBoxLayout(), top, requests) return } @@ -201,8 +201,8 @@ func ViewRequest(id uint64, closed chan interface{}, refresh chan bool, account add("Hash", decrypted.Request.Hash) add("Offline Url", decrypted.Request.OfflineUrl) - errMsg := widget.NewLabelWithStyle("", fyne.TextAlignCenter, fyne.TextStyle{Monospace:true}) - errIcon := fyne.NewContainerWithLayout(layout.NewFixedGridLayout( fyne.NewSize(20, 20)), canvas.NewImageFromResource(theme.WarningIcon())) + errMsg := widget.NewLabelWithStyle("", fyne.TextAlignCenter, fyne.TextStyle{Monospace: true}) + errIcon := fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.NewSize(20, 20)), canvas.NewImageFromResource(theme.WarningIcon())) errIcon.Hide() respondBtn := &widget.Button{} respondBtn = widget.NewButtonWithIcon("Record Response", theme.MailReplyIcon(), func() { @@ -214,7 +214,7 @@ func ViewRequest(id uint64, closed chan interface{}, refresh chan bool, account Win, ) go func() { - <- closing + <-closing close(closed) d.Hide() }() @@ -235,7 +235,7 @@ func ViewRequest(id uint64, closed chan interface{}, refresh chan bool, account } errIcon.Hide() errMsg.SetText("Done. Transaction ID: " + resp.TransactionID) - refresh <-true + refresh <- true }) buttons := widget.NewVBox( widget.NewHBox( @@ -277,7 +277,7 @@ func RespondRequest(req *fio.FundsReqTableResp, decrypted *fio.ObtRequestContent l.SetText(err.Error()) } tooLarge := "" - if 432 - len(content) < 0 { + if 432-len(content) < 0 { tooLarge = "Content is too large! " } over := 432 - len(content) @@ -308,7 +308,7 @@ func RespondRequest(req *fio.FundsReqTableResp, decrypted *fio.ObtRequestContent add("Payer Public Key", "", false, &record.PayerPublicAddress) add("Payee Public Key", decrypted.PayeePublicAddress, true, nil) add("Chain Code", decrypted.ChainCode, true, nil) - add("Token Code", decrypted.TokenCode, true,nil) + add("Token Code", decrypted.TokenCode, true, nil) add("Amount", decrypted.Amount, false, &record.Amount) add("Status", "", false, &record.Status) add("Memo", memo, false, &record.Memo) @@ -328,10 +328,10 @@ func RespondRequest(req *fio.FundsReqTableResp, decrypted *fio.ObtRequestContent errMsg.SetText("Push Action: " + err.Error()) return } - errs.ErrChan <-"Success, txid: " + resp.TransactionID + errs.ErrChan <- "Success, txid: " + resp.TransactionID errMsg.SetText("Success, txid: " + resp.TransactionID) sendResponse.Disable() - time.Sleep(2*time.Second) + time.Sleep(2 * time.Second) close(closed) }) @@ -384,7 +384,7 @@ func NewRequest(account *fio.Account, api *fio.API) fyne.CanvasObject { payeeNameSelect.SetSelected(payeeNameSelect.Options[0]) reqFormData = append(reqFormData, widget.NewFormItem("Your FIO Name", payeeNameSelect)) - payerPubLabel := widget.NewLabelWithStyle(spaces, fyne.TextAlignLeading, fyne.TextStyle{Monospace:true}) + payerPubLabel := widget.NewLabelWithStyle(spaces, fyne.TextAlignLeading, fyne.TextStyle{Monospace: true}) payerName := widget.NewEntry() invalid := func() { payerPubLabel.SetText(spaces) @@ -409,7 +409,6 @@ func NewRequest(account *fio.Account, api *fio.API) fyne.CanvasObject { reqFormData = append(reqFormData, widget.NewFormItem("Recipient's FIO Name", payerName)) reqFormData = append(reqFormData, widget.NewFormItem("", payerPubLabel)) - reqFormData = append(reqFormData, widget.NewFormItem("", layout.NewSpacer())) payeeRecvAddress := widget.NewEntry() @@ -422,7 +421,7 @@ func NewRequest(account *fio.Account, api *fio.API) fyne.CanvasObject { tokenSelect := widget.NewSelectEntry(make([]string, 0)) tokenSelect.OnChanged = func(s string) { nfr.TokenCode = s - resp, found, _:= api.PubAddressLookup(fio.Address(payeeFio), chainSelect.Text, tokenSelect.Text) + resp, found, _ := api.PubAddressLookup(fio.Address(payeeFio), chainSelect.Text, tokenSelect.Text) if !found { return } @@ -459,11 +458,11 @@ func NewRequest(account *fio.Account, api *fio.API) fyne.CanvasObject { add("Hash", "", false, &nfr.Hash) add("Offline Url", "", false, &nfr.OfflineUrl) errLabel := widget.NewLabel("") - sendRequest := func(){ + sendRequest := func() { defer func() { go func() { // prevent accidental click click click - time.Sleep(2*time.Second) + time.Sleep(2 * time.Second) send.Enable() }() }() @@ -477,7 +476,7 @@ func NewRequest(account *fio.Account, api *fio.API) fyne.CanvasObject { resp, err := api.SignPushActions(fio.NewFundsReq(account.Actor, payerFio, payeeFio, content)) if err != nil { errLabel.SetText(err.Error()) - errs.ErrChan <-err.Error() + errs.ErrChan <- err.Error() return } errLabel.SetText("Success, txid: " + resp.TransactionID) @@ -517,7 +516,7 @@ func GetTokens(s string) []string { var chainTokens = map[string][]string{ "ABBC": {"ABBC"}, - "ADA": {"ADA"}, + "ADA": {"ADA"}, "ALGO": {"ALGO"}, "ATOM": {"ATOM"}, "BAND": {"BAND"}, @@ -535,17 +534,17 @@ var chainTokens = map[string][]string{ "RUNE", "SWINGBY", }, - "BSV": {"BSV"}, - "BTC": {"BTC"}, - "BTM": {"BTM"}, - "CET": {"CET"}, - "CHX": {"CHX"}, - "CKB": {"CKB"}, + "BSV": {"BSV"}, + "BTC": {"BTC"}, + "BTM": {"BTM"}, + "CET": {"CET"}, + "CHX": {"CHX"}, + "CKB": {"CKB"}, "DASH": {"DASH"}, "DOGE": {"DOGE"}, - "DOT": {"DOT"}, - "EOS": {"EOS"}, - "ETC": {"ETC"}, + "DOT": {"DOT"}, + "EOS": {"EOS"}, + "ETC": {"ETC"}, "ETH": { "AERGO", "AKRO", @@ -634,26 +633,26 @@ var chainTokens = map[string][]string{ "ACH", "IBAN", }, - "FIO": {"FIO"}, - "FSN": {"FSN"}, - "HPB": {"HPB"}, + "FIO": {"FIO"}, + "FSN": {"FSN"}, + "HPB": {"HPB"}, "IOST": {"IOST"}, "KAVA": {"KAVA"}, - "LTC": {"LTC"}, - "LTO": {"LTO"}, - "MHC": {"MHC"}, + "LTC": {"LTC"}, + "LTO": {"LTO"}, + "MHC": {"MHC"}, "NEO": { "GAS", "NEO", }, - "OLT": {"OLT"}, + "OLT": {"OLT"}, "OMNI": {"USDT"}, - "ONE": {"ONE"}, + "ONE": {"ONE"}, "ONT": {"ONG", "ONT"}, "QTUM": {"QTUM"}, - "RVN": {"RVN"}, - "SOL": {"SOL"}, + "RVN": {"RVN"}, + "SOL": {"SOL"}, "TRX": { "BTT", "TRX", @@ -674,6 +673,3 @@ var chainTokens = map[string][]string{ "ZEC": {"ZEC"}, "ZIL": {"ZIL"}, } - - - diff --git a/tx-result.go b/tx-result.go index c51f493..0c18abb 100644 --- a/tx-result.go +++ b/tx-result.go @@ -106,12 +106,12 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou go func() { for { select { - case <- resizeTrigger: + case <-resizeTrigger: if win.window == nil || !win.window.Content().Visible() { continue } win.window.Resize(fyne.NewSize(txW, txH)) - time.Sleep(100*time.Millisecond) + time.Sleep(100 * time.Millisecond) win.window.Resize(win.window.Content().MinSize()) } } @@ -249,7 +249,7 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou summaryGroup = widget.NewGroupWithScroller("Transaction Result") summaryGroup.Refresh() textUpdateResp <- "" - textUpdateReq <-"" + textUpdateReq <- "" setGrid() } @@ -331,9 +331,9 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou for { select { case q := <-rq: - textUpdateReq <-trimDisplayed(q) + textUpdateReq <- trimDisplayed(q) case s := <-rs: - textUpdateResp <-trimDisplayed(s) + textUpdateResp <- trimDisplayed(s) case fullResponseIndex = <-frs: } } @@ -677,8 +677,8 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou setGrid() if len(Results) > 0 && !win.hideFail && !win.hideSucc { - textUpdateResp <-trimDisplayed(string(Results[0].Resp)) - textUpdateReq <-trimDisplayed(string(Results[0].Req)) + textUpdateResp <- trimDisplayed(string(Results[0].Resp)) + textUpdateReq <- trimDisplayed(string(Results[0].Req)) } if !running { stopButton.Disable() @@ -694,7 +694,7 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou win.window.Resize(win.window.Content().MinSize()) go func() { Win.RequestFocus() - time.Sleep(100*time.Millisecond) + time.Sleep(100 * time.Millisecond) win.window.Hide() }() }) From ab1b843e01d6afa566dcc710c44e819cd07aef51 Mon Sep 17 00:00:00 2001 From: Todd G Date: Tue, 6 Oct 2020 22:54:54 -0600 Subject: [PATCH 05/11] shrink giant buttons --- account-form.go | 8 ++++---- cmd/cryptonym-wallet/main.go | 6 +++++- table.go | 10 +++++----- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/account-form.go b/account-form.go index c73dd09..e4d6a84 100644 --- a/account-form.go +++ b/account-form.go @@ -49,9 +49,9 @@ func NewAccountSearchTab(box chan fyne.Container, account *fio.Account) { return widget.NewVBox( fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.NewSize(RWidth(), 40)), widget.NewHBox( - accountSelect, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(accountSelect.MinSize()), accountSelect), accountInput, - accountSubmit, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(accountSubmit.MinSize()), accountSubmit), ), ), layout.NewSpacer(), @@ -66,9 +66,9 @@ func NewAccountSearchTab(box chan fyne.Container, account *fio.Account) { return widget.NewVBox( fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.NewSize(RWidth(), 40)), widget.NewHBox( - accountSelect, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(accountSelect.MinSize()), accountSelect), accountInput, - accountSubmit, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(accountSubmit.MinSize()), accountSubmit), ), ), fyne.NewContainerWithLayout(layout.NewVBoxLayout(), diff --git a/cmd/cryptonym-wallet/main.go b/cmd/cryptonym-wallet/main.go index 11bf9ba..973fbb2 100644 --- a/cmd/cryptonym-wallet/main.go +++ b/cmd/cryptonym-wallet/main.go @@ -1023,7 +1023,11 @@ func keyBoxContent() *widget.Box { actor, myFioAddress, ), - widget.NewHBox(balanceLabel, balanceButton, loadButton), + widget.NewHBox( + balanceLabel, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(balanceButton.MinSize()), balanceButton), + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(loadButton.MinSize()), loadButton), + ), ), ), ) diff --git a/table.go b/table.go index fb97484..e97b443 100644 --- a/table.go +++ b/table.go @@ -366,17 +366,17 @@ func GetTableBrowser(w int, h int, api *fio.API) (tab *widget.Box, ok bool) { fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.NewSize(200, 35)), widget.NewHBox( widget.NewLabel(" "), - contract, - tables, - previous, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.NewSize(180, contract.MinSize().Height)), contract), + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.NewSize(180, tables.MinSize().Height)), tables), + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(previous.MinSize()), previous), widget.NewLabel("page"), page, widget.NewLabel("limit"), rowsPerPage, - next, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(next.MinSize()), next), showQueryCheck, widget.NewLabel(" "), - submit, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(submit.MinSize()), submit), ), ), fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.NewSize(RWidth(), int(math.Round(float64(H)*.62)))), From 229e0afcc9104bc08a05e7aa514fa99a2e1beea8 Mon Sep 17 00:00:00 2001 From: Todd G Date: Tue, 6 Oct 2020 23:57:44 -0600 Subject: [PATCH 06/11] make requests tab scroll --- requests-form.go | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/requests-form.go b/requests-form.go index 1476bba..df4b48c 100644 --- a/requests-form.go +++ b/requests-form.go @@ -59,14 +59,15 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form }) d.Show() }) + refr := widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), func() { + refreshChan <- true + }) topDesc := widget.NewLabel("") top := widget.NewHBox( layout.NewSpacer(), topDesc, - widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), func() { - refreshChan <- true - }), - sendNew, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(refr.MinSize()), refr), + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(sendNew.MinSize()), sendNew), layout.NewSpacer(), ) @@ -82,6 +83,9 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form if howMany > 100 { topDesc.SetText("More than 100 pending requests.") } + sort.Slice(pending.Requests, func(i, j int) bool { + return pending.Requests[i].FioRequestId < pending.Requests[j].FioRequestId + }) if howMany > 25 { topDesc.SetText(topDesc.Text + fmt.Sprintf(" (only first 25 displayed.)")) pending.Requests = pending.Requests[:25] @@ -95,9 +99,6 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form widget.NewLabelWithStyle("Summary", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}), ) - sort.Slice(pending.Requests, func(i, j int) bool { - return pending.Requests[i].FioRequestId < pending.Requests[j].FioRequestId - }) for _, req := range pending.Requests { func(req fio.RequestStatus) { id := widget.NewLabelWithStyle(fmt.Sprintf("%d | "+req.TimeStamp.Local().Format(time.Stamp), req.FioRequestId), fyne.TextAlignCenter, fyne.TextStyle{}) @@ -159,8 +160,17 @@ func GetPending(refreshChan chan bool, account *fio.Account, api *fio.API) (form requests.AddObject(widget.NewHBox(layout.NewSpacer(), widget.NewLabelWithStyle(summary, fyne.TextAlignTrailing, fyne.TextStyle{Italic: true}), rejectBtn)) }(req) } - form = fyne.NewContainerWithLayout(layout.NewVBoxLayout(), top, requests) - + form = widget.NewVBox( + top, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.NewSize(RWidth(), int(float32(PctHeight())*.68))), + widget.NewScrollContainer(widget.NewVBox(requests, + fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.Size{ + Width: 20, + Height: 50, + }), layout.NewSpacer()), + )), + ), + ) return } From 69d7022f2f0c564ec3de984409fbe9186438ce47 Mon Sep 17 00:00:00 2001 From: Todd G Date: Wed, 7 Oct 2020 08:59:10 -0600 Subject: [PATCH 07/11] make it easier to spot top21 in msig form --- msig-requests.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/msig-requests.go b/msig-requests.go index f1bfb54..d17d838 100644 --- a/msig-requests.go +++ b/msig-requests.go @@ -247,6 +247,7 @@ func requestBox(proposer string, requests []*fio.MsigApprovalsInfo, index int, p // actor, fio address, has approved, is produce //hasApproved := theme.CancelIcon() hasApproved := theme.CheckButtonIcon() + asterisk := "" if approvers[k] { //hasApproved = theme.ConfirmIcon() hasApproved = theme.CheckButtonCheckedIcon() @@ -254,10 +255,12 @@ func requestBox(proposer string, requests []*fio.MsigApprovalsInfo, index int, p for _, p := range producers.Active.Producers { if p.AccountName == eos.AccountName(k) { top21Count += 1 + asterisk = "*" break } } } + top21Label := widget.NewLabel(asterisk) var firstName string n, ok, _ := api.GetFioNamesForActor(k) if ok && len(n.FioAddresses) > 0 { @@ -272,6 +275,7 @@ func requestBox(proposer string, requests []*fio.MsigApprovalsInfo, index int, p fyne.NewContainerWithLayout(layout.NewGridLayout(2), widget.NewHBox( layout.NewSpacer(), + top21Label, fyne.NewContainerWithLayout(layout.NewFixedGridLayout(fyne.NewSize(32, 32)), canvas.NewImageFromResource(hasApproved), )), From 82b4c74178e6f6c7bddc8c68050655160b9158ee Mon Sep 17 00:00:00 2001 From: Todd G Date: Thu, 15 Oct 2020 16:07:35 -0600 Subject: [PATCH 08/11] fix crash on closing tx result win, eliminate weird dangling windows --- action-form.go | 7 ++----- cmd/cryptonym-wallet/main.go | 1 - tx-result.go | 14 ++------------ 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/action-form.go b/action-form.go index c7c2fbe..5b2ed3e 100644 --- a/action-form.go +++ b/action-form.go @@ -22,14 +22,13 @@ var ( FormState = NewAbi(0) bombsAway = &widget.Button{} txWindowOpts = &txResultOpts{ - window: App.NewWindow("Tx Results"), gone: true, } ) func ResetTxResult() { - if txWindowOpts.window != nil && !txWindowOpts.gone { - txWindowOpts.window.Hide() + if txWindowOpts.window != nil { + txWindowOpts.window.Close() } txWindowOpts.window = nil txWindowOpts.window = App.NewWindow("Tx Results") @@ -247,8 +246,6 @@ func GetAbiForm(action string, account *fio.Account, api *fio.API, opts *fio.TxO apiEndpoint.SetSelected("/v1/chain/push_transaction") apiEndpoint.Refresh() - txWindowOpts.window.Resize(fyne.NewSize(txW, txH)) - // multisig options: randProposal := func() string { var s string diff --git a/cmd/cryptonym-wallet/main.go b/cmd/cryptonym-wallet/main.go index 973fbb2..d2b4b2f 100644 --- a/cmd/cryptonym-wallet/main.go +++ b/cmd/cryptonym-wallet/main.go @@ -445,7 +445,6 @@ func reconnect(account *fio.Account) (result bool) { time.Sleep(2 * time.Second) explorer.BalanceChan <- true }() - explorer.ResetTxResult() result = true return } diff --git a/tx-result.go b/tx-result.go index 0c18abb..b7cf77f 100644 --- a/tx-result.go +++ b/tx-result.go @@ -95,9 +95,7 @@ type txResultOpts struct { } func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, account *fio.Account) { - if win.window == nil { - win.window = App.NewWindow("TX Result") - } + ResetTxResult() // this is a workaround for fyne sometimes showing blank black windows, resizing fixes // but when it happens the window still doesn't work correctly. It will show up, but does not @@ -685,18 +683,10 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou } repaint() win.window.SetOnClosed(func() { + Win.RequestFocus() win.gone = true exit = true close(textUpdateDone) - win.window.Hide() - win.window = App.NewWindow("Tx Results") - win.window.SetContent(fyne.NewContainer()) - win.window.Resize(win.window.Content().MinSize()) - go func() { - Win.RequestFocus() - time.Sleep(100 * time.Millisecond) - win.window.Hide() - }() }) if win.gone { win.gone = false From 243d8905719d14e82f0f48b3e07a8d20f5ba5eab Mon Sep 17 00:00:00 2001 From: Todd G Date: Thu, 15 Oct 2020 16:33:13 -0600 Subject: [PATCH 09/11] fix crash on linux on closing tx result win --- action-form.go | 11 ++++++++--- tx-result.go | 5 ++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/action-form.go b/action-form.go index 5b2ed3e..5646512 100644 --- a/action-form.go +++ b/action-form.go @@ -28,16 +28,21 @@ var ( func ResetTxResult() { if txWindowOpts.window != nil { + txWindowOpts.window.Hide() txWindowOpts.window.Close() } - txWindowOpts.window = nil txWindowOpts.window = App.NewWindow("Tx Results") txWindowOpts.gone = true txWindowOpts.window.SetContent(layout.NewSpacer()) txWindowOpts.window.Show() go func() { - time.Sleep(100 * time.Millisecond) - txWindowOpts.window.Hide() + for { + time.Sleep(10 * time.Millisecond) + if txWindowOpts.window.Content().Visible() { + txWindowOpts.window.Hide() + return + } + } }() } diff --git a/tx-result.go b/tx-result.go index b7cf77f..7e1df31 100644 --- a/tx-result.go +++ b/tx-result.go @@ -256,12 +256,11 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou theme.DeleteIcon(), func() { go func() { - clear() if running { stopRequested <- true } win.gone = true - win.window.Close() + win.window.Hide() }() }, ) @@ -688,7 +687,7 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou exit = true close(textUpdateDone) }) - if win.gone { + if win.gone && win != nil { win.gone = false win.window.Show() resizeTrigger <- true From 3f4b52b6876f1b88b6f0ef46dafe0576986b42e7 Mon Sep 17 00:00:00 2001 From: Todd G Date: Thu, 15 Oct 2020 16:40:13 -0600 Subject: [PATCH 10/11] fix dangling window on darwin caused by linux fix --- tx-result.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tx-result.go b/tx-result.go index 7e1df31..41fdeef 100644 --- a/tx-result.go +++ b/tx-result.go @@ -18,6 +18,7 @@ import ( "log" "math" "regexp" + "runtime" "sort" "strconv" "strings" @@ -261,6 +262,10 @@ func TxResultsWindow(win *txResultOpts, api *fio.API, opts *fio.TxOptions, accou } win.gone = true win.window.Hide() + // this causes a segfault on linux, but on darwin if not closed it leaves a window hanging around. + if runtime.GOOS == "darwin" { + win.window.Close() + } }() }, ) From 69d0e74d6d98cca48834d06b716293dbdaef6901 Mon Sep 17 00:00:00 2001 From: Todd G Date: Thu, 15 Oct 2020 16:54:57 -0600 Subject: [PATCH 11/11] module update --- go.sum | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/go.sum b/go.sum index b021e2c..efec699 100644 --- a/go.sum +++ b/go.sum @@ -17,11 +17,13 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9 h1:1ltqoej5GtaWF8jaiA49HwsZD459jqm9YFz9ZtMFpQA= github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -102,11 +104,13 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526 h1:NfuKjkj/Xc2z1xZIj+EmNCm5p1nKJPyw3F4E20usXvg= github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/josephspurrier/goversioninfo v0.0.0-20190124120936-8611f5a5ff3f/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE= +github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca h1:ozPUX9TKQZVek4lZWYRsQo7uS8vJ+q4OOHvRhHiCLfU= github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -120,6 +124,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lucor/goinfo v0.0.0-20200401173949-526b5363a13a h1:4djPngMU3ttoFCf6DOgPNQYmxyNmRRmpLg4/uz2TTEg= github.com/lucor/goinfo v0.0.0-20200401173949-526b5363a13a/go.mod h1:ORP3/rB5IsulLEBwQZCJyyV6niqmI7P4EWSmkug+1Ng= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=