|
|
@ -494,76 +494,74 @@ func (ui *UI) layoutMenu(gtx layout.Context, sysIns system.Insets, expiry time.T
|
|
|
|
Right: unit.Add(gtx.Metric, sysIns.Right, unit.Dp(2)),
|
|
|
|
Right: unit.Add(gtx.Metric, sysIns.Right, unit.Dp(2)),
|
|
|
|
}.Layout(gtx, func(gtx C) D {
|
|
|
|
}.Layout(gtx, func(gtx C) D {
|
|
|
|
return layout.NE.Layout(gtx, func(gtx C) D {
|
|
|
|
return layout.NE.Layout(gtx, func(gtx C) D {
|
|
|
|
return Background{Color: argb(0x33000000), CornerRadius: unit.Dp(2)}.Layout(gtx, func(gtx C) D {
|
|
|
|
return widget.Border{Color: argb(0x33000000), CornerRadius: unit.Dp(2), Width: unit.Px(1)}.Layout(gtx, func(gtx C) D {
|
|
|
|
return layout.UniformInset(unit.Px(1)).Layout(gtx, func(gtx C) D {
|
|
|
|
return Background{Color: rgb(0xfafafa), CornerRadius: unit.Dp(2)}.Layout(gtx, func(gtx C) D {
|
|
|
|
return Background{Color: rgb(0xfafafa), CornerRadius: unit.Px(4)}.Layout(gtx, func(gtx C) D {
|
|
|
|
menu := &ui.menu
|
|
|
|
menu := &ui.menu
|
|
|
|
items := []struct {
|
|
|
|
items := []struct {
|
|
|
|
btn *widget.Clickable
|
|
|
|
btn *widget.Clickable
|
|
|
|
title string
|
|
|
|
title string
|
|
|
|
}{
|
|
|
|
}{
|
|
|
|
{title: "Copy My IP Address", btn: &menu.copy},
|
|
|
|
{title: "Copy My IP Address", btn: &menu.copy},
|
|
|
|
{title: "Reauthenticate", btn: &menu.reauth},
|
|
|
|
{title: "Reauthenticate", btn: &menu.reauth},
|
|
|
|
{title: "Log out", btn: &menu.logout},
|
|
|
|
{title: "Log out", btn: &menu.logout},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Lay out menu items twice; once for
|
|
|
|
// Lay out menu items twice; once for
|
|
|
|
// measuring the widest item, once for actual layout.
|
|
|
|
// measuring the widest item, once for actual layout.
|
|
|
|
var maxWidth int
|
|
|
|
var maxWidth int
|
|
|
|
var minWidth int
|
|
|
|
var minWidth int
|
|
|
|
children := []layout.FlexChild{
|
|
|
|
children := []layout.FlexChild{
|
|
|
|
layout.Rigid(func(gtx C) D {
|
|
|
|
layout.Rigid(func(gtx C) D {
|
|
|
|
return layout.Inset{
|
|
|
|
return layout.Inset{
|
|
|
|
Top: unit.Dp(16),
|
|
|
|
Top: unit.Dp(16),
|
|
|
|
Right: unit.Dp(16),
|
|
|
|
Right: unit.Dp(16),
|
|
|
|
Left: unit.Dp(16),
|
|
|
|
Left: unit.Dp(16),
|
|
|
|
Bottom: unit.Dp(4),
|
|
|
|
Bottom: unit.Dp(4),
|
|
|
|
}.Layout(gtx, func(gtx C) D {
|
|
|
|
}.Layout(gtx, func(gtx C) D {
|
|
|
|
gtx.Constraints.Min.X = minWidth
|
|
|
|
|
|
|
|
var expiryStr string
|
|
|
|
|
|
|
|
const fmtStr = time.Stamp
|
|
|
|
|
|
|
|
switch {
|
|
|
|
|
|
|
|
case expiry.IsZero():
|
|
|
|
|
|
|
|
expiryStr = "Expires: (never)"
|
|
|
|
|
|
|
|
case time.Now().After(expiry):
|
|
|
|
|
|
|
|
expiryStr = fmt.Sprintf("Expired: %s", expiry.Format(fmtStr))
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
expiryStr = fmt.Sprintf("Expires: %s", expiry.Format(fmtStr))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
l := material.Caption(ui.theme, expiryStr)
|
|
|
|
|
|
|
|
l.Color = rgb(0x8f8f8f)
|
|
|
|
|
|
|
|
dims := l.Layout(gtx)
|
|
|
|
|
|
|
|
if w := dims.Size.X; w > maxWidth {
|
|
|
|
|
|
|
|
maxWidth = w
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return dims
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(items); i++ {
|
|
|
|
|
|
|
|
it := &items[i]
|
|
|
|
|
|
|
|
children = append(children, layout.Rigid(func(gtx C) D {
|
|
|
|
|
|
|
|
return material.Clickable(gtx, it.btn, func(gtx C) D {
|
|
|
|
|
|
|
|
return layout.UniformInset(unit.Dp(16)).Layout(gtx, func(gtx C) D {
|
|
|
|
gtx.Constraints.Min.X = minWidth
|
|
|
|
gtx.Constraints.Min.X = minWidth
|
|
|
|
var expiryStr string
|
|
|
|
dims := material.Body1(ui.theme, it.title).Layout(gtx)
|
|
|
|
const fmtStr = time.Stamp
|
|
|
|
|
|
|
|
switch {
|
|
|
|
|
|
|
|
case expiry.IsZero():
|
|
|
|
|
|
|
|
expiryStr = "Expires: (never)"
|
|
|
|
|
|
|
|
case time.Now().After(expiry):
|
|
|
|
|
|
|
|
expiryStr = fmt.Sprintf("Expired: %s", expiry.Format(fmtStr))
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
expiryStr = fmt.Sprintf("Expires: %s", expiry.Format(fmtStr))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
l := material.Caption(ui.theme, expiryStr)
|
|
|
|
|
|
|
|
l.Color = rgb(0x8f8f8f)
|
|
|
|
|
|
|
|
dims := l.Layout(gtx)
|
|
|
|
|
|
|
|
if w := dims.Size.X; w > maxWidth {
|
|
|
|
if w := dims.Size.X; w > maxWidth {
|
|
|
|
maxWidth = w
|
|
|
|
maxWidth = w
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return dims
|
|
|
|
return dims
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
for i := 0; i < len(items); i++ {
|
|
|
|
}
|
|
|
|
it := &items[i]
|
|
|
|
f := layout.Flex{Axis: layout.Vertical}
|
|
|
|
children = append(children, layout.Rigid(func(gtx C) D {
|
|
|
|
// First pass: record and discard operations
|
|
|
|
return material.Clickable(gtx, it.btn, func(gtx C) D {
|
|
|
|
// and determine widest item.
|
|
|
|
return layout.UniformInset(unit.Dp(16)).Layout(gtx, func(gtx C) D {
|
|
|
|
m := op.Record(gtx.Ops)
|
|
|
|
gtx.Constraints.Min.X = minWidth
|
|
|
|
f.Layout(gtx, children...)
|
|
|
|
dims := material.Body1(ui.theme, it.title).Layout(gtx)
|
|
|
|
m.Stop()
|
|
|
|
if w := dims.Size.X; w > maxWidth {
|
|
|
|
// Second pass: layout items with equal width.
|
|
|
|
maxWidth = w
|
|
|
|
minWidth = maxWidth
|
|
|
|
}
|
|
|
|
return f.Layout(gtx, children...)
|
|
|
|
return dims
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
f := layout.Flex{Axis: layout.Vertical}
|
|
|
|
|
|
|
|
// First pass: record and discard operations
|
|
|
|
|
|
|
|
// and determine widest item.
|
|
|
|
|
|
|
|
m := op.Record(gtx.Ops)
|
|
|
|
|
|
|
|
f.Layout(gtx, children...)
|
|
|
|
|
|
|
|
m.Stop()
|
|
|
|
|
|
|
|
// Second pass: layout items with equal width.
|
|
|
|
|
|
|
|
minWidth = maxWidth
|
|
|
|
|
|
|
|
return f.Layout(gtx, children...)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
@ -853,9 +851,8 @@ func drawDisc(ops *op.Ops, radius float32, col color.RGBA) {
|
|
|
|
|
|
|
|
|
|
|
|
// Background lays out a widget and draws a color background behind it.
|
|
|
|
// Background lays out a widget and draws a color background behind it.
|
|
|
|
type Background struct {
|
|
|
|
type Background struct {
|
|
|
|
Color color.RGBA
|
|
|
|
Color color.RGBA
|
|
|
|
CornerRadius unit.Value
|
|
|
|
CornerRadius unit.Value
|
|
|
|
CornerRadius2 float32
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (b Background) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions {
|
|
|
|
func (b Background) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions {
|
|
|
@ -874,16 +871,6 @@ func (b Background) Layout(gtx layout.Context, w layout.Widget) layout.Dimension
|
|
|
|
NE: rr, NW: rr, SE: rr, SW: rr,
|
|
|
|
NE: rr, NW: rr, SE: rr, SW: rr,
|
|
|
|
}.Add(gtx.Ops)
|
|
|
|
}.Add(gtx.Ops)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if r := b.CornerRadius2; r > 0 {
|
|
|
|
|
|
|
|
rr := float32(r)
|
|
|
|
|
|
|
|
clip.RRect{
|
|
|
|
|
|
|
|
Rect: f32.Rectangle{Max: f32.Point{
|
|
|
|
|
|
|
|
X: float32(sz.X),
|
|
|
|
|
|
|
|
Y: float32(sz.Y),
|
|
|
|
|
|
|
|
}},
|
|
|
|
|
|
|
|
NE: rr, NW: rr, SE: rr, SW: rr,
|
|
|
|
|
|
|
|
}.Add(gtx.Ops)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fill{b.Color}.Layout(gtx, sz)
|
|
|
|
fill{b.Color}.Layout(gtx, sz)
|
|
|
|
call.Add(gtx.Ops)
|
|
|
|
call.Add(gtx.Ops)
|
|
|
|
return dims
|
|
|
|
return dims
|
|
|
|