Tighten phone group and detail layout
This commit is contained in:
@@ -316,7 +316,6 @@ type ui struct {
|
|||||||
cancelDeleteGroup widget.Clickable
|
cancelDeleteGroup widget.Clickable
|
||||||
addCustomField widget.Clickable
|
addCustomField widget.Clickable
|
||||||
toggleGroupControls widget.Clickable
|
toggleGroupControls widget.Clickable
|
||||||
togglePhoneGroupBrowser widget.Clickable
|
|
||||||
toggleLifecycleAdvanced widget.Clickable
|
toggleLifecycleAdvanced widget.Clickable
|
||||||
toggleHistory widget.Clickable
|
toggleHistory widget.Clickable
|
||||||
togglePasswordInline widget.Clickable
|
togglePasswordInline widget.Clickable
|
||||||
@@ -626,6 +625,11 @@ func newUIWithState(mode string, sess appstate.CurrentSession, paths statePaths)
|
|||||||
u.restoreStartupLifecycleTarget()
|
u.restoreStartupLifecycleTarget()
|
||||||
u.requestMasterPassFocus = u.hasSelectedLifecycleTarget()
|
u.requestMasterPassFocus = u.hasSelectedLifecycleTarget()
|
||||||
u.loadUIPreferences()
|
u.loadUIPreferences()
|
||||||
|
if u.mode == "phone" {
|
||||||
|
if _, err := os.Stat(u.uiPreferencesPath); err != nil {
|
||||||
|
u.groupControlsHidden = true
|
||||||
|
}
|
||||||
|
}
|
||||||
u.loadSettings()
|
u.loadSettings()
|
||||||
u.loadSettingsFormFromPreferences()
|
u.loadSettingsFormFromPreferences()
|
||||||
u.loadSettingsDraft()
|
u.loadSettingsDraft()
|
||||||
@@ -3946,6 +3950,11 @@ func (u *ui) headerActions(gtx layout.Context) layout.Dimensions {
|
|||||||
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
|
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
|
||||||
layout.Rigid(u.syncButtonGroup),
|
layout.Rigid(u.syncButtonGroup),
|
||||||
layout.Rigid(layout.Spacer{Width: unit.Dp(8)}.Layout),
|
layout.Rigid(layout.Spacer{Width: unit.Dp(8)}.Layout),
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
btn := material.Button(u.theme, &u.lockVault, "Lock")
|
||||||
|
return btn.Layout(gtx)
|
||||||
|
}),
|
||||||
|
layout.Rigid(layout.Spacer{Width: unit.Dp(8)}.Layout),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
icon := u.menuIcon
|
icon := u.menuIcon
|
||||||
if icon == nil {
|
if icon == nil {
|
||||||
@@ -3958,11 +3967,6 @@ func (u *ui) headerActions(gtx layout.Context) layout.Dimensions {
|
|||||||
btn.Inset = layout.UniformInset(unit.Dp(8))
|
btn.Inset = layout.UniformInset(unit.Dp(8))
|
||||||
return btn.Layout(gtx)
|
return btn.Layout(gtx)
|
||||||
}),
|
}),
|
||||||
layout.Rigid(layout.Spacer{Width: unit.Dp(8)}.Layout),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
btn := material.Button(u.theme, &u.lockVault, "Lock")
|
|
||||||
return btn.Layout(gtx)
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4483,17 +4487,17 @@ func (u *ui) phoneSlider(gtx layout.Context) layout.Dimensions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(18))
|
gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(24))
|
||||||
gtx.Constraints.Max.Y = gtx.Dp(unit.Dp(18))
|
gtx.Constraints.Max.Y = gtx.Dp(unit.Dp(24))
|
||||||
return layout.UniformInset(unit.Dp(2)).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
return layout.UniformInset(unit.Dp(2)).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||||
defer clip.Rect{Max: gtx.Constraints.Min}.Push(gtx.Ops).Pop()
|
defer clip.Rect{Max: gtx.Constraints.Min}.Push(gtx.Ops).Pop()
|
||||||
u.splitDrag.Add(gtx.Ops)
|
u.splitDrag.Add(gtx.Ops)
|
||||||
pointer.CursorRowResize.Add(gtx.Ops)
|
pointer.CursorRowResize.Add(gtx.Ops)
|
||||||
handleW := gtx.Dp(unit.Dp(84))
|
handleW := gtx.Dp(unit.Dp(108))
|
||||||
handleH := gtx.Dp(unit.Dp(4))
|
handleH := gtx.Dp(unit.Dp(6))
|
||||||
x := (gtx.Constraints.Min.X - handleW) / 2
|
x := (gtx.Constraints.Min.X - handleW) / 2
|
||||||
y := (gtx.Constraints.Min.Y - handleH) / 2
|
y := (gtx.Constraints.Min.Y - handleH) / 2
|
||||||
paint.FillShape(gtx.Ops, color.NRGBA{R: 214, G: 208, B: 197, A: 255}, clip.Rect{Min: image.Pt(0, y+1), Max: image.Pt(gtx.Constraints.Min.X, y+2)}.Op())
|
paint.FillShape(gtx.Ops, color.NRGBA{R: 214, G: 208, B: 197, A: 255}, clip.Rect{Min: image.Pt(0, y+2), Max: image.Pt(gtx.Constraints.Min.X, y+3)}.Op())
|
||||||
paint.FillShape(gtx.Ops, accentColor, clip.RRect{
|
paint.FillShape(gtx.Ops, accentColor, clip.RRect{
|
||||||
Rect: image.Rectangle{Min: image.Pt(x, y), Max: image.Pt(x+handleW, y+handleH)},
|
Rect: image.Rectangle{Min: image.Pt(x, y), Max: image.Pt(x+handleW, y+handleH)},
|
||||||
NE: 2, NW: 2, SE: 2, SW: 2,
|
NE: 2, NW: 2, SE: 2, SW: 2,
|
||||||
@@ -4697,8 +4701,18 @@ func (u *ui) detailPanelContent(gtx layout.Context) layout.Dimensions {
|
|||||||
layout.Spacer{Height: titlePad}.Layout,
|
layout.Spacer{Height: titlePad}.Layout,
|
||||||
func(gtx layout.Context) layout.Dimensions {
|
func(gtx layout.Context) layout.Dimensions {
|
||||||
if u.state.Section != appstate.SectionRecycleBin {
|
if u.state.Section != appstate.SectionRecycleBin {
|
||||||
lbl := material.Label(u.theme, unit.Sp(16), item.Title)
|
if u.mode == "phone" {
|
||||||
return lbl.Layout(gtx)
|
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
|
||||||
|
layout.Flexed(0.5, func(gtx layout.Context) layout.Dimensions {
|
||||||
|
return compactTonedButton(gtx, u.theme, &u.copyUser, "Copy Username")
|
||||||
|
}),
|
||||||
|
layout.Rigid(layout.Spacer{Width: unit.Dp(6)}.Layout),
|
||||||
|
layout.Flexed(0.5, func(gtx layout.Context) layout.Dimensions {
|
||||||
|
return compactTonedButton(gtx, u.theme, &u.copyPass, "Copy Password")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return layout.Dimensions{}
|
||||||
}
|
}
|
||||||
return recycleDetailTitle(gtx, u.theme, item.Title)
|
return recycleDetailTitle(gtx, u.theme, item.Title)
|
||||||
},
|
},
|
||||||
@@ -4741,29 +4755,11 @@ func (u *ui) detailPanelContent(gtx layout.Context) layout.Dimensions {
|
|||||||
func(gtx layout.Context) layout.Dimensions {
|
func(gtx layout.Context) layout.Dimensions {
|
||||||
return compactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
return compactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
lbl := material.Label(u.theme, unit.Sp(12), "PASSWORD")
|
|
||||||
lbl.Color = mutedColor
|
|
||||||
return lbl.Layout(gtx)
|
|
||||||
}),
|
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
|
|
||||||
layout.Rigid(u.passwordLine("Password", password)),
|
layout.Rigid(u.passwordLine("Password", password)),
|
||||||
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.mode == "phone" {
|
if u.mode == "phone" {
|
||||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
return compactTonedButton(gtx, u.theme, &u.copyURL, "Copy URL")
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
return tonedButton(gtx, u.theme, &u.copyPass, "Copy Password")
|
|
||||||
}),
|
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
return tonedButton(gtx, u.theme, &u.copyUser, "Copy Username")
|
|
||||||
}),
|
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
return tonedButton(gtx, u.theme, &u.copyURL, "Copy URL")
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
|
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
@@ -5344,72 +5340,20 @@ func (u *ui) groupBar(gtx layout.Context) layout.Dimensions {
|
|||||||
displayPath := u.displayPath()
|
displayPath := u.displayPath()
|
||||||
atRoot := len(displayPath) == 0
|
atRoot := len(displayPath) == 0
|
||||||
return compactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
return compactCard(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||||
if u.mode == "phone" {
|
if u.mode == "phone" {
|
||||||
if atRoot {
|
if atRoot {
|
||||||
u.phoneGroupBrowserExpanded = true
|
u.phoneGroupBrowserExpanded = true
|
||||||
}
|
}
|
||||||
toggleLabel := "Browse"
|
|
||||||
if u.phoneGroupBrowserExpanded {
|
|
||||||
toggleLabel = "Hide"
|
|
||||||
}
|
|
||||||
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 {
|
||||||
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
|
lbl := material.Label(u.theme, unit.Sp(12), "GROUPS")
|
||||||
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
|
lbl.Color = mutedColor
|
||||||
lbl := material.Label(u.theme, unit.Sp(12), "GROUPS")
|
return lbl.Layout(gtx)
|
||||||
lbl.Color = mutedColor
|
|
||||||
return lbl.Layout(gtx)
|
|
||||||
}),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
if len(groups) == 0 && atRoot {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
return tonedButton(gtx, u.theme, &u.togglePhoneGroupBrowser, toggleLabel)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
if atRoot {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
return layout.Inset{Top: unit.Dp(8)}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
|
||||||
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
for u.goToRootGroup.Clicked(gtx) {
|
|
||||||
root := u.hiddenVaultRoot()
|
|
||||||
if root == "" {
|
|
||||||
u.setCurrentPath(nil)
|
|
||||||
} else {
|
|
||||||
u.setCurrentPath([]string{root})
|
|
||||||
}
|
|
||||||
u.filter()
|
|
||||||
}
|
|
||||||
return tonedButton(gtx, u.theme, &u.goToRootGroup, "Root")
|
|
||||||
}),
|
|
||||||
layout.Rigid(layout.Spacer{Width: unit.Dp(6)}.Layout),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
for u.goToParentGroup.Clicked(gtx) {
|
|
||||||
u.setCurrentPath(u.currentPath[:len(u.currentPath)-1])
|
|
||||||
u.filter()
|
|
||||||
}
|
|
||||||
return tonedButton(gtx, u.theme, &u.goToParentGroup, "Up")
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
for u.togglePhoneGroupBrowser.Clicked(gtx) {
|
|
||||||
u.phoneGroupBrowserExpanded = !u.phoneGroupBrowserExpanded
|
|
||||||
}
|
|
||||||
if !u.phoneGroupBrowserExpanded {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
return layout.Spacer{Height: unit.Dp(8)}.Layout(gtx)
|
return layout.Spacer{Height: unit.Dp(8)}.Layout(gtx)
|
||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
if !u.phoneGroupBrowserExpanded {
|
|
||||||
return layout.Dimensions{}
|
|
||||||
}
|
|
||||||
if len(groups) == 0 {
|
if len(groups) == 0 {
|
||||||
lbl := material.Label(u.theme, unit.Sp(12), "No subgroups here.")
|
lbl := material.Label(u.theme, unit.Sp(12), "No subgroups here.")
|
||||||
lbl.Color = mutedColor
|
lbl.Color = mutedColor
|
||||||
@@ -5429,7 +5373,6 @@ func (u *ui) groupBar(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.syncPhoneGroupBrowser(u.currentPath)
|
|
||||||
u.filter()
|
u.filter()
|
||||||
}
|
}
|
||||||
return tonedButton(gtx, u.theme, &u.groupClicks[idx], name)
|
return tonedButton(gtx, u.theme, &u.groupClicks[idx], name)
|
||||||
@@ -5673,6 +5616,15 @@ func tonedButton(gtx layout.Context, th *material.Theme, click *widget.Clickable
|
|||||||
return btn.Layout(gtx)
|
return btn.Layout(gtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func compactTonedButton(gtx layout.Context, th *material.Theme, click *widget.Clickable, label string) layout.Dimensions {
|
||||||
|
btn := material.Button(th, click, label)
|
||||||
|
btn.Background, btn.Color = buttonFocusColors(defaultAccessibilityPreferences(), false)
|
||||||
|
btn.CornerRadius = unit.Dp(10)
|
||||||
|
btn.TextSize = unit.Sp(13)
|
||||||
|
btn.Inset = layout.Inset{Top: 6, Bottom: 6, Left: 8, Right: 8}
|
||||||
|
return btn.Layout(gtx)
|
||||||
|
}
|
||||||
|
|
||||||
func syncPrimaryButton(gtx layout.Context, th *material.Theme, click *widget.Clickable, label string, compact bool) layout.Dimensions {
|
func syncPrimaryButton(gtx layout.Context, th *material.Theme, click *widget.Clickable, label string, compact bool) layout.Dimensions {
|
||||||
btn := material.Button(th, click, label)
|
btn := material.Button(th, click, label)
|
||||||
btn.Background = color.NRGBA{R: 231, G: 236, B: 232, A: 255}
|
btn.Background = color.NRGBA{R: 231, G: 236, B: 232, A: 255}
|
||||||
|
|||||||
@@ -775,6 +775,15 @@ func TestUIPhoneGroupBrowserToggleDoesNotChangeCurrentGroupToolsState(t *testing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUIPhoneStartsWithGroupToolsCollapsed(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
u := newUIWithModel("phone", vault.Model{})
|
||||||
|
if !u.groupControlsHidden {
|
||||||
|
t.Fatal("groupControlsHidden = false, want phone Group Tools collapsed by default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUIPhoneListPanelWithExpandedGroupControlsAndEntriesDoesNotPanic(t *testing.T) {
|
func TestUIPhoneListPanelWithExpandedGroupControlsAndEntriesDoesNotPanic(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -923,10 +923,9 @@ func (u *ui) groupControlsDisclosure(gtx layout.Context) layout.Dimensions {
|
|||||||
}),
|
}),
|
||||||
layout.Rigid(layout.Spacer{Width: unit.Dp(4)}.Layout),
|
layout.Rigid(layout.Spacer{Width: unit.Dp(4)}.Layout),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
label := "Group management"
|
label := "Group Tools"
|
||||||
size := unit.Sp(12)
|
size := unit.Sp(12)
|
||||||
if u.mode == "phone" {
|
if u.mode == "phone" {
|
||||||
label = "Tools"
|
|
||||||
size = unit.Sp(11)
|
size = unit.Sp(11)
|
||||||
}
|
}
|
||||||
lbl := material.Label(u.theme, size, label)
|
lbl := material.Label(u.theme, size, label)
|
||||||
|
|||||||
Reference in New Issue
Block a user