113 lines
3.1 KiB
Go
113 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
"strings"
|
|
|
|
"gioui.org/layout"
|
|
"gioui.org/op/clip"
|
|
"gioui.org/op/paint"
|
|
"gioui.org/unit"
|
|
)
|
|
|
|
type focusAppearance struct {
|
|
BorderColor color.NRGBA
|
|
OutlineColor color.NRGBA
|
|
OutlineWidth int
|
|
MinHeight int
|
|
}
|
|
|
|
func fieldFocusAppearance(metric unit.Metric, focused bool) focusAppearance {
|
|
appearance := focusAppearance{
|
|
BorderColor: color.NRGBA{R: 202, G: 194, B: 180, A: 255},
|
|
OutlineColor: color.NRGBA{A: 0},
|
|
OutlineWidth: max(1, metric.Dp(unit.Dp(1))),
|
|
MinHeight: metric.Dp(unit.Dp(44)),
|
|
}
|
|
if focused {
|
|
appearance.BorderColor = accentColor
|
|
appearance.OutlineColor = color.NRGBA{R: 28, G: 83, B: 63, A: 72}
|
|
appearance.OutlineWidth = max(2, metric.Dp(unit.Dp(2)))
|
|
}
|
|
return appearance
|
|
}
|
|
|
|
func buttonFocusColors(focused bool) (background color.NRGBA, text color.NRGBA) {
|
|
background = color.NRGBA{R: 231, G: 239, B: 235, A: 255}
|
|
text = accentColor
|
|
if focused {
|
|
background = color.NRGBA{R: 214, G: 229, B: 221, A: 255}
|
|
}
|
|
return background, text
|
|
}
|
|
|
|
func (u *ui) accessibilityLabel(id focusID) string {
|
|
switch {
|
|
case id == focusSearch:
|
|
return "Search vault"
|
|
case strings.HasPrefix(string(id), "breadcrumb:"):
|
|
index := focusIndex(id)
|
|
crumbs := u.breadcrumbLabels()
|
|
if index >= 0 && index < len(crumbs) {
|
|
return fmt.Sprintf("Navigate to %s", crumbs[index])
|
|
}
|
|
case strings.HasPrefix(string(id), "list:"):
|
|
index := focusIndex(id)
|
|
if index >= 0 && index < len(u.visible) {
|
|
return fmt.Sprintf("Select entry %s", u.visible[index].Title)
|
|
}
|
|
case strings.HasPrefix(string(id), "detail:"):
|
|
name := strings.TrimPrefix(string(id), "detail:")
|
|
return fmt.Sprintf("Edit %s", detailFieldLabel(detailField(name)))
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func drawFocusOutline(gtx layout.Context, appearance focusAppearance, size image.Point) layout.Dimensions {
|
|
if appearance.OutlineColor.A == 0 || appearance.OutlineWidth <= 0 {
|
|
return layout.Dimensions{Size: size}
|
|
}
|
|
|
|
width := appearance.OutlineWidth
|
|
paint.FillShape(gtx.Ops, appearance.OutlineColor, clip.Rect{Max: image.Pt(size.X, width)}.Op())
|
|
paint.FillShape(gtx.Ops, appearance.OutlineColor, clip.Rect{Min: image.Pt(0, size.Y-width), Max: image.Pt(size.X, size.Y)}.Op())
|
|
paint.FillShape(gtx.Ops, appearance.OutlineColor, clip.Rect{Max: image.Pt(width, size.Y)}.Op())
|
|
paint.FillShape(gtx.Ops, appearance.OutlineColor, clip.Rect{Min: image.Pt(size.X-width, 0), Max: image.Pt(size.X, size.Y)}.Op())
|
|
return layout.Dimensions{Size: size}
|
|
}
|
|
|
|
func (u *ui) isFocused(id focusID) bool {
|
|
return u.keyboardFocus == id
|
|
}
|
|
|
|
func detailFieldLabel(field detailField) string {
|
|
switch field {
|
|
case detailFieldID:
|
|
return "ID"
|
|
case detailFieldTitle:
|
|
return "Title"
|
|
case detailFieldUsername:
|
|
return "Username"
|
|
case detailFieldPassword:
|
|
return "Password"
|
|
case detailFieldURL:
|
|
return "URL"
|
|
case detailFieldPath:
|
|
return "Path"
|
|
case detailFieldTags:
|
|
return "Tags"
|
|
case detailFieldPasswordProfile:
|
|
return "Password Profile"
|
|
case detailFieldNotes:
|
|
return "Notes"
|
|
case detailFieldFields:
|
|
return "Custom Fields"
|
|
case detailFieldHistoryIndex:
|
|
return "History Index"
|
|
default:
|
|
return strings.ReplaceAll(string(field), "-", " ")
|
|
}
|
|
}
|