Improve local vault open usability
This commit is contained in:
+120
-66
@@ -21,10 +21,20 @@ func (u *ui) lifecycleControls(gtx layout.Context) layout.Dimensions {
|
||||
busy := u.lifecycleBusy()
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "OPEN OR CREATE VAULT")
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "OPEN A VAULT")
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
message := "Choose a recent vault or pick a `.kdbx` file, then unlock it."
|
||||
if u.lifecycleMode == "remote" {
|
||||
message = "Connect to a remote vault, then unlock it with the KeePass master key."
|
||||
}
|
||||
lbl := material.Label(u.theme, unit.Sp(14), message)
|
||||
lbl.Color = accentColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
|
||||
@@ -44,17 +54,6 @@ func (u *ui) lifecycleControls(gtx layout.Context) layout.Dimensions {
|
||||
)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.masterPasswordField(gtx, "Leave blank if this vault is protected by key file only.")
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if busy {
|
||||
return labeledEditorHelp(u.theme, "Key File", "Optional path to a KeePass-compatible key file.", &u.keyFilePath, false)(gtx)
|
||||
}
|
||||
return selectorEditorHelp(u.theme, "Key File", "Optional path to a KeePass-compatible key file.", &u.keyFilePath, &u.pickKeyFile, "Choose File", false)(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if u.lifecycleMode == "remote" {
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
@@ -162,62 +161,92 @@ func (u *ui) lifecycleControls(gtx layout.Context) layout.Dimensions {
|
||||
}
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "VAULT FILE")
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "RECENT VAULTS")
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if busy {
|
||||
return labeledEditorHelp(u.theme, "Vault Path", "Choose the existing .kdbx file to open.", &u.vaultPath, false)(gtx)
|
||||
}
|
||||
return selectorEditorHelp(u.theme, "Vault Path", "Choose the existing .kdbx file to open.", &u.vaultPath, &u.pickVaultPath, "Choose File", false)(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if strings.TrimSpace(u.vaultPath.Text()) == "" {
|
||||
return layout.Dimensions{}
|
||||
}
|
||||
return compactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.UniformInset(unit.Dp(10)).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "SELECTED VAULT")
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(2)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(14), friendlyRecentVaultLabel(u.vaultPath.Text()))
|
||||
lbl.Color = accentColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if busy {
|
||||
return layout.Dimensions{}
|
||||
}
|
||||
return tonedButton(gtx, u.theme, &u.clearVaultSelection, "Change...")
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(2)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(11), u.vaultPath.Text())
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if busy {
|
||||
return layout.Dimensions{}
|
||||
}
|
||||
return u.recentVaultList(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "VAULT FILE")
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
selectedPath := strings.TrimSpace(u.vaultPath.Text())
|
||||
switch {
|
||||
case busy:
|
||||
return labeledEditorHelp(u.theme, "Vault Path", "Choose the existing .kdbx file to open.", &u.vaultPath, false)(gtx)
|
||||
case selectedPath == "":
|
||||
return selectorEditorHelp(u.theme, "Vault Path", "Choose the existing .kdbx file to open.", &u.vaultPath, &u.pickVaultPath, "Choose File", false)(gtx)
|
||||
default:
|
||||
lastGroup := u.recentVaultGroup(selectedPath)
|
||||
return compactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.UniformInset(unit.Dp(10)).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "SELECTED VAULT")
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(2)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(16), friendlyRecentVaultLabel(selectedPath))
|
||||
lbl.Color = accentColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
dir := compactPathDirectorySummary(selectedPath)
|
||||
if dir == "" {
|
||||
return layout.Dimensions{}
|
||||
}
|
||||
lbl := material.Label(u.theme, unit.Sp(11), dir)
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if len(lastGroup) == 0 {
|
||||
return layout.Dimensions{}
|
||||
}
|
||||
lbl := material.Label(u.theme, unit.Sp(11), "Last group: "+strings.Join(u.displayEntryPath(lastGroup), " / "))
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return tonedButton(gtx, u.theme, &u.clearVaultSelection, "Change...")
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
}),
|
||||
)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "UNLOCK")
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return u.masterPasswordField(gtx, "Leave blank if this vault is protected by key file only.")
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if busy {
|
||||
return labeledEditorHelp(u.theme, "Key File", "Optional path to a KeePass-compatible key file.", &u.keyFilePath, false)(gtx)
|
||||
}
|
||||
return selectorEditorHelp(u.theme, "Key File", "Optional path to a KeePass-compatible key file.", &u.keyFilePath, &u.pickKeyFile, "Choose File", false)(gtx)
|
||||
}),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if busy {
|
||||
return layout.Dimensions{}
|
||||
@@ -255,7 +284,7 @@ func (u *ui) lifecycleControls(gtx layout.Context) layout.Dimensions {
|
||||
}
|
||||
return tonedButton(gtx, u.theme, &u.openRemote, label)
|
||||
}
|
||||
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
label := "Open Vault"
|
||||
if busy {
|
||||
@@ -266,12 +295,18 @@ func (u *ui) lifecycleControls(gtx layout.Context) layout.Dimensions {
|
||||
}
|
||||
return tonedButton(gtx, u.theme, &u.openVault, label)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Width: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(11), "Need a fresh database instead?")
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if busy {
|
||||
return passiveTonedButton(gtx, u.theme, "New Vault")
|
||||
return passiveSectionTab(gtx, u.theme, "Create New Vault", false)
|
||||
}
|
||||
return tonedButton(gtx, u.theme, &u.createVault, "New Vault")
|
||||
return sectionTabButton(gtx, u.theme, &u.createVault, "Create New Vault", false)
|
||||
}),
|
||||
)
|
||||
}),
|
||||
@@ -317,7 +352,7 @@ func (u *ui) recentVaultList(gtx layout.Context) layout.Dimensions {
|
||||
}
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "RECENTLY OPENED")
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "TAP TO SELECT")
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
@@ -344,13 +379,30 @@ func (u *ui) recentVaultList(gtx layout.Context) layout.Dimensions {
|
||||
return layout.UniformInset(unit.Dp(10)).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(14), label)
|
||||
lbl.Color = accentColor
|
||||
return lbl.Layout(gtx)
|
||||
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
|
||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(15), label)
|
||||
lbl.Color = accentColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
badge := "Tap to use"
|
||||
if selected {
|
||||
badge = "Selected"
|
||||
}
|
||||
lbl := material.Label(u.theme, unit.Sp(11), badge)
|
||||
if selected {
|
||||
lbl.Color = accentColor
|
||||
} else {
|
||||
lbl.Color = mutedColor
|
||||
}
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(2)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(11), path)
|
||||
lbl := material.Label(u.theme, unit.Sp(11), compactPathDirectorySummary(path))
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
@@ -1213,7 +1265,9 @@ func (u *ui) masterPasswordField(gtx layout.Context, help string) layout.Dimensi
|
||||
defer func() { u.masterPassword.Mask = restore }()
|
||||
gtx.Constraints.Min.X = gtx.Constraints.Max.X
|
||||
ed := material.Editor(u.theme, &u.masterPassword, "Master Password")
|
||||
return ed.Layout(gtx)
|
||||
dims := ed.Layout(gtx)
|
||||
u.requestMasterPasswordFocusIfNeeded(gtx)
|
||||
return dims
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Width: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
|
||||
Reference in New Issue
Block a user