Make phone entry pane fully scrollable

This commit is contained in:
Joe Julian
2026-04-02 21:38:51 -07:00
parent 7691104d9e
commit f2e4e707cf
2 changed files with 117 additions and 0 deletions
+85
View File
@@ -245,6 +245,7 @@ type ui struct {
detailList widget.List
apiPolicyList widget.List
lifecycleList widget.List
phonePanelList widget.List
recentVaultListState widget.List
recentRemoteListState widget.List
copyUser widget.Clickable
@@ -556,6 +557,9 @@ func newUIWithState(mode string, sess appstate.CurrentSession, paths statePaths)
lifecycleList: widget.List{
List: layout.List{Axis: layout.Vertical},
},
phonePanelList: widget.List{
List: layout.List{Axis: layout.Vertical},
},
recentVaultListState: widget.List{
List: layout.List{Axis: layout.Vertical},
},
@@ -4026,6 +4030,87 @@ func (u *ui) listPanel(gtx layout.Context) layout.Dimensions {
panel = compactCard
}
u.ensureNavClickables()
if u.mode == "phone" {
return panel(gtx, func(gtx layout.Context) layout.Dimensions {
rows := make([]layout.Widget, 0, 16+len(u.visible))
if !u.isVaultLocked() {
rows = append(rows, u.navigationHeader)
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
return layout.Spacer{Height: spacing}.Layout(gtx)
})
}
if !u.isVaultLocked() && u.state.Section == appstate.SectionRecycleBin {
rows = append(rows, u.recycleBinSectionNotice)
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
return layout.Spacer{Height: spacing}.Layout(gtx)
})
}
if !u.isVaultLocked() && (u.state.Section == appstate.SectionEntries || u.state.Section == appstate.SectionRecycleBin) {
rows = append(rows, u.pathBar)
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
return layout.Spacer{Height: spacing}.Layout(gtx)
})
}
if !u.isVaultLocked() && u.state.Section == appstate.SectionEntries {
rows = append(rows, u.groupBar)
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
return layout.Spacer{Height: spacing}.Layout(gtx)
})
rows = append(rows, u.groupControlsSection)
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
return layout.Spacer{Height: spacing}.Layout(gtx)
})
}
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
gtx.Constraints.Min.X = gtx.Constraints.Max.X
return u.outlinedFieldState(gtx, u.isFocused(focusSearch), func(gtx layout.Context) layout.Dimensions {
editor := material.Editor(u.theme, &u.search, "Search vault")
editor.Color = u.theme.Palette.Fg
editor.HintColor = mutedColor
return layout.UniformInset(unit.Dp(10)).Layout(gtx, editor.Layout)
})
})
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
return layout.Spacer{Height: spacing}.Layout(gtx)
})
if !u.isVaultLocked() {
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
switch u.state.Section {
case appstate.SectionEntries:
btn := material.Button(u.theme, &u.addEntry, "+ Add Entry")
return btn.Layout(gtx)
case appstate.SectionAPITokens:
return tonedButton(gtx, u.theme, &u.issueAPIToken, "Issue API Token")
default:
return layout.Dimensions{}
}
})
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
return layout.Spacer{Height: spacing}.Layout(gtx)
})
}
switch {
case u.state.Section == appstate.SectionAPITokens:
rows = append(rows, u.apiTokenListPanel)
case u.state.Section == appstate.SectionAPIAudit:
rows = append(rows, u.apiAuditListPanel)
case len(u.visible) == 0:
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
return emptyStatePanel(gtx, u.theme, u.listEmptyState())
})
default:
for i := range u.visible {
idx := i
rows = append(rows, func(gtx layout.Context) layout.Dimensions {
return u.entryRow(gtx, &u.entryClicks[idx], idx, u.visible[idx])
})
}
}
return material.List(u.theme, &u.phonePanelList).Layout(gtx, len(rows), func(gtx layout.Context, i int) layout.Dimensions {
return rows[i](gtx)
})
})
}
return panel(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {