Prioritize phone vault actions
This commit is contained in:
+21
-1
@@ -746,6 +746,20 @@ func TestUILifecycleControlsWithSelectedRecentVaultDoesNotPanic(t *testing.T) {
|
|||||||
_ = u.lifecycleControls(gtx)
|
_ = u.lifecycleControls(gtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUIShouldPrioritizeLifecyclePrimaryActionsOnPhone(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
phone := newUIWithSession("phone", &session.Manager{})
|
||||||
|
if !phone.shouldPrioritizeLifecyclePrimaryActions() {
|
||||||
|
t.Fatal("phone.shouldPrioritizeLifecyclePrimaryActions() = false, want true")
|
||||||
|
}
|
||||||
|
|
||||||
|
desktop := newUIWithSession("desktop", &session.Manager{})
|
||||||
|
if desktop.shouldPrioritizeLifecyclePrimaryActions() {
|
||||||
|
t.Fatal("desktop.shouldPrioritizeLifecyclePrimaryActions() = true, want false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUIRecentVaultListWithSelectedRecentVaultDoesNotPanic(t *testing.T) {
|
func TestUIRecentVaultListWithSelectedRecentVaultDoesNotPanic(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@@ -6040,7 +6054,13 @@ func TestUIRemoteSyncSetupShortcutLabelUsesClearLanguage(t *testing.T) {
|
|||||||
func TestUILifecycleRemoteSyncActionLabelUsesSetupLanguageWithoutSavedBinding(t *testing.T) {
|
func TestUILifecycleRemoteSyncActionLabelUsesSetupLanguageWithoutSavedBinding(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
u := newUIWithSession("desktop", &session.Manager{})
|
dir := t.TempDir()
|
||||||
|
u := newUIWithSession("desktop", &session.Manager{}, statePaths{
|
||||||
|
DefaultSaveAsPath: filepath.Join(dir, "vault.kdbx"),
|
||||||
|
RecentVaultsPath: filepath.Join(dir, "recent-vaults.json"),
|
||||||
|
RecentRemotesPath: filepath.Join(dir, "recent-remotes.json"),
|
||||||
|
UIPreferencesPath: filepath.Join(dir, "ui-prefs.json"),
|
||||||
|
})
|
||||||
u.vaultPath.SetText("/vaults/bellagio.kdbx")
|
u.vaultPath.SetText("/vaults/bellagio.kdbx")
|
||||||
|
|
||||||
if !u.shouldShowLifecycleRemoteSyncAction() {
|
if !u.shouldShowLifecycleRemoteSyncAction() {
|
||||||
|
|||||||
+102
-92
@@ -22,6 +22,92 @@ func (u *ui) lifecycleControls(gtx layout.Context) layout.Dimensions {
|
|||||||
busy := u.lifecycleBusy()
|
busy := u.lifecycleBusy()
|
||||||
showLocalChooser := u.showLocalVaultChooser()
|
showLocalChooser := u.showLocalVaultChooser()
|
||||||
selectedLocalPath := strings.TrimSpace(u.vaultPath.Text())
|
selectedLocalPath := strings.TrimSpace(u.vaultPath.Text())
|
||||||
|
advancedSection := func(gtx layout.Context) layout.Dimensions {
|
||||||
|
if busy {
|
||||||
|
return layout.Dimensions{}
|
||||||
|
}
|
||||||
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
|
layout.Rigid(u.lifecycleAdvancedDisclosure),
|
||||||
|
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
if u.lifecycleAdvancedHidden {
|
||||||
|
return layout.Dimensions{}
|
||||||
|
}
|
||||||
|
if u.lifecycleMode == "remote" {
|
||||||
|
return layout.Dimensions{}
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
lbl := material.Label(u.theme, unit.Sp(13), "Vault settings")
|
||||||
|
lbl.Color = accentColor
|
||||||
|
return lbl.Layout(gtx)
|
||||||
|
}),
|
||||||
|
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
lbl := material.Label(u.theme, unit.Sp(12), u.lifecycleSecuritySettingsSummary())
|
||||||
|
lbl.Color = mutedColor
|
||||||
|
return lbl.Layout(gtx)
|
||||||
|
}),
|
||||||
|
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
return tonedButton(gtx, u.theme, &u.openSecuritySettings, "Open Vault Settings")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
primaryActionsSection := func(gtx layout.Context) layout.Dimensions {
|
||||||
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
label := "Open Vault"
|
||||||
|
if busy {
|
||||||
|
label = "Opening Vault..."
|
||||||
|
}
|
||||||
|
if busy {
|
||||||
|
return passiveTonedButton(gtx, u.theme, label)
|
||||||
|
}
|
||||||
|
return tonedButton(gtx, u.theme, &u.openVault, label)
|
||||||
|
}),
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
if busy || !u.shouldShowLifecycleRemoteSyncAction() {
|
||||||
|
return layout.Dimensions{}
|
||||||
|
}
|
||||||
|
return layout.Spacer{Height: unit.Dp(6)}.Layout(gtx)
|
||||||
|
}),
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
if busy || !u.shouldShowLifecycleRemoteSyncAction() {
|
||||||
|
return layout.Dimensions{}
|
||||||
|
}
|
||||||
|
return tonedButton(gtx, u.theme, &u.lifecycleRemoteSyncAction, u.lifecycleRemoteSyncActionLabel())
|
||||||
|
}),
|
||||||
|
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 passiveSectionTab(gtx, u.theme, "Create New Vault", false)
|
||||||
|
}
|
||||||
|
return sectionTabButton(gtx, u.theme, &u.createVault, "Create New Vault", false)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
selectedVaultSection := func(gtx layout.Context) layout.Dimensions {
|
||||||
|
if busy || selectedLocalPath == "" {
|
||||||
|
return layout.Dimensions{}
|
||||||
|
}
|
||||||
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
|
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
return u.selectedLocalVaultCard(gtx, selectedLocalPath)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
lbl := material.Label(u.theme, unit.Sp(12), "OPEN A VAULT")
|
lbl := material.Label(u.theme, unit.Sp(12), "OPEN A VAULT")
|
||||||
@@ -119,106 +205,30 @@ func (u *ui) lifecycleControls(gtx layout.Context) layout.Dimensions {
|
|||||||
}
|
}
|
||||||
return keyFileSelector(u.theme, &u.keyFilePath, &u.pickKeyFile)(gtx)
|
return keyFileSelector(u.theme, &u.keyFilePath, &u.pickKeyFile)(gtx)
|
||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
if busy {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
return layout.Spacer{Height: unit.Dp(8)}.Layout(gtx)
|
|
||||||
}),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
if busy {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
return u.lifecycleAdvancedDisclosure(gtx)
|
|
||||||
}),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
if busy {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
return layout.Spacer{Height: unit.Dp(6)}.Layout(gtx)
|
|
||||||
}),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
if busy || u.lifecycleAdvancedHidden {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
if u.lifecycleMode == "remote" {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
lbl := material.Label(u.theme, unit.Sp(13), "Vault settings")
|
|
||||||
lbl.Color = accentColor
|
|
||||||
return lbl.Layout(gtx)
|
|
||||||
}),
|
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
lbl := material.Label(u.theme, unit.Sp(12), u.lifecycleSecuritySettingsSummary())
|
|
||||||
lbl.Color = mutedColor
|
|
||||||
return lbl.Layout(gtx)
|
|
||||||
}),
|
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
return tonedButton(gtx, u.theme, &u.openSecuritySettings, "Open Vault Settings")
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
if u.shouldPrioritizeLifecyclePrimaryActions() {
|
||||||
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
|
layout.Rigid(primaryActionsSection),
|
||||||
|
layout.Rigid(selectedVaultSection),
|
||||||
|
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||||
|
layout.Rigid(advancedSection),
|
||||||
|
)
|
||||||
|
}
|
||||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(advancedSection),
|
||||||
label := "Open Vault"
|
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||||
if busy {
|
layout.Rigid(primaryActionsSection),
|
||||||
label = "Opening Vault..."
|
layout.Rigid(selectedVaultSection),
|
||||||
}
|
|
||||||
if busy {
|
|
||||||
return passiveTonedButton(gtx, u.theme, label)
|
|
||||||
}
|
|
||||||
return tonedButton(gtx, u.theme, &u.openVault, label)
|
|
||||||
}),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
if busy || !u.shouldShowLifecycleRemoteSyncAction() {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
return layout.Spacer{Height: unit.Dp(6)}.Layout(gtx)
|
|
||||||
}),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
if busy || !u.shouldShowLifecycleRemoteSyncAction() {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
return tonedButton(gtx, u.theme, &u.lifecycleRemoteSyncAction, u.lifecycleRemoteSyncActionLabel())
|
|
||||||
}),
|
|
||||||
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 passiveSectionTab(gtx, u.theme, "Create New Vault", false)
|
|
||||||
}
|
|
||||||
return sectionTabButton(gtx, u.theme, &u.createVault, "Create New Vault", false)
|
|
||||||
}),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
if busy || selectedLocalPath == "" {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
return layout.Spacer{Height: unit.Dp(8)}.Layout(gtx)
|
|
||||||
}),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
if busy || selectedLocalPath == "" {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
return u.selectedLocalVaultCard(gtx, selectedLocalPath)
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *ui) shouldPrioritizeLifecyclePrimaryActions() bool {
|
||||||
|
return u.mode == "phone"
|
||||||
|
}
|
||||||
|
|
||||||
func (u *ui) selectedRemoteConnectionCard(gtx layout.Context) layout.Dimensions {
|
func (u *ui) selectedRemoteConnectionCard(gtx layout.Context) layout.Dimensions {
|
||||||
heading := u.selectedRemoteCardHeading()
|
heading := u.selectedRemoteCardHeading()
|
||||||
primary := u.selectedRemoteCardPrimaryText()
|
primary := u.selectedRemoteCardPrimaryText()
|
||||||
|
|||||||
Reference in New Issue
Block a user