Fix Android header menus
This commit is contained in:
@@ -518,6 +518,10 @@ type ui struct {
|
|||||||
deleteGroupPath []string
|
deleteGroupPath []string
|
||||||
apiPolicyGroupScope bool
|
apiPolicyGroupScope bool
|
||||||
apiTokenSecret string
|
apiTokenSecret string
|
||||||
|
phoneSyncMenuAnchor image.Point
|
||||||
|
phoneMainMenuAnchor image.Point
|
||||||
|
phoneSyncMenuVisible bool
|
||||||
|
phoneMainMenuVisible bool
|
||||||
selectedAuditIndex int
|
selectedAuditIndex int
|
||||||
statusExpiresAt time.Time
|
statusExpiresAt time.Time
|
||||||
now func() time.Time
|
now func() time.Time
|
||||||
@@ -4132,6 +4136,8 @@ func (u *ui) layout(gtx layout.Context) layout.Dimensions {
|
|||||||
// Clear the full frame explicitly so mobile surfaces don't start from an
|
// Clear the full frame explicitly so mobile surfaces don't start from an
|
||||||
// unpainted black buffer before nested background widgets run.
|
// unpainted black buffer before nested background widgets run.
|
||||||
paint.FillShape(gtx.Ops, bgColor, clip.Rect{Max: gtx.Constraints.Max}.Op())
|
paint.FillShape(gtx.Ops, bgColor, clip.Rect{Max: gtx.Constraints.Max}.Op())
|
||||||
|
u.phoneSyncMenuVisible = false
|
||||||
|
u.phoneMainMenuVisible = false
|
||||||
u.syncHostedAPI()
|
u.syncHostedAPI()
|
||||||
u.filter()
|
u.filter()
|
||||||
u.processShortcuts(gtx)
|
u.processShortcuts(gtx)
|
||||||
@@ -4164,9 +4170,15 @@ func (u *ui) layout(gtx layout.Context) layout.Dimensions {
|
|||||||
}
|
}
|
||||||
for u.toggleSyncMenu.Clicked(gtx) {
|
for u.toggleSyncMenu.Clicked(gtx) {
|
||||||
u.syncMenuOpen = !u.syncMenuOpen
|
u.syncMenuOpen = !u.syncMenuOpen
|
||||||
|
if u.syncMenuOpen {
|
||||||
|
u.mainMenuOpen = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for u.toggleMainMenu.Clicked(gtx) {
|
for u.toggleMainMenu.Clicked(gtx) {
|
||||||
u.mainMenuOpen = !u.mainMenuOpen
|
u.mainMenuOpen = !u.mainMenuOpen
|
||||||
|
if u.mainMenuOpen {
|
||||||
|
u.syncMenuOpen = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for u.openAdvancedSync.Clicked(gtx) {
|
for u.openAdvancedSync.Clicked(gtx) {
|
||||||
u.openAdvancedSyncDialog()
|
u.openAdvancedSyncDialog()
|
||||||
@@ -4773,6 +4785,9 @@ func (u *ui) layout(gtx layout.Context) layout.Dimensions {
|
|||||||
}
|
}
|
||||||
return u.approvalDialog(gtx)
|
return u.approvalDialog(gtx)
|
||||||
}),
|
}),
|
||||||
|
layout.Stacked(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
return u.phoneHeaderMenus(gtx)
|
||||||
|
}),
|
||||||
layout.Stacked(u.statusToast),
|
layout.Stacked(u.statusToast),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -5502,6 +5517,29 @@ func (u *ui) header(gtx layout.Context) layout.Dimensions {
|
|||||||
gtx.Constraints.Min.X = gtx.Constraints.Max.X
|
gtx.Constraints.Min.X = gtx.Constraints.Max.X
|
||||||
return u.headerActions(gtx)
|
return u.headerActions(gtx)
|
||||||
}),
|
}),
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
if !u.syncMenuOpen && !u.mainMenuOpen {
|
||||||
|
return layout.Dimensions{}
|
||||||
|
}
|
||||||
|
return layout.Inset{Top: unit.Dp(6)}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||||
|
return layout.E.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||||
|
var menu layout.Widget
|
||||||
|
if u.syncMenuOpen {
|
||||||
|
menu = u.syncMenu
|
||||||
|
} else {
|
||||||
|
menu = u.mainMenu
|
||||||
|
}
|
||||||
|
measureGTX := gtx
|
||||||
|
measureGTX.Constraints.Min = image.Point{}
|
||||||
|
macro := op.Record(gtx.Ops)
|
||||||
|
dims := menu(measureGTX)
|
||||||
|
_ = macro.Stop()
|
||||||
|
gtx.Constraints.Min.X = dims.Size.X
|
||||||
|
gtx.Constraints.Max.X = dims.Size.X
|
||||||
|
return menu(gtx)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if u.shouldShowDesktopWorkingHeader() {
|
if u.shouldShowDesktopWorkingHeader() {
|
||||||
@@ -5575,6 +5613,20 @@ func (u *ui) headerActions(gtx layout.Context) layout.Dimensions {
|
|||||||
rowCall.Add(gtx.Ops)
|
rowCall.Add(gtx.Ops)
|
||||||
rowStack.Pop()
|
rowStack.Pop()
|
||||||
|
|
||||||
|
if u.mode == "phone" {
|
||||||
|
if u.syncMenuOpen {
|
||||||
|
u.phoneSyncMenuVisible = true
|
||||||
|
u.phoneSyncMenuAnchor = image.Pt(rowOriginX+syncDims.Size.X, rowDims.Size.Y)
|
||||||
|
}
|
||||||
|
if u.mainMenuOpen {
|
||||||
|
triggerRightX := syncDims.Size.X + spacing + lockDims.Size.X + spacing + mainDims.Size.X
|
||||||
|
u.phoneMainMenuVisible = true
|
||||||
|
u.phoneMainMenuAnchor = image.Pt(rowOriginX+triggerRightX, rowDims.Size.Y)
|
||||||
|
}
|
||||||
|
width := gtx.Constraints.Max.X
|
||||||
|
return layout.Dimensions{Size: image.Pt(width, rowDims.Size.Y)}
|
||||||
|
}
|
||||||
|
|
||||||
if u.syncMenuOpen {
|
if u.syncMenuOpen {
|
||||||
drawMenu(u.syncMenu, syncDims.Size.X, rowDims.Size.Y)
|
drawMenu(u.syncMenu, syncDims.Size.X, rowDims.Size.Y)
|
||||||
}
|
}
|
||||||
@@ -5584,9 +5636,6 @@ func (u *ui) headerActions(gtx layout.Context) layout.Dimensions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
width := rowDims.Size.X
|
width := rowDims.Size.X
|
||||||
if u.mode == "phone" {
|
|
||||||
width = gtx.Constraints.Max.X
|
|
||||||
}
|
|
||||||
return layout.Dimensions{Size: image.Pt(width, rowDims.Size.Y)}
|
return layout.Dimensions{Size: image.Pt(width, rowDims.Size.Y)}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5600,7 +5649,7 @@ func (u *ui) mainMenu(gtx layout.Context) layout.Dimensions {
|
|||||||
func(gtx layout.Context) layout.Dimensions { return tonedButton(gtx, u.theme, &u.openSecuritySettings, "Settings") },
|
func(gtx layout.Context) layout.Dimensions { return tonedButton(gtx, u.theme, &u.openSecuritySettings, "Settings") },
|
||||||
}
|
}
|
||||||
rowWidth := menuActionWidth(gtx, rows)
|
rowWidth := menuActionWidth(gtx, rows)
|
||||||
return compactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
return intrinsicCompactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
return rightAlignedMenuAction(gtx, rowWidth, rows[0])
|
return rightAlignedMenuAction(gtx, rowWidth, rows[0])
|
||||||
@@ -5715,8 +5764,13 @@ func (u *ui) syncButtonGroup(gtx layout.Context) layout.Dimensions {
|
|||||||
|
|
||||||
func (u *ui) syncMenuToggle(gtx layout.Context) layout.Dimensions {
|
func (u *ui) syncMenuToggle(gtx layout.Context) layout.Dimensions {
|
||||||
btn := material.IconButton(u.theme, &u.toggleSyncMenu, u.chevronDownIcon, "More synchronize actions")
|
btn := material.IconButton(u.theme, &u.toggleSyncMenu, u.chevronDownIcon, "More synchronize actions")
|
||||||
|
if u.syncMenuOpen {
|
||||||
|
btn.Background = accentColor
|
||||||
|
btn.Color = color.NRGBA{R: 255, G: 252, B: 247, A: 255}
|
||||||
|
} else {
|
||||||
btn.Background = color.NRGBA{R: 231, G: 236, B: 232, A: 255}
|
btn.Background = color.NRGBA{R: 231, G: 236, B: 232, A: 255}
|
||||||
btn.Color = accentColor
|
btn.Color = accentColor
|
||||||
|
}
|
||||||
btn.Size = unit.Dp(18)
|
btn.Size = unit.Dp(18)
|
||||||
btn.Inset = layout.UniformInset(unit.Dp(8))
|
btn.Inset = layout.UniformInset(unit.Dp(8))
|
||||||
if u.mode == "phone" {
|
if u.mode == "phone" {
|
||||||
@@ -5764,7 +5818,7 @@ func (u *ui) syncMenu(gtx layout.Context) layout.Dimensions {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
actionWidth := menuActionWidth(gtx, actionRows)
|
actionWidth := menuActionWidth(gtx, actionRows)
|
||||||
return compactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
return intrinsicCompactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||||
rows := []layout.FlexChild{
|
rows := []layout.FlexChild{
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
lbl := material.Label(u.theme, unit.Sp(11), "Need another source or direction?")
|
lbl := material.Label(u.theme, unit.Sp(11), "Need another source or direction?")
|
||||||
@@ -5951,6 +6005,20 @@ func (u *ui) syncMenu(gtx layout.Context) layout.Dimensions {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func intrinsicCompactCard(gtx layout.Context, w layout.Widget) layout.Dimensions {
|
||||||
|
measureGTX := gtx
|
||||||
|
measureGTX.Constraints.Min = image.Point{}
|
||||||
|
macro := op.Record(gtx.Ops)
|
||||||
|
contentDims := w(measureGTX)
|
||||||
|
_ = macro.Stop()
|
||||||
|
width := contentDims.Size.X + gtx.Dp(unit.Dp(20))
|
||||||
|
if width > 0 {
|
||||||
|
gtx.Constraints.Min.X = width
|
||||||
|
gtx.Constraints.Max.X = width
|
||||||
|
}
|
||||||
|
return compactCard(gtx, w)
|
||||||
|
}
|
||||||
|
|
||||||
func (u *ui) sectionSpacing() unit.Dp {
|
func (u *ui) sectionSpacing() unit.Dp {
|
||||||
if u.mode == "phone" {
|
if u.mode == "phone" {
|
||||||
if u.denseLayout {
|
if u.denseLayout {
|
||||||
@@ -7252,8 +7320,13 @@ func (u *ui) mainMenuButtonGroup(gtx layout.Context) layout.Dimensions {
|
|||||||
icon = u.settingsIcon
|
icon = u.settingsIcon
|
||||||
}
|
}
|
||||||
btn := material.IconButton(u.theme, &u.toggleMainMenu, icon, "Menu")
|
btn := material.IconButton(u.theme, &u.toggleMainMenu, icon, "Menu")
|
||||||
|
if u.mainMenuOpen {
|
||||||
|
btn.Background = accentColor
|
||||||
|
btn.Color = color.NRGBA{R: 255, G: 252, B: 247, A: 255}
|
||||||
|
} else {
|
||||||
btn.Background = selectedColor
|
btn.Background = selectedColor
|
||||||
btn.Color = accentColor
|
btn.Color = accentColor
|
||||||
|
}
|
||||||
btn.Size = unit.Dp(18)
|
btn.Size = unit.Dp(18)
|
||||||
btn.Inset = layout.UniformInset(unit.Dp(8))
|
btn.Inset = layout.UniformInset(unit.Dp(8))
|
||||||
return btn.Layout(gtx)
|
return btn.Layout(gtx)
|
||||||
@@ -7261,6 +7334,42 @@ func (u *ui) mainMenuButtonGroup(gtx layout.Context) layout.Dimensions {
|
|||||||
return button(gtx)
|
return button(gtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *ui) phoneHeaderMenus(gtx layout.Context) layout.Dimensions {
|
||||||
|
if u.mode != "phone" {
|
||||||
|
return layout.Dimensions{}
|
||||||
|
}
|
||||||
|
if !u.syncMenuVisibleOnPhone() && !u.mainMenuVisibleOnPhone() {
|
||||||
|
return layout.Dimensions{}
|
||||||
|
}
|
||||||
|
gtx.Constraints.Min = gtx.Constraints.Max
|
||||||
|
|
||||||
|
drawMenu := func(anchor image.Point, menu layout.Widget) layout.Dimensions {
|
||||||
|
_ = anchor
|
||||||
|
return layout.NE.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||||
|
return layout.Inset{
|
||||||
|
Top: unit.Dp(56),
|
||||||
|
Right: unit.Dp(16),
|
||||||
|
}.Layout(gtx, menu)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.syncMenuVisibleOnPhone() {
|
||||||
|
drawMenu(u.phoneSyncMenuAnchor, u.syncMenu)
|
||||||
|
}
|
||||||
|
if u.mainMenuVisibleOnPhone() {
|
||||||
|
drawMenu(u.phoneMainMenuAnchor, u.mainMenu)
|
||||||
|
}
|
||||||
|
return layout.Dimensions{Size: gtx.Constraints.Max}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ui) syncMenuVisibleOnPhone() bool {
|
||||||
|
return u.mode == "phone" && u.phoneSyncMenuVisible && u.syncMenuOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *ui) mainMenuVisibleOnPhone() bool {
|
||||||
|
return u.mode == "phone" && u.phoneMainMenuVisible && u.mainMenuOpen
|
||||||
|
}
|
||||||
|
|
||||||
func (u *ui) syncMenuDropsBelowTrigger() bool {
|
func (u *ui) syncMenuDropsBelowTrigger() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -7510,6 +7619,9 @@ func menuActionWidth(gtx layout.Context, rows []layout.Widget) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func rightAlignedMenuAction(gtx layout.Context, width int, child layout.Widget) layout.Dimensions {
|
func rightAlignedMenuAction(gtx layout.Context, width int, child layout.Widget) layout.Dimensions {
|
||||||
|
if width < gtx.Constraints.Max.X {
|
||||||
|
width = gtx.Constraints.Max.X
|
||||||
|
}
|
||||||
if width <= 0 {
|
if width <= 0 {
|
||||||
return child(gtx)
|
return child(gtx)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user