Use desktop overlay model for phone header menus

This commit is contained in:
Joe Julian
2026-04-08 20:40:20 -07:00
parent 7a50138640
commit 168927713c
2 changed files with 35 additions and 39 deletions
+22 -39
View File
@@ -5512,36 +5512,8 @@ func (u *ui) header(gtx layout.Context) layout.Dimensions {
if u.shouldShowLifecycleSetup() || u.isVaultLocked() {
return layout.Dimensions{}
}
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
gtx.Constraints.Min.X = gtx.Constraints.Max.X
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), Left: unit.Dp(16), Right: unit.Dp(16)}.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{}
measureGTX.Constraints.Max.X = gtx.Constraints.Max.X
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)
})
})
}),
)
gtx.Constraints.Min.X = gtx.Constraints.Max.X
return u.headerActions(gtx)
}
if u.shouldShowDesktopWorkingHeader() {
return layout.Dimensions{}
@@ -7348,22 +7320,29 @@ func (u *ui) phoneHeaderMenus(gtx layout.Context) layout.Dimensions {
return layout.Dimensions{}
}
gtx.Constraints.Min = gtx.Constraints.Max
contentInsetPx := gtx.Dp(unit.Dp(16))
contentWidth := max(0, gtx.Constraints.Max.X-(contentInsetPx*2))
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)
})
menuGTX := gtx
menuGTX.Constraints.Min = image.Point{}
menuGTX.Constraints.Max.X = contentWidth
menuOps := op.Record(gtx.Ops)
menuDims := layout.Inset{Top: unit.Dp(6)}.Layout(menuGTX, menu)
menuCall := menuOps.Stop()
menuX := contentInsetPx + anchoredMenuOriginX(contentWidth, 0, anchor.X, menuDims.Size.X)
menuY := contentInsetPx + anchor.Y
stack := op.Offset(image.Pt(menuX, menuY)).Push(gtx.Ops)
menuCall.Add(gtx.Ops)
stack.Pop()
return layout.Dimensions{Size: gtx.Constraints.Max}
}
if u.syncMenuVisibleOnPhone() {
drawMenu(u.phoneSyncMenuAnchor, u.syncMenu)
_ = drawMenu(u.phoneSyncMenuAnchor, u.syncMenu)
}
if u.mainMenuVisibleOnPhone() {
drawMenu(u.phoneMainMenuAnchor, u.mainMenu)
_ = drawMenu(u.phoneMainMenuAnchor, u.mainMenu)
}
return layout.Dimensions{Size: gtx.Constraints.Max}
}
@@ -7384,6 +7363,10 @@ func (u *ui) syncMenuRightAlignsToTrigger() bool {
return true
}
func (u *ui) headerMenusUseOverlayModel() bool {
return true
}
func (u *ui) mainMenuDropsBelowTrigger() bool {
return true
}
+13
View File
@@ -356,6 +356,19 @@ func TestUIMainMenuAnchorsMatchAcrossModes(t *testing.T) {
}
}
func TestUIHeaderMenusUseOverlayModelAcrossModes(t *testing.T) {
t.Parallel()
desktop := newUIWithSession("desktop", summarySession{hasVault: true})
desktop.state.Section = appstate.SectionEntries
phone := newUIWithSession("phone", summarySession{hasVault: true})
phone.state.Section = appstate.SectionEntries
if !desktop.headerMenusUseOverlayModel() || !phone.headerMenusUseOverlayModel() {
t.Fatal("header menus should use the same overlay model across desktop and phone")
}
}
func TestAnchoredMenuXAllowsWiderMenusToExtendLeft(t *testing.T) {
t.Parallel()