Use structured custom fields in entry editor
This commit is contained in:
+96
-2
@@ -126,6 +126,66 @@ func (u *ui) attachmentList(gtx layout.Context) layout.Dimensions {
|
||||
}()...)
|
||||
}
|
||||
|
||||
func (u *ui) customFieldEditorPanel(gtx layout.Context) layout.Dimensions {
|
||||
if len(u.customFieldKeys) == 0 {
|
||||
u.setCustomFieldRows(nil)
|
||||
}
|
||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
lbl := material.Label(u.theme, unit.Sp(12), "CUSTOM FIELDS")
|
||||
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), "Add key/value pairs. Changes are only saved when you save the entry.")
|
||||
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 layout.Flex{Axis: layout.Vertical}.Layout(gtx, func() []layout.FlexChild {
|
||||
children := make([]layout.FlexChild, 0, len(u.customFieldKeys)*2)
|
||||
for i := range u.customFieldKeys {
|
||||
index := i
|
||||
children = append(children, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
for u.removeCustomFields[index].Clicked(gtx) {
|
||||
u.removeCustomFieldRow(index)
|
||||
}
|
||||
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
|
||||
layout.Flexed(0.38, func(gtx layout.Context) layout.Dimensions {
|
||||
return labeledEditor(u.theme, "Name", &u.customFieldKeys[index], false)(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Width: unit.Dp(6)}.Layout),
|
||||
layout.Flexed(0.52, func(gtx layout.Context) layout.Dimensions {
|
||||
return labeledEditor(u.theme, "Value", &u.customFieldValues[index], false)(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Width: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
if len(u.customFieldKeys) == 1 && (strings.TrimSpace(u.customFieldKeys[index].Text()) != "" || strings.TrimSpace(u.customFieldValues[index].Text()) != "") {
|
||||
return layout.Dimensions{}
|
||||
}
|
||||
return tonedButton(gtx, u.theme, &u.removeCustomFields[index], "-")
|
||||
}),
|
||||
)
|
||||
}))
|
||||
if i < len(u.customFieldKeys)-1 {
|
||||
children = append(children, layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout))
|
||||
}
|
||||
}
|
||||
return children
|
||||
}()...)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
for u.addCustomField.Clicked(gtx) {
|
||||
u.appendCustomFieldRow("", "")
|
||||
}
|
||||
return tonedButton(gtx, u.theme, &u.addCustomField, "+")
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
func (u *ui) groupControls(gtx layout.Context) layout.Dimensions {
|
||||
if u.state.Section != appstate.SectionEntries {
|
||||
return layout.Dimensions{}
|
||||
@@ -218,9 +278,9 @@ func (u *ui) entryEditorPanel(gtx layout.Context) layout.Dimensions {
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(labeledEditorWithFocus(u.theme, "Notes", &u.entryNotes, false, u.isFocused(detailFocusID(detailFieldNotes)))),
|
||||
layout.Rigid(labeledMultilineEditorWithFocus(u.theme, "Notes", &u.entryNotes, false, u.isFocused(detailFocusID(detailFieldNotes)), unit.Dp(120))),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
layout.Rigid(labeledEditorHelpFocus(u.theme, "Custom Fields", "One key=value pair per line. These fields are only saved when you save the entry.", &u.entryFields, false, u.isFocused(detailFocusID(detailFieldFields)))),
|
||||
layout.Rigid(u.customFieldEditorPanel),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
||||
layout.Rigid(labeledEditorWithFocus(u.theme, "History Index", &u.historyIndex, false, u.isFocused(detailFocusID(detailFieldHistoryIndex)))),
|
||||
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||
@@ -385,3 +445,37 @@ func labeledEditorWithFocus(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func labeledMultilineEditorWithFocus(
|
||||
th *material.Theme,
|
||||
label string,
|
||||
editor *widget.Editor,
|
||||
sensitive bool,
|
||||
focused bool,
|
||||
minHeight unit.Dp,
|
||||
) layout.Widget {
|
||||
return 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(th, unit.Sp(12), strings.ToUpper(label))
|
||||
lbl.Color = mutedColor
|
||||
return lbl.Layout(gtx)
|
||||
}),
|
||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||
return outlinedFieldState(gtx, focused, func(gtx layout.Context) layout.Dimensions {
|
||||
mask := editor.Mask
|
||||
if sensitive {
|
||||
editor.Mask = '•'
|
||||
}
|
||||
defer func() { editor.Mask = mask }()
|
||||
gtx.Constraints.Min.X = gtx.Constraints.Max.X
|
||||
if min := gtx.Dp(minHeight); gtx.Constraints.Min.Y < min {
|
||||
gtx.Constraints.Min.Y = min
|
||||
}
|
||||
ed := material.Editor(th, editor, label)
|
||||
return layout.UniformInset(unit.Dp(8)).Layout(gtx, ed.Layout)
|
||||
})
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user