overview.go raw
1 package gui
2
3 import (
4 "fmt"
5 "strings"
6 "time"
7
8 icons2 "golang.org/x/exp/shiny/materialdesign/icons"
9
10 "github.com/p9c/p9/pkg/gel/gio/text"
11
12 l "github.com/p9c/p9/pkg/gel/gio/layout"
13
14 "github.com/p9c/p9/pkg/gel"
15 "github.com/p9c/p9/pkg/btcjson"
16 )
17
18 func (wg *WalletGUI) balanceCard() func(gtx l.Context) l.Dimensions {
19
20 // gtx.Constraints.Min.X = int(wg.TextSize.True * sp.inputWidth)
21 return func(gtx l.Context) l.Dimensions {
22 gtx.Constraints.Min.X =
23 int(wg.TextSize.V * 16)
24 gtx.Constraints.Max.X =
25 int(wg.TextSize.V * 16)
26 return wg.VFlex().
27 AlignStart().
28 Rigid(
29 wg.Inset(
30 0.25,
31 wg.H5("balances").
32 Fn,
33 ).Fn,
34 ).
35 Rigid(
36 wg.Fill(
37 "Primary", l.E, 0, 0,
38 wg.Inset(
39 0.25,
40 wg.Flex().
41 AlignEnd().
42 Flexed(
43 1,
44 wg.VFlex().AlignEnd().
45 Rigid(
46 wg.ButtonLayout(wg.clickables["balanceConfirmed"]).SetClick(
47 func() {
48 go wg.WriteClipboard(
49 fmt.Sprintf(
50 "%6.8f",
51 wg.State.balance.Load(),
52 ),
53 )
54 },
55 ).Background("Transparent").Embed(
56 wg.Flex().AlignEnd().Flexed(
57 1,
58 wg.Inset(
59 0.5,
60 wg.Caption(
61 "confirmed"+leftPadTo(
62 14, 14,
63 fmt.Sprintf(
64 "%6.8f",
65 wg.State.balance.Load(),
66 ),
67 ),
68 ).
69 Font("go regular").
70 Alignment(text.End).
71 Color("DocText").Fn,
72 ).Fn,
73 ).Fn,
74 ).Fn,
75 ).
76 Rigid(
77 wg.ButtonLayout(wg.clickables["balanceUnconfirmed"]).SetClick(
78 func() {
79 go wg.WriteClipboard(
80 fmt.Sprintf(
81 "%6.8f",
82 wg.State.balanceUnconfirmed.Load(),
83 ),
84 )
85 },
86 ).Background("Transparent").Embed(
87 wg.Flex().AlignEnd().Flexed(
88 1,
89 wg.Inset(
90 0.5,
91 wg.Caption(
92 "unconfirmed"+leftPadTo(
93 14, 14,
94 fmt.Sprintf(
95 "%6.8f",
96 wg.State.balanceUnconfirmed.Load(),
97 ),
98 ),
99 ).
100 Font("go regular").
101 Alignment(text.End).
102 Color("DocText").Fn,
103
104 ).Fn,
105 ).Fn,
106 ).Fn,
107 ).
108 Rigid(
109 wg.ButtonLayout(wg.clickables["balanceTotal"]).SetClick(
110 func() {
111 go wg.WriteClipboard(
112 fmt.Sprintf(
113 "%6.8f",
114 wg.State.balance.Load()+wg.State.balanceUnconfirmed.Load(),
115 ),
116 )
117 },
118 ).Background("Transparent").Embed(
119 wg.Flex().AlignEnd().Flexed(
120 1,
121 wg.Inset(
122 0.5,
123 wg.H5(
124 "total"+leftPadTo(
125 14, 14, fmt.Sprintf(
126 "%6.8f", wg.State.balance.Load()+wg.
127 State.balanceUnconfirmed.Load(),
128 ),
129 ),
130 ).
131 Alignment(text.End).
132 Color("DocText").Fn,
133 ).
134 Fn,
135 ).Fn,
136 ).Fn,
137 ).Fn,
138 ).Fn,
139 ).Fn,
140 ).Fn,
141 ).Fn(gtx)
142 }
143 }
144
145 func (wg *WalletGUI) OverviewPage() l.Widget {
146 if wg.RecentTxsWidget == nil {
147 wg.RecentTxsWidget = func(gtx l.Context) l.Dimensions {
148 return l.Dimensions{Size: gtx.Constraints.Max}
149 }
150 }
151 return func(gtx l.Context) l.Dimensions {
152 return wg.Responsive(
153 wg.Size.Load(), gel.Widgets{
154 {
155 Size: 0,
156 Widget:
157 wg.VFlex().AlignStart().
158 Rigid(
159 // wg.ButtonInset(0.25,
160 wg.VFlex().
161 Rigid(
162 wg.Inset(
163 0.25,
164 wg.balanceCard(),
165 ).Fn,
166 ).Fn,
167 // ).Fn,
168 ).
169 // Rigid(wg.Inset(0.25, gel.EmptySpace(0, 0)).Fn).
170 Flexed(
171 1,
172 wg.VFlex().AlignStart().
173 Rigid(
174 wg.Inset(
175 0.25,
176 wg.H5("Recent Transactions").Fn,
177 ).Fn,
178 ).
179 Flexed(
180 1,
181 // wg.Inset(0.5,
182 wg.RecentTxsWidget,
183 // p9.EmptyMaxWidth(),
184 // ).Fn,
185 ).
186 Fn,
187 ).
188 Fn,
189 },
190 {
191 Size: 64,
192 Widget: wg.Flex().AlignStart().
193 Rigid(
194 // wg.ButtonInset(0.25,
195 wg.VFlex(). // SpaceSides().AlignStart().
196 Rigid(
197 wg.Inset(
198 0.25,
199 wg.balanceCard(),
200 ).Fn,
201 ).Fn,
202 // ).Fn,
203 ).
204 // Rigid(wg.Inset(0.25, gel.EmptySpace(0, 0)).Fn).
205 Flexed(
206 1,
207 // wg.Inset(
208 // 0.25,
209 wg.VFlex().AlignStart().
210 Rigid(
211 wg.Inset(
212 0.25,
213 wg.H5("Recent transactions").Fn,
214 ).Fn,
215 ).
216 Flexed(
217 1,
218 // wg.Fill("DocBg", l.W, wg.TextSize.True, 0, wg.Inset(0.25,
219 wg.RecentTxsWidget,
220 // p9.EmptyMaxWidth(),
221 // ).Fn).Fn,
222 ).
223 Fn,
224 // ).
225 // Fn,
226 ).
227 Fn,
228 },
229 },
230 ).Fn(gtx)
231 }
232 }
233
234 func (wg *WalletGUI) recentTxCardStub(txs *btcjson.ListTransactionsResult) l.Widget {
235 return wg.Inset(
236 0.25,
237 wg.Flex().
238 // AlignBaseline().
239 // AlignStart().
240 // SpaceEvenly().
241 SpaceBetween().
242 // Flexed(
243 // 1,
244 // wg.Inset(
245 // 0.25,
246 // wg.Caption(txs.Address).
247 // Font("go regular").
248 // Color("PanelText").
249 // TextScale(0.66).
250 // Alignment(text.End).
251 // Fn,
252 // ).Fn,
253 // ).
254 Rigid(
255 wg.Caption(fmt.Sprintf("%-6.8f DUO", txs.Amount)).Font("go regular").Color("DocText").Fn,
256 ).
257 Rigid(
258 wg.Flex().
259 Rigid(
260 wg.Icon().Color("PanelText").Scale(1).Src(&icons2.DeviceWidgets).Fn,
261 ).
262 Rigid(
263 wg.Caption(fmt.Sprint(txs.BlockIndex)).Fn,
264 // wg.buttonIconText(txs.clickBlock,
265 // fmt.Sprint(*txs.BlockIndex),
266 // &icons2.DeviceWidgets,
267 // wg.blockPage(*txs.BlockIndex)),
268 ).
269 Fn,
270 ).
271 Rigid(
272 wg.Flex().
273 Rigid(
274 wg.Icon().Color("PanelText").Scale(1).Src(&icons2.ActionCheckCircle).Fn,
275 ).
276 Rigid(
277 wg.Caption(fmt.Sprintf("%d ", txs.Confirmations)).Fn,
278 ).
279 Fn,
280 ).
281 Rigid(
282 wg.Flex().
283 Rigid(
284 func(gtx l.Context) l.Dimensions {
285 switch txs.Category {
286 case "generate":
287 return wg.Icon().Color("PanelText").Scale(1).Src(&icons2.ActionStars).Fn(gtx)
288 case "immature":
289 return wg.Icon().Color("PanelText").Scale(1).Src(&icons2.ImageTimeLapse).Fn(gtx)
290 case "receive":
291 return wg.Icon().Color("PanelText").Scale(1).Src(&icons2.ActionPlayForWork).Fn(gtx)
292 case "unknown":
293 return wg.Icon().Color("PanelText").Scale(1).Src(&icons2.AVNewReleases).Fn(gtx)
294 }
295 return l.Dimensions{}
296 },
297 ).
298 Rigid(
299 wg.Caption(txs.Category+" ").Fn,
300 ).
301 Fn,
302 ).
303 // Flexed(1, gel.EmptyMaxWidth()).
304 Rigid(
305 wg.Flex().
306 Rigid(
307 wg.Icon().Color("PanelText").Scale(1).Src(&icons2.DeviceAccessTime).Fn,
308 ).
309 Rigid(
310 wg.Caption(
311 time.Unix(
312 txs.Time,
313 0,
314 ).Format("02 Jan 06 15:04:05 MST"),
315 ).Font("go regular").
316 // Alignment(text.End).
317 Color("PanelText").Fn,
318 ).
319 Fn,
320 ).
321 Fn,
322 ).
323 Fn
324 }
325
326 func (wg *WalletGUI) recentTxCardSummary(txs *btcjson.ListTransactionsResult) l.Widget {
327 return wg.VFlex().AlignStart().SpaceBetween().
328 Rigid(
329 // wg.Inset(
330 // 0.25,
331 wg.Flex().AlignStart().SpaceBetween().
332 Rigid(
333 wg.H6(fmt.Sprintf("%-.8f DUO", txs.Amount)).Alignment(text.Start).Color("PanelText").Fn,
334 ).
335 Flexed(
336 1,
337 wg.Inset(
338 0.25,
339 wg.Caption(txs.Address).
340 Font("go regular").
341 Color("PanelText").
342 TextScale(0.66).
343 Alignment(text.End).
344 Fn,
345 ).Fn,
346 ).Fn,
347 // ).Fn,
348 ).
349 Rigid(
350 // wg.Inset(
351 // 0.25,
352 wg.Flex().
353 Flexed(
354 1,
355 wg.Flex().
356 Rigid(
357 wg.Flex().
358 Rigid(
359 wg.Icon().Color("PanelText").Scale(1).Src(&icons2.DeviceWidgets).Fn,
360 ).
361 // Rigid(
362 // wg.Caption(fmt.Sprint(*txs.BlockIndex)).Fn,
363 // // wg.buttonIconText(txs.clickBlock,
364 // // fmt.Sprint(*txs.BlockIndex),
365 // // &icons2.DeviceWidgets,
366 // // wg.blockPage(*txs.BlockIndex)),
367 // ).
368 Rigid(
369 wg.Caption(fmt.Sprintf("%d ", txs.BlockIndex)).Fn,
370 ).
371 Fn,
372 ).
373 Rigid(
374 wg.Flex().
375 Rigid(
376 wg.Icon().Color("PanelText").Scale(1).Src(&icons2.ActionCheckCircle).Fn,
377 ).
378 Rigid(
379 wg.Caption(fmt.Sprintf("%d ", txs.Confirmations)).Fn,
380 ).
381 Fn,
382 ).
383 Rigid(
384 wg.Flex().
385 Rigid(
386 func(gtx l.Context) l.Dimensions {
387 switch txs.Category {
388 case "generate":
389 return wg.Icon().Color("PanelText").Scale(1).Src(&icons2.ActionStars).Fn(gtx)
390 case "immature":
391 return wg.Icon().Color("PanelText").Scale(1).Src(&icons2.ImageTimeLapse).Fn(gtx)
392 case "receive":
393 return wg.Icon().Color("PanelText").Scale(1).Src(&icons2.ActionPlayForWork).Fn(gtx)
394 case "unknown":
395 return wg.Icon().Color("PanelText").Scale(1).Src(&icons2.AVNewReleases).Fn(gtx)
396 }
397 return l.Dimensions{}
398 },
399 ).
400 Rigid(
401 wg.Caption(txs.Category+" ").Fn,
402 ).
403 Fn,
404 ).
405 Rigid(
406 wg.Flex().
407 Rigid(
408 wg.Icon().Color("PanelText").Scale(1).Src(&icons2.DeviceAccessTime).Fn,
409 ).
410 Rigid(
411 wg.Caption(
412 time.Unix(
413 txs.Time,
414 0,
415 ).Format("02 Jan 06 15:04:05 MST"),
416 ).Color("PanelText").Fn,
417 ).
418 Fn,
419 ).Fn,
420 ).Fn,
421 // ).Fn,
422 ).Fn
423 }
424
425 func (wg *WalletGUI) recentTxCardSummaryButton(
426 txs *btcjson.ListTransactionsResult,
427 clickable *gel.Clickable,
428 bgColor string, back bool,
429 ) l.Widget {
430 return wg.ButtonLayout(
431 clickable.SetClick(
432 func() {
433 D.Ln("clicked tx")
434 // D.S(txs)
435 curr := wg.openTxID.Load()
436 if curr == txs.TxID {
437 wg.prevOpenTxID.Store(wg.openTxID.Load())
438 wg.openTxID.Store("")
439 moveto := wg.originTxDetail
440 if moveto == "" {
441 moveto = wg.MainApp.ActivePageGet()
442 }
443 wg.MainApp.ActivePage(moveto)
444 } else {
445 if wg.MainApp.ActivePageGet() == "home" {
446 wg.originTxDetail = "home"
447 wg.MainApp.ActivePage("history")
448 } else {
449 wg.originTxDetail = "history"
450 }
451 wg.openTxID.Store(txs.TxID)
452 }
453 },
454 ),
455 ).
456 Background(bgColor).
457 Embed(
458 gel.If(
459 back,
460 wg.Flex().
461 Rigid(
462 wg.Icon().Color("PanelText").Scale(4).Src(&icons2.NavigationArrowBack).Fn,
463 ).
464 Rigid(
465 wg.Inset(0.5, gel.EmptyMinWidth()).Fn,
466 ).
467 Flexed(
468 1,
469 wg.Fill(
470 "DocBg", l.Center, 0, 0, wg.Inset(
471 0.5,
472 wg.recentTxCardSummary(txs),
473 ).Fn,
474 ).Fn,
475 ).
476 Fn,
477 wg.Flex().
478 Rigid(
479 wg.Inset(0.5, gel.EmptyMaxHeight()).Fn,
480 ).
481 Flexed(
482 1,
483 wg.Fill(
484 "DocBg", l.Center, 0, 0, wg.Inset(
485 0.5,
486 wg.recentTxCardSummary(txs),
487 ).Fn,
488 ).Fn,
489 ).
490 Fn,
491 ),
492 ).Fn
493 }
494
495 func (wg *WalletGUI) recentTxCardSummaryButtonGenerate(
496 txs *btcjson.ListTransactionsResult,
497 clickable *gel.Clickable,
498 bgColor string, back bool,
499 ) l.Widget {
500 return wg.ButtonLayout(
501 clickable.SetClick(
502 func() {
503 D.Ln("clicked tx")
504 // D.S(txs)
505 curr := wg.openTxID.Load()
506 if curr == txs.TxID {
507 wg.prevOpenTxID.Store(wg.openTxID.Load())
508 wg.openTxID.Store("")
509 moveto := wg.originTxDetail
510 if moveto == "" {
511 moveto = wg.MainApp.ActivePageGet()
512 }
513 wg.MainApp.ActivePage(moveto)
514 } else {
515 if wg.MainApp.ActivePageGet() == "home" {
516 wg.originTxDetail = "home"
517 wg.MainApp.ActivePage("history")
518 } else {
519 wg.originTxDetail = "history"
520 }
521 wg.openTxID.Store(txs.TxID)
522 }
523 },
524 ),
525 ).
526 Background(bgColor).
527 Embed(
528 wg.Flex().AlignStart().
529 Rigid(
530 // wg.Fill(
531 // "Primary", l.W, 0, 0, wg.Inset(
532 // 0.5,
533 gel.If(
534 back,
535 wg.Flex().AlignStart().
536 Rigid(
537 wg.Icon().Color("PanelText").Scale(4).Src(&icons2.NavigationArrowBack).Fn,
538 ).
539 Flexed(
540 1,
541 wg.recentTxCardSummary(txs),
542 ).
543 Fn,
544 wg.Flex().AlignStart().
545 Flexed(
546 1,
547 wg.recentTxCardStub(txs),
548 ).
549 Fn,
550 // wg.Flex().
551 // Rigid(
552 // wg.Inset(0.5, gel.EmptyMaxHeight()).Fn,
553 // ).
554 // Flexed(
555 // 1,
556 // wg.Fill(
557 // "DocBg", l.Center, 0, 0, wg.Inset(
558 // 0.5,
559 // wg.recentTxCardSummary(txs),
560 // ).Fn,
561 // ).Fn,
562 // ).
563 // Fn,
564 ),
565 ).Fn,
566 // ).Fn,
567 // ).Fn,
568 ).Fn
569 }
570
571 func (wg *WalletGUI) recentTxCardDetail(txs *btcjson.ListTransactionsResult, clickable *gel.Clickable) l.Widget {
572 return wg.VFlex().
573 Rigid(
574 wg.Fill(
575 "Primary", l.Center, wg.TextSize.V, 0,
576 wg.recentTxCardSummaryButton(txs, clickable, "Primary", false),
577 ).Fn,
578 // ).
579 // Rigid(
580 // wg.Fill(
581 // "DocBg", l.Center, wg.TextSize.True, 0,
582 // wg.Flex().
583 // Flexed(
584 // 1,
585 // wg.Inset(
586 // 0.25,
587 // wg.VFlex().
588 // Rigid(wg.Inset(0.25, gel.EmptySpace(0, 0)).Fn).
589 // Rigid(
590 // wg.H6("Transaction Details").
591 // Color("PanelText").
592 // Fn,
593 // ).
594 // Rigid(
595 // wg.Inset(
596 // 0.25,
597 // wg.VFlex().
598 // Rigid(
599 // wg.txDetailEntry("Transaction ID", txs.TxID),
600 // ).
601 // Rigid(
602 // wg.txDetailEntry("Address", txs.Address),
603 // ).
604 // Rigid(
605 // wg.txDetailEntry("Amount", fmt.Sprintf("%0.8f", txs.Amount)),
606 // ).
607 // Rigid(
608 // wg.txDetailEntry("In Block", fmt.Sprint(txs.BlockIndex)),
609 // ).
610 // Rigid(
611 // wg.txDetailEntry("First Mined", fmt.Sprint(txs.BlockTime)),
612 // ).
613 // Rigid(
614 // wg.txDetailEntry("Category", txs.Category),
615 // ).
616 // Rigid(
617 // wg.txDetailEntry("Confirmations", fmt.Sprint(txs.Confirmations)),
618 // ).
619 // Rigid(
620 // wg.txDetailEntry("Fee", fmt.Sprintf("%0.8f", txs.Fee)),
621 // ).
622 // Rigid(
623 // wg.txDetailEntry("Confirmations", fmt.Sprint(txs.Confirmations)),
624 // ).
625 // Rigid(
626 // wg.txDetailEntry("Involves Watch Only", fmt.Sprint(txs.InvolvesWatchOnly)),
627 // ).
628 // Rigid(
629 // wg.txDetailEntry("Time", fmt.Sprint(txs.Time)),
630 // ).
631 // Rigid(
632 // wg.txDetailEntry("Time Received", fmt.Sprint(txs.TimeReceived)),
633 // ).
634 // Rigid(
635 // wg.txDetailEntry("Trusted", fmt.Sprint(txs.Trusted)),
636 // ).
637 // Rigid(
638 // wg.txDetailEntry("Abandoned", fmt.Sprint(txs.Abandoned)),
639 // ).
640 // Rigid(
641 // wg.txDetailEntry("BIP125 Replaceable", fmt.Sprint(txs.BIP125Replaceable)),
642 // ).
643 // Fn,
644 // ).Fn,
645 // ).Fn,
646 // ).Fn,
647 // ).Fn,
648 // ).Fn,
649 ).Fn
650 }
651
652 func (wg *WalletGUI) txDetailEntry(name, detail string, bgColor string, small bool) l.Widget {
653 content := wg.Body1
654 if small {
655 content = wg.Caption
656 }
657 return wg.Fill(
658 bgColor, l.Center, wg.TextSize.V, 0,
659 wg.Flex().AlignBaseline().
660 Flexed(
661 0.25,
662 wg.Inset(
663 0.25,
664 wg.Body1(name).
665 Color("PanelText").
666 Font("bariol bold").
667 Fn,
668 ).Fn,
669 ).
670 Flexed(
671 0.75,
672 wg.Flex().SpaceStart().Rigid(
673 wg.Inset(
674 0.25,
675 content(detail).Font("go regular").
676 Color("PanelText").
677 Fn,
678 ).Fn,
679 ).Fn,
680 ).Fn,
681 ).Fn
682 }
683
684 // RecentTransactions generates a display showing recent transactions
685 //
686 // fields to use: Address, Amount, BlockIndex, BlockTime, Category, Confirmations, Generated
687 func (wg *WalletGUI) RecentTransactions(n int, listName string) l.Widget {
688 wg.txMx.Lock()
689 defer wg.txMx.Unlock()
690 // wg.ready.Store(false)
691 var out []l.Widget
692 // first := true
693 // out = append(out)
694 var txList []btcjson.ListTransactionsResult
695 var clickables []*gel.Clickable
696 txList = wg.txHistoryList
697 switch listName {
698 case "history":
699 clickables = wg.txHistoryClickables
700 case "recent":
701 // txList = wg.txRecentList
702 clickables = wg.recentTxsClickables
703 }
704 ltxl := len(txList)
705 ltc := len(clickables)
706 if ltxl > ltc {
707 count := ltxl - ltc
708 for ; count > 0; count-- {
709 clickables = append(clickables, wg.Clickable())
710 }
711 }
712 if len(clickables) == 0 {
713 return func(gtx l.Context) l.Dimensions {
714 return l.Dimensions{Size: gtx.Constraints.Max}
715 }
716 }
717 D.Ln(">>>>>>>>>>>>>>>> iterating transactions", n, listName)
718 var collected int
719 for x := range txList {
720 if collected >= n && n > 0 {
721 break
722 }
723 txs := txList[x]
724 switch listName {
725 case "history":
726 collected++
727 case "recent":
728 if txs.Category == "generate" || txs.Category == "immature" || txs.Amount < 0 && txs.Fee == 0 {
729 continue
730 } else {
731 collected++
732 }
733 }
734 // spacer
735 // if !first {
736 // out = append(
737 // out,
738 // wg.Inset(0.25, gel.EmptyMaxWidth()).Fn,
739 // )
740 // } else {
741 // first = false
742 // }
743
744 ck := clickables[x]
745 out = append(
746 out,
747 func(gtx l.Context) l.Dimensions {
748 return gel.If(
749 txs.Category == "immature",
750 wg.recentTxCardSummaryButtonGenerate(&txs, ck, "DocBg", false),
751 gel.If(
752 txs.Category == "send",
753 wg.recentTxCardSummaryButton(&txs, ck, "Danger", false),
754 gel.If(
755 txs.Category == "receive",
756 wg.recentTxCardSummaryButton(&txs, ck, "Success", false),
757 gel.If(
758 txs.Category == "generate",
759 wg.recentTxCardSummaryButtonGenerate(&txs, ck, "DocBg", false),
760 gel.If(
761 wg.prevOpenTxID.Load() == txs.TxID,
762 wg.recentTxCardSummaryButton(&txs, ck, "Primary", false),
763 wg.recentTxCardSummaryButton(&txs, ck, "DocBg", false),
764 ),
765 ),
766 ),
767 ),
768 )(gtx)
769 },
770 )
771 // out = append(out,
772 // wg.Caption(txs.TxID).
773 // Font("go regular").
774 // Color("PanelText").
775 // TextScale(0.5).Fn,
776 // )
777 // out = append(
778 // out,
779 // wg.Fill(
780 // "DocBg", l.W, 0, 0,
781 //
782 // ).Fn,
783 // )
784 }
785 le := func(gtx l.Context, index int) l.Dimensions {
786 return wg.Inset(
787 0.25,
788 out[index],
789 ).Fn(gtx)
790 }
791 wo := func(gtx l.Context) l.Dimensions {
792 return wg.VFlex().AlignStart().
793 Rigid(
794 wg.lists[listName].
795 Vertical().
796 Length(len(out)).
797 ListElement(le).
798 Fn,
799 ).Fn(gtx)
800 }
801 D.Ln(">>>>>>>>>>>>>>>> history widget completed", n, listName)
802 switch listName {
803 case "history":
804 wg.TxHistoryWidget = wo
805 case "recent":
806 wg.RecentTxsWidget = wo
807 }
808 return func(gtx l.Context) l.Dimensions {
809 return wo(gtx)
810 }
811 }
812
813 func leftPadTo(length, limit int, txt string) string {
814 if len(txt) > limit {
815 return txt[:limit]
816 }
817 if len(txt) == limit {
818 return txt
819 }
820 pad := length - len(txt)
821 return strings.Repeat(" ", pad) + txt
822 }
823