Fix compact header overlay ordering

This commit is contained in:
Joe Julian
2026-04-10 18:55:02 -07:00
parent 550d9f362c
commit 54f13d352c
3 changed files with 55 additions and 26 deletions
+44 -25
View File
@@ -12,6 +12,7 @@ import (
"gioui.org/widget/material"
headerview "git.julianfamily.org/keepassgo/internal/appui/header"
headerlayout "git.julianfamily.org/keepassgo/internal/appui/header/layout"
"git.julianfamily.org/keepassgo/internal/appui/platform"
)
func (u *ui) header(gtx layout.Context) layout.Dimensions {
@@ -41,25 +42,34 @@ func (u *ui) headerActions(gtx layout.Context) layout.Dimensions {
}
cluster := u.newHeaderActionCluster(gtx)
surface := headerlayout.DropdownSurface{ContainerWidth: gtx.Constraints.Max.X, LeftInset: 0, TopInset: 0}
rowDims := layout.E.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
cluster.RowCall.Add(gtx.Ops)
return cluster.Metrics.RowDims
})
rowDims := cluster.layout(gtx, u)
if u.usesCompactViewport() {
u.maybeLogHeaderBounds(newHeaderButtonBounds(image.Pt(u.frameInsetPx, u.frameInsetPx), cluster.Metrics.Bounds()))
}
if u.usesCompactViewport() {
compactSurface := headerlayout.DropdownSurface{
ContainerWidth: gtx.Constraints.Max.X,
LeftInset: u.frameInsetPx,
TopInset: u.frameInsetPx,
}
if u.syncMenuOpen {
u.phoneSyncMenuVisible = true
u.phoneSyncMenuAnchor = cluster.Metrics.SyncAnchor().Point()
u.maybeLogHeaderMenuToggle("sync-visible", true)
placement, menuCall := compactSurface.Place(gtx, cluster.Metrics.SyncAnchor(), u.syncMenu)
u.phoneSyncMenuOrigin = placement.Origin
u.phoneSyncMenuCall = menuCall
u.maybeLogHeaderMenuPlacement("sync-phone", compactSurface, placement)
}
if u.mainMenuOpen {
u.phoneMainMenuVisible = true
u.phoneMainMenuAnchor = cluster.Metrics.MainAnchor().Point()
u.maybeLogHeaderMenuToggle("main-visible", true)
placement, menuCall := compactSurface.Place(gtx, cluster.Metrics.MainAnchor(), u.mainMenu)
u.phoneMainMenuOrigin = placement.Origin
u.phoneMainMenuCall = menuCall
u.maybeLogHeaderMenuPlacement("main-phone", compactSurface, placement)
}
return layout.Dimensions{Size: image.Pt(gtx.Constraints.Max.X, rowDims.Size.Y)}
}
@@ -84,7 +94,6 @@ func (u *ui) headerActions(gtx layout.Context) layout.Dimensions {
type headerActionCluster struct {
Metrics headerlayout.ActionMetrics
RowCall op.CallOp
SyncMenu layout.Widget
MainMenu layout.Widget
}
@@ -103,13 +112,20 @@ func (u *ui) newHeaderActionCluster(gtx layout.Context) headerActionCluster {
if !u.usesCompactViewport() {
cluster.Metrics.SyncInnerSpacing = gtx.Dp(unit.Dp(4))
}
rowOps := op.Record(gtx.Ops)
cluster.Metrics.RowDims = cluster.layoutRow(gtx, u)
cluster.RowCall = rowOps.Stop()
cluster.Metrics.RowOriginX = max(0, gtx.Constraints.Max.X-cluster.Metrics.RowDims.Size.X)
return cluster
}
func (c *headerActionCluster) layout(gtx layout.Context, u *ui) layout.Dimensions {
rowOps := op.Record(gtx.Ops)
c.Metrics.RowDims = c.layoutRow(gtx, u)
rowCall := rowOps.Stop()
c.Metrics.RowOriginX = max(0, gtx.Constraints.Max.X-c.Metrics.RowDims.Size.X)
return layout.E.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
rowCall.Add(gtx.Ops)
return c.Metrics.RowDims
})
}
func (c *headerActionCluster) layoutRow(gtx layout.Context, u *ui) layout.Dimensions {
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
@@ -169,29 +185,32 @@ func (u *ui) topRightActionOrder() []string {
}
func (u *ui) phoneHeaderMenus(gtx layout.Context) layout.Dimensions {
if u.debugLogHeaderBounds {
platform.LogInfo("KeePassGO", fmt.Sprintf(
"keepassgo phone-header-menus compact=%t syncVisible=%t syncOpen=%t mainVisible=%t mainOpen=%t syncCall=%t mainCall=%t max=%dx%d",
u.usesCompactViewport(),
u.phoneSyncMenuVisible,
u.syncMenuOpen,
u.phoneMainMenuVisible,
u.mainMenuOpen,
u.phoneSyncMenuCall != (op.CallOp{}),
u.phoneMainMenuCall != (op.CallOp{}),
gtx.Constraints.Max.X,
gtx.Constraints.Max.Y,
))
}
if !u.usesCompactViewport() || (!u.syncMenuVisibleOnPhone() && !u.mainMenuVisibleOnPhone()) {
return layout.Dimensions{}
}
gtx.Constraints.Min = gtx.Constraints.Max
contentInsetPx := gtx.Dp(unit.Dp(16))
surface := headerlayout.DropdownSurface{
ContainerWidth: max(0, gtx.Constraints.Max.X-(contentInsetPx*2)),
LeftInset: contentInsetPx,
TopInset: contentInsetPx,
}
if u.syncMenuVisibleOnPhone() {
placement, menuCall := surface.Place(gtx, headerlayout.DropdownAnchor{TriggerRightX: u.phoneSyncMenuAnchor.X, TriggerBottomY: u.phoneSyncMenuAnchor.Y}, u.syncMenu)
u.maybeLogHeaderMenuPlacement("sync-phone", surface, placement)
stack := op.Offset(placement.Origin).Push(gtx.Ops)
menuCall.Add(gtx.Ops)
stack := op.Offset(u.phoneSyncMenuOrigin).Push(gtx.Ops)
u.phoneSyncMenuCall.Add(gtx.Ops)
stack.Pop()
}
if u.mainMenuVisibleOnPhone() {
placement, menuCall := surface.Place(gtx, headerlayout.DropdownAnchor{TriggerRightX: u.phoneMainMenuAnchor.X, TriggerBottomY: u.phoneMainMenuAnchor.Y}, u.mainMenu)
u.maybeLogHeaderMenuPlacement("main-phone", surface, placement)
stack := op.Offset(placement.Origin).Push(gtx.Ops)
menuCall.Add(gtx.Ops)
stack := op.Offset(u.phoneMainMenuOrigin).Push(gtx.Ops)
u.phoneMainMenuCall.Add(gtx.Ops)
stack.Pop()
}
return layout.Dimensions{Size: gtx.Constraints.Max}