This commit is contained in:
parent
0e0ce5f2b4
commit
a09b833ca6
114
internal/ui.go
114
internal/ui.go
|
@ -15,15 +15,34 @@ import (
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
)
|
)
|
||||||
|
|
||||||
type view uint8
|
type state uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
viewPassword view = iota + 1
|
stateEnteringPassword state = iota + 1
|
||||||
viewList
|
stateBrowsingList
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
keyBindingCopy = key.NewBinding(
|
||||||
|
key.WithKeys("enter"),
|
||||||
|
key.WithHelp("enter", "copy to clipboard"),
|
||||||
|
)
|
||||||
|
keyBindingUnlock = key.NewBinding(
|
||||||
|
key.WithKeys("enter"),
|
||||||
|
key.WithHelp("enter", "unlock vault"),
|
||||||
|
)
|
||||||
|
keyBindingQuit = key.NewBinding(
|
||||||
|
key.WithKeys("esc", "ctrl+c"),
|
||||||
|
key.WithHelp("esc/ctrl+c", "quit"),
|
||||||
|
)
|
||||||
|
keyClearFilter = key.NewBinding(
|
||||||
|
key.WithKeys("c"),
|
||||||
|
key.WithHelp("c", "clear filter"),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
type UI struct {
|
type UI struct {
|
||||||
view view
|
state state
|
||||||
vault Vault
|
vault Vault
|
||||||
db DB
|
db DB
|
||||||
list list.Model
|
list list.Model
|
||||||
|
@ -57,9 +76,10 @@ func NewUI(appName string, vault Vault) UI {
|
||||||
}
|
}
|
||||||
|
|
||||||
l.KeyMap.Quit = keyBindingQuit
|
l.KeyMap.Quit = keyBindingQuit
|
||||||
|
l.KeyMap.ClearFilter = keyClearFilter
|
||||||
|
|
||||||
return UI{
|
return UI{
|
||||||
view: viewPassword,
|
state: stateEnteringPassword,
|
||||||
vault: vault,
|
vault: vault,
|
||||||
list: l,
|
list: l,
|
||||||
passwordInput: passwordInput,
|
passwordInput: passwordInput,
|
||||||
|
@ -77,48 +97,37 @@ type refreshListMsg struct {
|
||||||
t time.Time
|
t time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
keyBindingCopy = key.NewBinding(
|
|
||||||
key.WithKeys("enter"),
|
|
||||||
key.WithHelp("enter", "copy to clipboard"),
|
|
||||||
key.WithDisabled(),
|
|
||||||
)
|
|
||||||
keyBindingUnlock = key.NewBinding(
|
|
||||||
key.WithKeys("enter"),
|
|
||||||
key.WithHelp("enter", "unlock vault"),
|
|
||||||
)
|
|
||||||
keyBindingQuit = key.NewBinding(
|
|
||||||
key.WithKeys("esc", "ctrl+c"),
|
|
||||||
key.WithHelp("esc/ctrl+c", "quit"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func (m UI) Update(teaMsg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m UI) Update(teaMsg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
var cmd tea.Cmd
|
||||||
|
|
||||||
|
if msg, ok := teaMsg.(tea.WindowSizeMsg); ok {
|
||||||
|
h, v := listStyle.GetFrameSize()
|
||||||
|
m.list.SetSize(msg.Width-h, msg.Height-v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, tea.Batch(cmd, m.handleEnteringPassword(teaMsg), m.handleBrowsingList(teaMsg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *UI) handleEnteringPassword(teaMsg tea.Msg) tea.Cmd {
|
||||||
|
if m.state != stateEnteringPassword {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var passwordInputCmd tea.Cmd
|
var passwordInputCmd tea.Cmd
|
||||||
//nolint:revive
|
|
||||||
m.passwordInput, passwordInputCmd = m.passwordInput.Update(teaMsg)
|
m.passwordInput, passwordInputCmd = m.passwordInput.Update(teaMsg)
|
||||||
|
|
||||||
if m.passwordInput.Value() != "" && m.passwordError != nil {
|
if m.passwordInput.Value() != "" && m.passwordError != nil {
|
||||||
//nolint:revive
|
|
||||||
m.passwordError = nil
|
m.passwordError = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmd tea.Cmd
|
var cmd tea.Cmd
|
||||||
|
|
||||||
switch msg := teaMsg.(type) {
|
switch msg := teaMsg.(type) {
|
||||||
case tea.WindowSizeMsg:
|
|
||||||
h, v := listStyle.GetFrameSize()
|
|
||||||
m.list.SetSize(msg.Width-h, msg.Height-v)
|
|
||||||
case refreshListMsg:
|
|
||||||
cmd = tea.Batch(
|
|
||||||
m.list.SetItems(newListItems(m.db, msg.t)),
|
|
||||||
m.tick(),
|
|
||||||
)
|
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
switch {
|
switch {
|
||||||
case key.Matches(msg, keyBindingQuit):
|
case key.Matches(msg, keyBindingQuit):
|
||||||
return m, tea.Quit
|
return tea.Quit
|
||||||
case key.Matches(msg, keyBindingUnlock):
|
case key.Matches(msg, keyBindingUnlock):
|
||||||
var err error
|
var err error
|
||||||
//nolint:revive
|
//nolint:revive
|
||||||
|
@ -129,16 +138,41 @@ func (m UI) Update(teaMsg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
m.passwordInput.Reset()
|
m.passwordInput.Reset()
|
||||||
} else {
|
} else {
|
||||||
//nolint:revive
|
//nolint:revive
|
||||||
m.view = viewList
|
m.state = stateBrowsingList
|
||||||
keyBindingUnlock.SetEnabled(false)
|
|
||||||
keyBindingCopy.SetEnabled(true)
|
|
||||||
cmd = tea.Batch(
|
cmd = tea.Batch(
|
||||||
m.list.SetItems(newListItems(m.db, time.Now())),
|
m.list.SetItems(newListItems(m.db, time.Now())),
|
||||||
m.tick(),
|
m.tick(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
case key.Matches(msg, keyBindingCopy) && !clipboard.Unsupported:
|
}
|
||||||
item, ok := m.list.SelectedItem().(listItem)
|
}
|
||||||
|
|
||||||
|
return tea.Batch(passwordInputCmd, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *UI) handleBrowsingList(teaMsg tea.Msg) tea.Cmd {
|
||||||
|
if m.state != stateBrowsingList {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmd tea.Cmd
|
||||||
|
|
||||||
|
switch msg := teaMsg.(type) {
|
||||||
|
case refreshListMsg:
|
||||||
|
for _, i := range m.list.Items() {
|
||||||
|
converted, ok := i.(*listItem)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
converted.t = msg.t
|
||||||
|
}
|
||||||
|
cmd = tea.Batch(
|
||||||
|
m.tick(),
|
||||||
|
)
|
||||||
|
case tea.KeyMsg:
|
||||||
|
if key.Matches(msg, keyBindingCopy) && !clipboard.Unsupported {
|
||||||
|
item, ok := m.list.SelectedItem().(*listItem)
|
||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -154,7 +188,7 @@ func (m UI) Update(teaMsg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
//nolint:revive
|
//nolint:revive
|
||||||
m.list, listCmd = m.list.Update(teaMsg)
|
m.list, listCmd = m.list.Update(teaMsg)
|
||||||
|
|
||||||
return m, tea.Batch(passwordInputCmd, cmd, listCmd)
|
return tea.Batch(listCmd, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
const tickDuration = time.Second
|
const tickDuration = time.Second
|
||||||
|
@ -171,7 +205,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m UI) View() string {
|
func (m UI) View() string {
|
||||||
if m.view == viewList {
|
if m.state == stateBrowsingList {
|
||||||
return listStyle.Render(m.list.View())
|
return listStyle.Render(m.list.View())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +234,7 @@ type listItem struct {
|
||||||
func newListItems(db DB, t time.Time) []list.Item {
|
func newListItems(db DB, t time.Time) []list.Item {
|
||||||
items := make([]list.Item, 0, len(db.Entries))
|
items := make([]list.Item, 0, len(db.Entries))
|
||||||
for _, e := range db.Entries {
|
for _, e := range db.Entries {
|
||||||
items = append(items, listItem{
|
items = append(items, &listItem{
|
||||||
entry: e,
|
entry: e,
|
||||||
t: t,
|
t: t,
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue
Block a user