Fix hidden root section restore
This commit is contained in:
@@ -26,8 +26,8 @@ import (
|
|||||||
"gioui.org/widget"
|
"gioui.org/widget"
|
||||||
"gioui.org/widget/material"
|
"gioui.org/widget/material"
|
||||||
"git.julianfamily.org/keepassgo/api"
|
"git.julianfamily.org/keepassgo/api"
|
||||||
"git.julianfamily.org/keepassgo/apiaudit"
|
|
||||||
"git.julianfamily.org/keepassgo/apiapproval"
|
"git.julianfamily.org/keepassgo/apiapproval"
|
||||||
|
"git.julianfamily.org/keepassgo/apiaudit"
|
||||||
"git.julianfamily.org/keepassgo/apitokens"
|
"git.julianfamily.org/keepassgo/apitokens"
|
||||||
"git.julianfamily.org/keepassgo/appstate"
|
"git.julianfamily.org/keepassgo/appstate"
|
||||||
"git.julianfamily.org/keepassgo/clipboard"
|
"git.julianfamily.org/keepassgo/clipboard"
|
||||||
@@ -156,6 +156,7 @@ type ui struct {
|
|||||||
attachmentPath widget.Editor
|
attachmentPath widget.Editor
|
||||||
exportAttachmentPath widget.Editor
|
exportAttachmentPath widget.Editor
|
||||||
list widget.List
|
list widget.List
|
||||||
|
groupList widget.List
|
||||||
detailList widget.List
|
detailList widget.List
|
||||||
lifecycleList widget.List
|
lifecycleList widget.List
|
||||||
copyUser widget.Clickable
|
copyUser widget.Clickable
|
||||||
@@ -375,6 +376,9 @@ func newUIWithState(mode string, sess appstate.CurrentSession, paths statePaths)
|
|||||||
list: widget.List{
|
list: widget.List{
|
||||||
List: layout.List{Axis: layout.Vertical},
|
List: layout.List{Axis: layout.Vertical},
|
||||||
},
|
},
|
||||||
|
groupList: widget.List{
|
||||||
|
List: layout.List{Axis: layout.Vertical},
|
||||||
|
},
|
||||||
detailList: widget.List{
|
detailList: widget.List{
|
||||||
List: layout.List{Axis: layout.Vertical},
|
List: layout.List{Axis: layout.Vertical},
|
||||||
},
|
},
|
||||||
@@ -508,7 +512,9 @@ func (u *ui) selectedAttachmentNames() []string {
|
|||||||
|
|
||||||
func (u *ui) showEntriesSection() {
|
func (u *ui) showEntriesSection() {
|
||||||
u.resetPasswordPeek()
|
u.resetPasswordPeek()
|
||||||
|
preservedPath := append([]string(nil), u.currentPath...)
|
||||||
u.state.ShowSection(appstate.SectionEntries)
|
u.state.ShowSection(appstate.SectionEntries)
|
||||||
|
u.restoreEntriesPath(preservedPath)
|
||||||
u.filter()
|
u.filter()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1213,6 +1219,28 @@ func (u *ui) restoreRecentRemoteGroup(baseURL, path string) {
|
|||||||
u.enterHiddenVaultRoot()
|
u.enterHiddenVaultRoot()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *ui) restoreEntriesPath(path []string) {
|
||||||
|
if len(path) == 0 {
|
||||||
|
u.enterHiddenVaultRoot()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
model, err := u.state.Session.Current()
|
||||||
|
if err != nil {
|
||||||
|
u.enterHiddenVaultRoot()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
root := u.hiddenVaultRoot()
|
||||||
|
if len(path) == 1 && root != "" && path[0] == root {
|
||||||
|
u.setCurrentPath(path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(model.EntriesInPath(path)) > 0 || len(model.ChildGroups(path)) > 0 || hasExactGroup(model, path) {
|
||||||
|
u.setCurrentPath(path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
u.enterHiddenVaultRoot()
|
||||||
|
}
|
||||||
|
|
||||||
func (u *ui) displayPath() []string {
|
func (u *ui) displayPath() []string {
|
||||||
path := append([]string(nil), u.currentPath...)
|
path := append([]string(nil), u.currentPath...)
|
||||||
root := u.hiddenVaultRoot()
|
root := u.hiddenVaultRoot()
|
||||||
@@ -3033,21 +3061,28 @@ func (u *ui) groupBar(gtx layout.Context) layout.Dimensions {
|
|||||||
}),
|
}),
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||||
}
|
}
|
||||||
for i, group := range groups {
|
|
||||||
idx := i
|
|
||||||
name := group
|
|
||||||
children = append(children, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
children = append(children, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
const maxGroupListHeight = 160
|
||||||
|
maxY := gtx.Dp(unit.Dp(maxGroupListHeight))
|
||||||
|
if gtx.Constraints.Max.Y > maxY {
|
||||||
|
gtx.Constraints.Max.Y = maxY
|
||||||
|
}
|
||||||
|
if gtx.Constraints.Min.Y > gtx.Constraints.Max.Y {
|
||||||
|
gtx.Constraints.Min.Y = gtx.Constraints.Max.Y
|
||||||
|
}
|
||||||
|
return material.List(u.theme, &u.groupList).Layout(gtx, len(groups), func(gtx layout.Context, i int) layout.Dimensions {
|
||||||
|
idx := i
|
||||||
|
name := groups[i]
|
||||||
|
return layout.Inset{Bottom: unit.Dp(6)}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||||
for u.groupClicks[idx].Clicked(gtx) {
|
for u.groupClicks[idx].Clicked(gtx) {
|
||||||
u.state.EnterGroup(name)
|
u.state.EnterGroup(name)
|
||||||
u.currentPath = append([]string(nil), u.state.CurrentPath...)
|
u.currentPath = append([]string(nil), u.state.CurrentPath...)
|
||||||
u.filter()
|
u.filter()
|
||||||
}
|
}
|
||||||
return tonedButton(gtx, u.theme, &u.groupClicks[idx], name)
|
return tonedButton(gtx, u.theme, &u.groupClicks[idx], name)
|
||||||
|
})
|
||||||
|
})
|
||||||
}))
|
}))
|
||||||
if i < len(groups)-1 {
|
|
||||||
children = append(children, layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return children
|
return children
|
||||||
}()...)
|
}()...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2198,6 +2198,35 @@ func TestUIAutoEntersSingleVaultRootGroupAndDisplaysSlashRoot(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUIShowEntriesSectionRestoresHiddenRootAfterLeavingEntries(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
u := newUIWithModel("desktop", vault.Model{
|
||||||
|
Entries: []vault.Entry{
|
||||||
|
{ID: "1", Title: "Vault Console", Path: []string{"keepass", "Crew", "Internet"}},
|
||||||
|
{ID: "2", Title: "Home Assistant", Path: []string{"keepass", "Crew", "Home"}},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
u.showEntriesSection()
|
||||||
|
if got := u.currentPath; !slices.Equal(got, []string{"keepass"}) {
|
||||||
|
t.Fatalf("currentPath after initial entries section = %v, want [keepass]", got)
|
||||||
|
}
|
||||||
|
|
||||||
|
u.showAPITokensSection()
|
||||||
|
u.showEntriesSection()
|
||||||
|
|
||||||
|
if got := u.currentPath; !slices.Equal(got, []string{"keepass"}) {
|
||||||
|
t.Fatalf("currentPath after returning to entries = %v, want [keepass]", got)
|
||||||
|
}
|
||||||
|
if got := u.displayPath(); len(got) != 0 {
|
||||||
|
t.Fatalf("displayPath() after returning to entries = %v, want root slash path", got)
|
||||||
|
}
|
||||||
|
if got := u.childGroups(); !slices.Equal(got, []string{"Crew"}) {
|
||||||
|
t.Fatalf("childGroups() after returning to entries = %v, want [Crew]", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUINoteRecentVaultDeduplicatesAndOrdersMostRecentFirst(t *testing.T) {
|
func TestUINoteRecentVaultDeduplicatesAndOrdersMostRecentFirst(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user