Scroll lifecycle screen and restore remote groups
This commit is contained in:
@@ -91,6 +91,7 @@ type recentRemoteRecord struct {
|
||||
Path string `json:"path"`
|
||||
Username string `json:"username,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
LastGroup []string `json:"lastGroup,omitempty"`
|
||||
}
|
||||
|
||||
type ui struct {
|
||||
@@ -124,6 +125,7 @@ type ui struct {
|
||||
exportAttachmentPath widget.Editor
|
||||
list widget.List
|
||||
detailList widget.List
|
||||
lifecycleList widget.List
|
||||
copyUser widget.Clickable
|
||||
copyPass widget.Clickable
|
||||
copyURL widget.Clickable
|
||||
@@ -283,6 +285,9 @@ func newUIWithState(mode string, sess appstate.CurrentSession, paths statePaths)
|
||||
detailList: widget.List{
|
||||
List: layout.List{Axis: layout.Vertical},
|
||||
},
|
||||
lifecycleList: widget.List{
|
||||
List: layout.List{Axis: layout.Vertical},
|
||||
},
|
||||
state: appstate.State{},
|
||||
selectedHistoryIndex: -1,
|
||||
lifecycleMode: "local",
|
||||
@@ -583,7 +588,7 @@ func (u *ui) openRemoteAction() error {
|
||||
u.rememberRemoteAuth.Value,
|
||||
)
|
||||
u.resetPasswordPeek()
|
||||
u.enterHiddenVaultRoot()
|
||||
u.restoreRecentRemoteGroup(strings.TrimSpace(u.remoteBaseURL.Text()), strings.TrimSpace(u.remotePath.Text()))
|
||||
u.editingEntry = false
|
||||
u.filter()
|
||||
return nil
|
||||
@@ -753,6 +758,7 @@ func (u *ui) loadRecentRemotes() {
|
||||
continue
|
||||
}
|
||||
seen[key] = true
|
||||
record.LastGroup = append([]string(nil), record.LastGroup...)
|
||||
filtered = append(filtered, record)
|
||||
if len(filtered) == 6 {
|
||||
break
|
||||
@@ -806,8 +812,12 @@ func (u *ui) noteRecentRemote(baseURL, path, username, password string, remember
|
||||
return
|
||||
}
|
||||
record := recentRemoteRecord{
|
||||
BaseURL: baseURL,
|
||||
Path: path,
|
||||
BaseURL: baseURL,
|
||||
Path: path,
|
||||
LastGroup: append([]string(nil), u.currentPath...),
|
||||
}
|
||||
if len(record.LastGroup) == 0 {
|
||||
record.LastGroup = u.recentRemoteGroup(baseURL, path)
|
||||
}
|
||||
if rememberAuth {
|
||||
record.Username = strings.TrimSpace(username)
|
||||
@@ -830,6 +840,37 @@ func (u *ui) noteRecentRemote(baseURL, path, username, password string, remember
|
||||
u.saveRecentRemotes()
|
||||
}
|
||||
|
||||
func (u *ui) recentRemoteGroup(baseURL, path string) []string {
|
||||
baseURL = strings.TrimSpace(baseURL)
|
||||
path = strings.TrimSpace(path)
|
||||
for _, record := range u.recentRemotes {
|
||||
if record.BaseURL == baseURL && record.Path == path {
|
||||
return append([]string(nil), record.LastGroup...)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *ui) noteCurrentRemotePath() {
|
||||
status, ok := u.state.Session.(sessionStatus)
|
||||
if !ok || !status.IsRemote() || status.IsLocked() {
|
||||
return
|
||||
}
|
||||
baseURL := strings.TrimSpace(u.remoteBaseURL.Text())
|
||||
path := strings.TrimSpace(u.remotePath.Text())
|
||||
if baseURL == "" || path == "" {
|
||||
return
|
||||
}
|
||||
for i := range u.recentRemotes {
|
||||
if u.recentRemotes[i].BaseURL != baseURL || u.recentRemotes[i].Path != path {
|
||||
continue
|
||||
}
|
||||
u.recentRemotes[i].LastGroup = append([]string(nil), u.currentPath...)
|
||||
u.saveRecentRemotes()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (u *ui) recentVaultGroup(path string) []string {
|
||||
if u.recentVaultGroups == nil {
|
||||
return nil
|
||||
@@ -886,6 +927,29 @@ func (u *ui) restoreRecentVaultGroup(path string) {
|
||||
u.enterHiddenVaultRoot()
|
||||
}
|
||||
|
||||
func (u *ui) restoreRecentRemoteGroup(baseURL, path string) {
|
||||
saved := u.recentRemoteGroup(baseURL, path)
|
||||
if len(saved) == 0 {
|
||||
u.enterHiddenVaultRoot()
|
||||
return
|
||||
}
|
||||
model, err := u.state.Session.Current()
|
||||
if err != nil {
|
||||
u.enterHiddenVaultRoot()
|
||||
return
|
||||
}
|
||||
root := u.hiddenVaultRoot()
|
||||
if len(saved) == 1 && root != "" && saved[0] == root {
|
||||
u.setCurrentPath(saved)
|
||||
return
|
||||
}
|
||||
if len(model.EntriesInPath(saved)) > 0 || len(model.ChildGroups(saved)) > 0 || hasExactGroup(model, saved) {
|
||||
u.setCurrentPath(saved)
|
||||
return
|
||||
}
|
||||
u.enterHiddenVaultRoot()
|
||||
}
|
||||
|
||||
func (u *ui) displayPath() []string {
|
||||
path := append([]string(nil), u.currentPath...)
|
||||
root := u.hiddenVaultRoot()
|
||||
@@ -1175,7 +1239,11 @@ func (u *ui) syncCurrentPath() {
|
||||
|
||||
func (u *ui) noteCurrentVaultPath() {
|
||||
status, ok := u.state.Session.(sessionStatus)
|
||||
if !ok || status.IsRemote() || status.IsLocked() {
|
||||
if !ok || status.IsLocked() {
|
||||
return
|
||||
}
|
||||
if status.IsRemote() {
|
||||
u.noteCurrentRemotePath()
|
||||
return
|
||||
}
|
||||
path := strings.TrimSpace(u.vaultPath.Text())
|
||||
@@ -1372,7 +1440,7 @@ func (u *ui) layout(gtx layout.Context) layout.Dimensions {
|
||||
}),
|
||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||||
if u.shouldShowLifecycleSetup() {
|
||||
return layout.Dimensions{}
|
||||
return u.lifecycleScreen(gtx)
|
||||
}
|
||||
if u.shouldUseLockedSinglePane() {
|
||||
return u.detailPanel(gtx)
|
||||
@@ -1414,30 +1482,31 @@ func (u *ui) layout(gtx layout.Context) layout.Dimensions {
|
||||
})
|
||||
}
|
||||
|
||||
func (u *ui) lifecycleScreen(gtx layout.Context) layout.Dimensions {
|
||||
panel := card
|
||||
if u.mode == "phone" {
|
||||
panel = compactCard
|
||||
}
|
||||
return panel(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
rows := []layout.Widget{
|
||||
u.lifecycleControls,
|
||||
}
|
||||
return material.List(u.theme, &u.lifecycleList).Layout(gtx, len(rows), func(gtx layout.Context, i int) layout.Dimensions {
|
||||
return rows[i](gtx)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (u *ui) header(gtx layout.Context) layout.Dimensions {
|
||||
if u.mode == "phone" {
|
||||
return compactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
|
||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(20), productName)
|
||||
lbl.Color = accentColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(u.headerActions),
|
||||
)
|
||||
}),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if !u.shouldShowLifecycleSetup() {
|
||||
return layout.Dimensions{}
|
||||
}
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||
layout.Rigid(u.lifecycleControls),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||
)
|
||||
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
|
||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(20), productName)
|
||||
lbl.Color = accentColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(u.headerActions),
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -1445,27 +1514,13 @@ func (u *ui) header(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Dimensions{}
|
||||
}
|
||||
return card(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
|
||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(24), productName)
|
||||
lbl.Color = accentColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(u.headerActions),
|
||||
)
|
||||
}),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if !u.shouldShowLifecycleSetup() {
|
||||
return layout.Dimensions{}
|
||||
}
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
||||
layout.Rigid(u.lifecycleControls),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
||||
)
|
||||
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
|
||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(24), productName)
|
||||
lbl.Color = accentColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(u.headerActions),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user