summaryrefslogtreecommitdiff
path: root/internal/client/ui/auth
diff options
context:
space:
mode:
Diffstat (limited to 'internal/client/ui/auth')
-rw-r--r--internal/client/ui/auth/auth.go75
-rw-r--r--internal/client/ui/auth/field/field.go27
2 files changed, 77 insertions, 25 deletions
diff --git a/internal/client/ui/auth/auth.go b/internal/client/ui/auth/auth.go
index 647d238..9444491 100644
--- a/internal/client/ui/auth/auth.go
+++ b/internal/client/ui/auth/auth.go
@@ -20,13 +20,16 @@ var (
errorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#F16265"))
fieldStyle = lipgloss.NewStyle().
PaddingLeft(1).
- BorderStyle(lipgloss.RoundedBorder()).
+ Border(lipgloss.RoundedBorder()).
BorderForeground(lipgloss.Color("#007E8A"))
- focusedButton = focusedStyle.Render("[ Submit ]")
+ focusedButton = focusedStyle.Render("[ sign-up ]")
blurredButton = fmt.Sprintf("[ %s ]", lipgloss.NewStyle().
- Foreground(lipgloss.Color("240")).
- Render("Submit"))
+ Foreground(lipgloss.Color("240")).
+ Render("sign-up"))
+
+ headerStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#54D7A9"))
+ titleStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#5874FF"))
)
type Model struct {
@@ -53,33 +56,56 @@ func New() Model {
switch i {
case 0:
+ field.Header = "Username"
field.Input.Placeholder = "Username"
field.Focus()
+ field.Input.Validate = func(username string) error {
+ if len(username) == 0 {
+ return errors.New("* required field")
+ }
+ return nil
+ }
case 1:
+ field.Header = "Email (Optional)"
field.Input.Placeholder = "Email"
field.Input.CharLimit = 64
field.Input.Validate = func(email string) error {
+ if len(email) == 0 {
+ return errors.New("* required field")
+ }
+ var errs []string
if !strings.ContainsRune(email, '@') {
- return errors.New("missing @")
+ errs = append(errs, "- missing @")
}
if !strings.ContainsRune(email, '.') {
- return errors.New("missing .")
+ errs = append(errs, "- missing .")
}
proton := strings.Contains(email, "proton.me") || strings.Contains(email, "protonmail.com")
gmail := strings.Contains(email, "gmail.com")
outlook := strings.Contains(email, "hotmail.com")
if !(proton || gmail || outlook) {
- return errors.New("unknown email provider")
+ errs = append(errs, "- unknown email provider")
+ }
+ if errs != nil {
+ return errors.New(strings.Join(errs, "\n"))
}
return nil
}
case 2:
+ field.Header = "Password"
field.Input.Placeholder = "Password"
field.Input.EchoMode = textinput.EchoPassword
field.Input.EchoCharacter = '*'
// field.Input.EchoCharacter = '•'
+ field.Input.Validate = func(password string) error {
+ if len(password) == 0 {
+ return errors.New("* required field")
+ }
+ return nil
+ }
}
+ field.Header = headerStyle.Render(field.Header)
m.fields[i] = field
}
@@ -93,6 +119,7 @@ func (m Model) Init() tea.Cmd {
func (m Model) View() string {
var builder strings.Builder
+ builder.WriteRune('\n')
for i := range m.fields {
builder.WriteString(m.fields[i].View())
if i < len(m.fields)-1 {
@@ -105,19 +132,26 @@ func (m Model) View() string {
button = &focusedButton
}
submit := lipgloss.NewStyle().
- PaddingLeft((lipgloss.Width(builder.String()) - lipgloss.Width(*button)) / 2).
Render(*button)
fmt.Fprintf(&builder, "\n\n%s", submit)
- width, height := lipgloss.Width(builder.String()), lipgloss.Height(builder.String())
+ title := titleStyle.Render(`
+____ _ ____ _ _ _ _ ___
+[__ | | __ |\ | __ | | |__]
+___] | |__] | \| |__| |
+ `)
+
+ // Tiny offset so odd numbers will have the extra char on the right, ie: 12 <thing> 13
+ content := lipgloss.JoinVertical(lipgloss.Center-0.01, title, builder.String())
+ width := lipgloss.Width(content)
vp := viewport.New(50, 25)
- vp.SetContent(builder.String())
+ vp.SetContent(content)
vp.Style = vp.Style.
Border(lipgloss.RoundedBorder()).
- BorderForeground(lipgloss.Color("#0000FF")).
+ BorderForeground(lipgloss.Color("#007E8A")).
// NOTE: Without -1 it wraps/truncates, not sure why
- Padding((vp.Height-height)/2-1, (vp.Width-width)/2-1)
+ Padding(0, (vp.Width-width)/2-1)
return lipgloss.Place(
m.width, m.height,
@@ -141,7 +175,22 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case tea.KeyTab, tea.KeyShiftTab, tea.KeyEnter, tea.KeyUp, tea.KeyDown:
// User pressed submit
if key == tea.KeyEnter && m.focusIndex == len(m.fields) {
- return m, tea.Quit
+ var cmds []tea.Cmd
+ for i, field := range m.fields {
+ if field.Input.Validate == nil {
+ continue
+ }
+ field.Input.Err = field.Input.Validate(field.Input.Value())
+ if field.Input.Err != nil {
+ var cmd tea.Cmd
+ m.fields[i], cmd = field.Update(msg)
+ cmds = append(cmds, cmd)
+ }
+ }
+ if len(cmds) == 0 {
+ return m, tea.Quit
+ }
+ return m, tea.Batch(cmds...)
}
// Cycle indexes
diff --git a/internal/client/ui/auth/field/field.go b/internal/client/ui/auth/field/field.go
index afc55b1..623cdd6 100644
--- a/internal/client/ui/auth/field/field.go
+++ b/internal/client/ui/auth/field/field.go
@@ -1,20 +1,20 @@
package field
import (
- "strings"
-
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
-)
+ "github.com/kyren223/eko/internal/client/ui"
+)
type Model struct {
- Input textinput.Model
- Style lipgloss.Style
+ Input textinput.Model
+ Style lipgloss.Style
FocusedStyle lipgloss.Style
BlurredStyle lipgloss.Style
- ErrorStyle lipgloss.Style
+ ErrorStyle lipgloss.Style
+ Header string
}
func New(width int) Model {
@@ -37,15 +37,18 @@ func (m Model) Init() tea.Cmd {
}
func (m Model) View() string {
- var builder strings.Builder
-
- builder.WriteString(m.Style.Render(m.Input.View()))
- builder.WriteRune('\n')
+ style := m.Style
+ error := ""
if m.Input.Err != nil {
- builder.WriteString(m.ErrorStyle.Render(m.Input.Err.Error()))
+ error = m.Input.Err.Error()
+ style = style.BorderForeground(m.ErrorStyle.GetForeground())
}
+ field := ui.AddBorderHeader(m.Header, 1, style, m.Input.View())
+
+ error = m.ErrorStyle.MaxWidth(lipgloss.Width(field)).Render(error)
- return builder.String()
+ // return lipgloss.JoinVertical(lipgloss.Left, borderTop, field, error)
+ return lipgloss.JoinVertical(lipgloss.Left, field, error)
}
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {