Refine entry detail and edit panels

This commit is contained in:
Joe Julian
2026-04-01 17:15:08 -07:00
parent d2fd4c55f5
commit c3521eea5b
4 changed files with 566 additions and 266 deletions
+150 -81
View File
@@ -299,6 +299,7 @@ type ui struct {
syncedPath []string
selectedHistoryIndex int
showPassword bool
generatedPasswordDraft bool
togglePassword widget.Clickable
copyAPITokenSecret widget.Clickable
issueAPIToken widget.Clickable
@@ -3719,11 +3720,11 @@ func (u *ui) detailPanelContent(gtx layout.Context) layout.Dimensions {
password := u.detailPasswordValue()
titleSize := unit.Sp(26)
titlePad := unit.Dp(10)
sectionGap := unit.Dp(8)
sectionGap := unit.Dp(6)
if u.mode == "phone" {
titleSize = unit.Sp(18)
titlePad = unit.Dp(6)
sectionGap = unit.Dp(6)
titlePad = unit.Dp(4)
sectionGap = unit.Dp(4)
}
rows := []layout.Widget{
func(gtx layout.Context) layout.Dimensions {
@@ -3765,72 +3766,87 @@ func (u *ui) detailPanelContent(gtx layout.Context) layout.Dimensions {
}
return 0
}()}.Layout,
detailLine(u.theme, "Path", strings.Join(u.displayEntryPath(item.Path), " / ")),
layout.Spacer{Height: sectionGap}.Layout,
detailLine(u.theme, "Username", item.Username),
layout.Spacer{Height: sectionGap}.Layout,
u.passwordLine("Password", password),
layout.Spacer{Height: sectionGap}.Layout,
detailLine(u.theme, "URL", item.URL),
layout.Spacer{Height: sectionGap}.Layout,
detailLine(u.theme, "Tags", strings.Join(item.Tags, ", ")),
layout.Spacer{Height: unit.Dp(10)}.Layout,
func(gtx layout.Context) layout.Dimensions {
lbl := material.Label(u.theme, unit.Sp(12), "Quick actions")
lbl.Color = mutedColor
return lbl.Layout(gtx)
return compactCard(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(detailLine(u.theme, "Path", strings.Join(u.displayEntryPath(item.Path), " / "))),
layout.Rigid(layout.Spacer{Height: sectionGap}.Layout),
layout.Rigid(detailLine(u.theme, "Username", item.Username)),
layout.Rigid(layout.Spacer{Height: sectionGap}.Layout),
layout.Rigid(detailLine(u.theme, "URL", item.URL)),
layout.Rigid(layout.Spacer{Height: sectionGap}.Layout),
layout.Rigid(detailLine(u.theme, "Tags", strings.Join(item.Tags, ", "))),
)
})
},
layout.Spacer{Height: unit.Dp(6)}.Layout,
layout.Spacer{Height: sectionGap}.Layout,
func(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 tonedButton(gtx, u.theme, &u.copyUser, "Copy User")
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(layout.Spacer{Height: unit.Dp(8)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return tonedButton(gtx, u.theme, &u.copyPass, "Copy Password")
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return tonedButton(gtx, u.theme, &u.copyURL, "Copy URL")
if u.mode == "phone" {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
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,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return tonedButton(gtx, u.theme, &u.copyPass, "Copy Password")
}),
layout.Rigid(layout.Spacer{Width: 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{Width: unit.Dp(6)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return tonedButton(gtx, u.theme, &u.copyURL, "Copy URL")
}),
)
}),
)
}
return layout.Flex{}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
btn := material.Button(u.theme, &u.copyUser, "Copy User")
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.copyPass, "Copy Password")
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.copyURL, "Copy URL")
return btn.Layout(gtx)
}),
)
})
},
layout.Spacer{Height: unit.Dp(12)}.Layout,
layout.Spacer{Height: unit.Dp(8)}.Layout,
func(gtx layout.Context) layout.Dimensions {
lbl := material.Label(u.theme, unit.Sp(12), "Notes")
lbl.Color = mutedColor
return lbl.Layout(gtx)
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(12), "NOTES")
lbl.Color = mutedColor
return lbl.Layout(gtx)
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
lbl := material.Body1(u.theme, item.Notes)
lbl.Color = mutedColor
return lbl.Layout(gtx)
}),
)
})
},
layout.Spacer{Height: unit.Dp(4)}.Layout,
func(gtx layout.Context) layout.Dimensions {
lbl := material.Body1(u.theme, item.Notes)
lbl.Color = mutedColor
return lbl.Layout(gtx)
},
layout.Spacer{Height: unit.Dp(12)}.Layout,
layout.Spacer{Height: unit.Dp(8)}.Layout,
u.attachmentSummaryPanel,
layout.Spacer{Height: unit.Dp(12)}.Layout,
layout.Spacer{Height: unit.Dp(8)}.Layout,
u.historyPanel,
layout.Spacer{Height: unit.Dp(12)}.Layout,
layout.Spacer{Height: unit.Dp(8)}.Layout,
func(gtx layout.Context) layout.Dimensions {
switch u.state.Section {
case appstate.SectionTemplates:
@@ -4105,36 +4121,89 @@ func (u *ui) historyPanel(gtx layout.Context) layout.Dimensions {
func (u *ui) attachmentSummaryPanel(gtx layout.Context) layout.Dimensions {
items := u.selectedAttachmentItems()
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
lbl := material.Label(u.theme, unit.Sp(12), "Attachments")
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 len(items) == 0 {
lbl := material.Label(u.theme, unit.Sp(12), "No attachments on this entry.")
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(12), "ATTACHMENTS")
lbl.Color = mutedColor
return lbl.Layout(gtx)
}
return layout.Flex{Axis: layout.Vertical}.Layout(gtx, func() []layout.FlexChild {
children := make([]layout.FlexChild, 0, len(items)*2)
for i, item := range items {
label := fmt.Sprintf("%s (%d B)", item.Name, item.Size)
children = append(children, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
lbl := material.Label(u.theme, unit.Sp(12), label)
lbl.Color = accentColor
return lbl.Layout(gtx)
}))
if i < len(items)-1 {
children = append(children, layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout))
}
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(4)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
lbl := material.Label(u.theme, unit.Sp(11), u.attachmentActionSummary())
lbl.Color = mutedColor
return lbl.Layout(gtx)
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
if len(items) == 0 {
return layout.Dimensions{}
}
return children
}()...)
}),
)
return layout.Inset{Top: unit.Dp(8)}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx, func() []layout.FlexChild {
children := make([]layout.FlexChild, 0, len(items)*2)
selectedName := strings.TrimSpace(u.attachmentName.Text())
for i, item := range items {
index := i
name := item.Name
selected := selectedName == name
children = append(children, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
for u.attachmentClicks[index].Clicked(gtx) {
u.attachmentName.SetText(name)
}
return u.attachmentClicks[index].Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Stack{}.Layout(gtx,
layout.Expanded(func(gtx layout.Context) layout.Dimensions {
size := gtx.Constraints.Min
if size.X == 0 {
size.X = gtx.Constraints.Max.X
}
if size.Y == 0 {
size.Y = gtx.Dp(unit.Dp(58))
}
bg := panelColor
if selected {
bg = selectedColor
}
paint.FillShape(gtx.Ops, bg, clip.Rect{Max: size}.Op())
if selected {
paint.FillShape(gtx.Ops, selectedEdge, clip.Rect{Max: image.Pt(4, size.Y)}.Op())
}
return layout.Dimensions{Size: size}
}),
layout.Stacked(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), name)
lbl.Color = accentColor
return lbl.Layout(gtx)
}),
layout.Rigid(layout.Spacer{Height: unit.Dp(2)}.Layout),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
text := fmt.Sprintf("%d B", item.Size)
if selected {
text += " · selected"
}
lbl := material.Label(u.theme, unit.Sp(11), text)
lbl.Color = mutedColor
return lbl.Layout(gtx)
}),
)
})
}),
)
})
}))
if i < len(items)-1 {
children = append(children, layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout))
}
}
return children
}()...)
})
}),
)
})
}
func (u *ui) historyRow(gtx layout.Context, click *widget.Clickable, index int, item entry) layout.Dimensions {