Files
p9/cmd/gui/receive.go
Loki Verloren 0e2bba237a initial commit
2021-05-03 10:43:10 +02:00

347 lines
8.7 KiB
Go

package gui
import (
"fmt"
"strconv"
"github.com/p9c/p9/pkg/amt"
"github.com/atotto/clipboard"
l "github.com/p9c/p9/pkg/gel/gio/layout"
"github.com/p9c/p9/pkg/gel/gio/text"
"github.com/p9c/p9/pkg/gel"
)
const Break1 = 48
type ReceivePage struct {
wg *WalletGUI
inputWidth, break1 float32
sm, md, lg, xl l.Widget
urn string
}
func (wg *WalletGUI) GetReceivePage() (rp *ReceivePage) {
rp = &ReceivePage{
wg: wg,
inputWidth: 17,
break1: 48,
}
rp.sm = rp.SmallList
return
}
func (rp *ReceivePage) Fn(gtx l.Context) l.Dimensions {
wg := rp.wg
return wg.Responsive(
wg.Size.Load(), gel.Widgets{
{
Widget: rp.SmallList,
},
{
Size: rp.break1,
Widget: rp.MediumList,
},
},
).Fn(gtx)
}
func (rp *ReceivePage) SmallList(gtx l.Context) l.Dimensions {
wg := rp.wg
smallWidgets := []l.Widget{
wg.Direction().Center().Embed(rp.QRButton()).Fn,
rp.InputMessage(),
rp.AmountInput(),
rp.MessageInput(),
rp.RegenerateButton(),
rp.AddressbookHeader(),
}
smallWidgets = append(smallWidgets, rp.GetAddressbookHistoryCards("DocBg")...)
le := func(gtx l.Context, index int) l.Dimensions {
return wg.Inset(0.25, smallWidgets[index]).Fn(gtx)
}
return wg.VFlex().AlignStart().
Flexed(
1,
wg.lists["receive"].
Vertical().Start().
Length(len(smallWidgets)).
ListElement(le).Fn,
).Fn(gtx)
}
func (rp *ReceivePage) InputMessage() l.Widget {
return rp.wg.Body2("Input details to request a payment").Alignment(text.Middle).Fn
}
func (rp *ReceivePage) MediumList(gtx l.Context) l.Dimensions {
wg := rp.wg
qrWidget := []l.Widget{
wg.Direction().Center().Embed(rp.QRButton()).Fn,
rp.InputMessage(),
rp.AmountInput(),
rp.MessageInput(),
rp.RegenerateButton(),
// rp.AddressbookHeader(),
}
qrLE := func(gtx l.Context, index int) l.Dimensions {
return wg.Inset(0.25, qrWidget[index]).Fn(gtx)
}
var historyWidget []l.Widget
historyWidget = append(historyWidget, rp.GetAddressbookHistoryCards("DocBg")...)
historyLE := func(gtx l.Context, index int) l.Dimensions {
return wg.Inset(
0.25,
historyWidget[index],
).Fn(gtx)
}
return wg.Flex().AlignStart().
Rigid(
func(gtx l.Context) l.Dimensions {
gtx.Constraints.Max.X, gtx.Constraints.Min.X = int(wg.TextSize.V*rp.inputWidth),
int(wg.TextSize.V*rp.inputWidth)
return wg.VFlex().
Rigid(
wg.lists["receiveMedium"].
Vertical().
Length(len(qrWidget)).
ListElement(qrLE).Fn,
).Fn(gtx)
},
).
Rigid(
wg.VFlex().AlignStart().
Rigid(
rp.AddressbookHeader(),
).
Rigid(
wg.lists["receiveAddresses"].
Vertical().
Length(len(historyWidget)).
ListElement(historyLE).Fn,
).
Fn,
).Fn(gtx)
}
func (rp *ReceivePage) Spacer() l.Widget {
return rp.wg.Flex().AlignMiddle().Flexed(1, rp.wg.Inset(0.25, gel.EmptySpace(0, 0)).Fn).Fn
}
func (rp *ReceivePage) GetAddressbookHistoryCards(bg string) (widgets []l.Widget) {
wg := rp.wg
avail := len(wg.receiveAddressbookClickables)
req := len(wg.State.receiveAddresses)
if req > avail {
for i := 0; i < req-avail; i++ {
wg.receiveAddressbookClickables = append(wg.receiveAddressbookClickables, wg.WidgetPool.GetClickable())
}
}
for x := range wg.State.receiveAddresses {
j := x
i := len(wg.State.receiveAddresses) - 1 - x
widgets = append(
widgets, func(gtx l.Context) l.Dimensions {
return wg.ButtonLayout(
wg.receiveAddressbookClickables[i].SetClick(
func() {
msg := wg.State.receiveAddresses[i].Message
if len(msg) > 64 {
msg = msg[:64]
}
qrText := fmt.Sprintf(
"parallelcoin:%s?amount=%8.8f&message=%s",
wg.State.receiveAddresses[i].Address,
wg.State.receiveAddresses[i].Amount.ToDUO(),
msg,
)
D.Ln("clicked receive address list item", j)
if e := clipboard.WriteAll(qrText); E.Chk(e) {
}
wg.GetNewReceivingQRCode(qrText)
rp.urn = qrText
},
),
).
Background(bg).
Embed(
wg.Inset(
0.25,
wg.VFlex().AlignStart().
Rigid(
wg.Flex().AlignBaseline().
Rigid(
wg.Caption(wg.State.receiveAddresses[i].Address).
Font("go regular").Fn,
).
Flexed(
1,
wg.Body1(wg.State.receiveAddresses[i].Amount.String()).
Alignment(text.End).Fn,
).
Fn,
).
Rigid(
wg.Caption(wg.State.receiveAddresses[i].Message).MaxLines(1).Fn,
).
Fn,
).
Fn,
).Fn(gtx)
},
)
}
return
}
func (rp *ReceivePage) QRMessage() l.Widget {
return rp.wg.Body2("Scan to send or click to copy").Alignment(text.Middle).Fn
}
func (rp *ReceivePage) GetQRText() string {
wg := rp.wg
msg := wg.inputs["receiveMessage"].GetText()
if len(msg) > 64 {
msg = msg[:64]
}
return fmt.Sprintf(
"parallelcoin:%s?amount=%s&message=%s",
wg.State.currentReceivingAddress.Load().EncodeAddress(),
wg.inputs["receiveAmount"].GetText(),
msg,
)
}
func (rp *ReceivePage) QRButton() l.Widget {
wg := rp.wg
if !wg.WalletAndClientRunning() || wg.currentReceiveQRCode == nil {
return func(gtx l.Context) l.Dimensions {
return l.Dimensions{}
}
}
return wg.VFlex().
Rigid(
wg.ButtonLayout(
wg.currentReceiveCopyClickable.SetClick(
func() {
D.Ln("clicked qr code copy clicker")
if e := clipboard.WriteAll(rp.urn); E.Chk(e) {
}
},
),
).
Background("white").
Embed(
wg.Inset(
0.125,
wg.Image().Src(*wg.currentReceiveQRCode).Scale(1).Fn,
).Fn,
).Fn,
).Rigid(
rp.QRMessage(),
).Fn
}
func (rp *ReceivePage) AddressbookHeader() l.Widget {
wg := rp.wg
return wg.Flex().
Rigid(
wg.Inset(
0.25,
wg.H5("Receive Address History").Alignment(text.Middle).Fn,
).Fn,
).Fn
}
func (rp *ReceivePage) AmountInput() l.Widget {
return func(gtx l.Context) l.Dimensions {
wg := rp.wg
// gtx.Constraints.Max.X, gtx.Constraints.Min.X = int(wg.TextSize.True*rp.inputWidth), int(wg.TextSize.True*rp.inputWidth)
return wg.inputs["receiveAmount"].Fn(gtx)
}
}
func (rp *ReceivePage) MessageInput() l.Widget {
return func(gtx l.Context) l.Dimensions {
wg := rp.wg
// gtx.Constraints.Max.X, gtx.Constraints.Min.X = int(wg.TextSize.True*rp.inputWidth), int(wg.TextSize.True*rp.inputWidth)
return wg.inputs["receiveMessage"].Fn(gtx)
}
}
func (rp *ReceivePage) RegenerateButton() l.Widget {
return func(gtx l.Context) l.Dimensions {
wg := rp.wg
if wg.inputs["receiveAmount"].GetText() == "" || wg.inputs["receiveMessage"].GetText() == "" {
gtx.Queue = nil
}
// gtx.Constraints.Max.X, gtx.Constraints.Min.X = int(wg.TextSize.True*rp.inputWidth), int(wg.TextSize.True*rp.inputWidth)
return wg.ButtonLayout(
wg.currentReceiveRegenClickable.
SetClick(
func() {
D.Ln("clicked regenerate button")
var amount float64
var am amt.Amount
var e error
if amount, e = strconv.ParseFloat(
wg.inputs["receiveAmount"].GetText(),
64,
); !E.Chk(e) {
if am, e = amt.NewAmount(amount); E.Chk(e) {
}
}
msg := wg.inputs["receiveMessage"].GetText()
if am == 0 || msg == "" {
// never store an entry without both fields filled
return
}
if len(wg.State.receiveAddresses) > 0 &&
(wg.State.receiveAddresses[len(wg.State.receiveAddresses)-1].Amount == 0 ||
wg.State.receiveAddresses[len(wg.State.receiveAddresses)-1].Message == "") {
// the first entry has neither of these, and newly generated items without them are assumed to
// not be intentional or used addresses so we don't generate a new entry for this case
wg.State.receiveAddresses[len(wg.State.receiveAddresses)-1].Amount = am
wg.State.receiveAddresses[len(wg.State.receiveAddresses)-1].Message = msg
} else {
// go func() {
wg.GetNewReceivingAddress()
msg := wg.inputs["receiveMessage"].GetText()
if len(msg) > 64 {
msg = msg[:64]
// enforce the field length limit
wg.inputs["receiveMessage"].SetText(msg)
}
qrText := fmt.Sprintf(
"parallelcoin:%s?amount=%f&message=%s",
wg.State.currentReceivingAddress.Load().EncodeAddress(),
am.ToDUO(),
msg,
)
rp.urn = qrText
wg.GetNewReceivingQRCode(rp.urn)
// }()
}
// force user to fill fields again after regenerate to stop duplicate entries especially from
// accidental double clicks/taps
wg.inputs["receiveAmount"].SetText("")
wg.inputs["receiveMessage"].SetText("")
wg.Invalidate()
},
),
).
Background("Primary").
Embed(
wg.Inset(
0.5,
wg.H6("regenerate").Color("Light").Fn,
).
Fn,
).
Fn(gtx)
}
}