Use structured custom fields in entry editor
This commit is contained in:
+67
-1
@@ -3,9 +3,11 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gioui.org/widget"
|
||||
"git.julianfamily.org/keepassgo/clipboard"
|
||||
"git.julianfamily.org/keepassgo/passwords"
|
||||
"git.julianfamily.org/keepassgo/vault"
|
||||
@@ -52,6 +54,7 @@ func (u *ui) loadSelectedEntryIntoEditor() {
|
||||
u.entryTags.SetText("")
|
||||
u.entryPath.SetText(strings.Join(u.displayPath(), " / "))
|
||||
u.entryFields.SetText("")
|
||||
u.setCustomFieldRows(nil)
|
||||
u.attachmentName.SetText("")
|
||||
u.attachmentPath.SetText("")
|
||||
u.exportAttachmentPath.SetText("")
|
||||
@@ -67,11 +70,74 @@ func (u *ui) loadSelectedEntryIntoEditor() {
|
||||
u.entryTags.SetText(strings.Join(item.Tags, ", "))
|
||||
u.entryPath.SetText(strings.Join(u.displayEntryPath(item.Path), " / "))
|
||||
u.entryFields.SetText(marshalFields(item.Fields))
|
||||
u.setCustomFieldRows(item.Fields)
|
||||
u.attachmentName.SetText("")
|
||||
u.attachmentPath.SetText("")
|
||||
u.exportAttachmentPath.SetText("")
|
||||
}
|
||||
|
||||
func (u *ui) setCustomFieldRows(fields map[string]string) {
|
||||
u.customFieldKeys = nil
|
||||
u.customFieldValues = nil
|
||||
u.removeCustomFields = nil
|
||||
if len(fields) == 0 {
|
||||
u.appendCustomFieldRow("", "")
|
||||
return
|
||||
}
|
||||
keys := make([]string, 0, len(fields))
|
||||
for key := range fields {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
slices.Sort(keys)
|
||||
for _, key := range keys {
|
||||
u.appendCustomFieldRow(key, fields[key])
|
||||
}
|
||||
}
|
||||
|
||||
func (u *ui) appendCustomFieldRow(key, value string) {
|
||||
keyEditor := widget.Editor{SingleLine: true, Submit: false}
|
||||
keyEditor.SetText(key)
|
||||
valueEditor := widget.Editor{SingleLine: true, Submit: false}
|
||||
valueEditor.SetText(value)
|
||||
u.customFieldKeys = append(u.customFieldKeys, keyEditor)
|
||||
u.customFieldValues = append(u.customFieldValues, valueEditor)
|
||||
u.removeCustomFields = append(u.removeCustomFields, widget.Clickable{})
|
||||
}
|
||||
|
||||
func (u *ui) removeCustomFieldRow(index int) {
|
||||
if index < 0 || index >= len(u.customFieldKeys) {
|
||||
return
|
||||
}
|
||||
u.customFieldKeys = append(u.customFieldKeys[:index], u.customFieldKeys[index+1:]...)
|
||||
u.customFieldValues = append(u.customFieldValues[:index], u.customFieldValues[index+1:]...)
|
||||
u.removeCustomFields = append(u.removeCustomFields[:index], u.removeCustomFields[index+1:]...)
|
||||
if len(u.customFieldKeys) == 0 {
|
||||
u.appendCustomFieldRow("", "")
|
||||
}
|
||||
}
|
||||
|
||||
func (u *ui) currentCustomFields() (map[string]string, error) {
|
||||
fields := map[string]string{}
|
||||
for i := range u.customFieldKeys {
|
||||
key := strings.TrimSpace(u.customFieldKeys[i].Text())
|
||||
value := strings.TrimSpace(u.customFieldValues[i].Text())
|
||||
if key == "" && value == "" {
|
||||
continue
|
||||
}
|
||||
if key == "" {
|
||||
return nil, fmt.Errorf("custom field name is required")
|
||||
}
|
||||
fields[key] = value
|
||||
}
|
||||
if len(fields) == 0 && strings.TrimSpace(u.entryFields.Text()) != "" {
|
||||
return parseFields(u.entryFields.Text())
|
||||
}
|
||||
if len(fields) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return fields, nil
|
||||
}
|
||||
|
||||
func (u *ui) visibleHistory() []vault.Entry {
|
||||
item, ok := u.selectedEntry()
|
||||
if !ok || len(item.History) == 0 {
|
||||
@@ -341,7 +407,7 @@ func (u *ui) editorEntry() (vault.Entry, error) {
|
||||
if root := u.hiddenVaultRoot(); root != "" && (len(path) == 0 || path[0] != root) {
|
||||
path = append([]string{root}, path...)
|
||||
}
|
||||
fields, err := parseFields(u.entryFields.Text())
|
||||
fields, err := u.currentCustomFields()
|
||||
if err != nil {
|
||||
return vault.Entry{}, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user