Add collapsible group tools section

This commit is contained in:
Joe Julian
2026-03-29 16:39:27 -07:00
parent db06fcd385
commit 2e9e2aae5f
3 changed files with 79 additions and 1 deletions
+10 -1
View File
@@ -152,6 +152,7 @@ type ui struct {
confirmDeleteGroup widget.Clickable
cancelDeleteGroup widget.Clickable
addCustomField widget.Clickable
toggleGroupControls widget.Clickable
togglePasswordInline widget.Clickable
showEntries widget.Clickable
showTemplates widget.Clickable
@@ -180,6 +181,8 @@ type ui struct {
eyeIcon *widget.Icon
eyeOffIcon *widget.Icon
copyIcon *widget.Icon
expandMoreIcon *widget.Icon
expandLessIcon *widget.Icon
clipboardWriter clipboard.Writer
loadingMessage string
lifecycleMode string
@@ -187,6 +190,7 @@ type ui struct {
defaultSaveAsPath string
recentVaultsPath string
editingEntry bool
groupControlsHidden bool
recentVaults []string
recentVaultGroups map[string][]string
deleteGroupPath []string
@@ -280,6 +284,8 @@ func newUIWithState(mode string, sess appstate.CurrentSession, paths statePaths)
u.eyeIcon, _ = widget.NewIcon(icons.ActionVisibility)
u.eyeOffIcon, _ = widget.NewIcon(icons.ActionVisibilityOff)
u.copyIcon, _ = widget.NewIcon(icons.ContentContentCopy)
u.expandMoreIcon, _ = widget.NewIcon(icons.NavigationExpandMore)
u.expandLessIcon, _ = widget.NewIcon(icons.NavigationExpandLess)
u.passwordProfile.SetText("strong")
u.keyboardFocus = focusSearch
u.setCustomFieldRows(nil)
@@ -1173,6 +1179,9 @@ func (u *ui) layout(gtx layout.Context) layout.Dimensions {
u.clearDeleteGroupConfirmation()
u.runAction("create group", u.createGroupAction)
}
for u.toggleGroupControls.Clicked(gtx) {
u.groupControlsHidden = !u.groupControlsHidden
}
for u.renameGroup.Clicked(gtx) {
u.clearDeleteGroupConfirmation()
u.runAction("rename group", u.renameGroupAction)
@@ -1358,7 +1367,7 @@ func (u *ui) listPanel(gtx layout.Context) layout.Dimensions {
if u.isVaultLocked() {
return layout.Dimensions{}
}
return u.groupControls(gtx)
return u.groupControlsSection(gtx)
}),
layout.Rigid(layout.Spacer{Height: spacing}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
+21
View File
@@ -787,6 +787,27 @@ func TestUIGroupManagementAndPathNavigationAreControllerDriven(t *testing.T) {
}
}
func TestUIGroupControlsCanBeCollapsed(t *testing.T) {
t.Parallel()
u := newUIWithModel("desktop", vault.Model{})
u.showEntriesSection()
if u.groupControlsHidden {
t.Fatal("groupControlsHidden = true, want false by default")
}
u.groupControlsHidden = true
if !u.groupControlsHidden {
t.Fatal("groupControlsHidden = false, want true after collapsing")
}
u.groupControlsHidden = false
if u.groupControlsHidden {
t.Fatal("groupControlsHidden = true, want false after expanding")
}
}
func TestUISavingEntryWithDifferentPathMovesItBetweenGroups(t *testing.T) {
t.Parallel()
+48
View File
@@ -256,6 +256,54 @@ func (u *ui) groupControls(gtx layout.Context) layout.Dimensions {
)
}
func (u *ui) groupControlsSection(gtx layout.Context) layout.Dimensions {
if u.state.Section != appstate.SectionEntries {
return layout.Dimensions{}
}
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return u.groupControlsDisclosure(gtx)
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
if u.groupControlsHidden {
return layout.Dimensions{}
}
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
layout.Rigid(u.groupControls),
)
}),
)
}
func (u *ui) groupControlsDisclosure(gtx layout.Context) layout.Dimensions {
return u.toggleGroupControls.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
icon := u.expandLessIcon
if u.groupControlsHidden {
icon = u.expandMoreIcon
}
if icon == nil {
lbl := material.Label(u.theme, unit.Sp(16), ">")
if !u.groupControlsHidden {
lbl.Text = "v"
}
lbl.Color = accentColor
return lbl.Layout(gtx)
}
return icon.Layout(gtx, accentColor)
}),
layout.Rigid(layout.Spacer{Width: unit.Dp(4)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
lbl := material.Label(u.theme, unit.Sp(13), "Group Tools")
lbl.Color = accentColor
return lbl.Layout(gtx)
}),
)
})
}
func (u *ui) entryEditorPanel(gtx layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(labeledEditorWithFocus(u.theme, "Title", &u.entryTitle, false, u.isFocused(detailFocusID(detailFieldTitle)))),