242 lines
5.4 KiB
Go
242 lines
5.4 KiB
Go
package stages
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"gitea.konchin.com/ytshih/inp2025/models"
|
|
"github.com/charmbracelet/bubbles/textinput"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
)
|
|
|
|
type landingOperationType int
|
|
|
|
const (
|
|
landingOperationChoose landingOperationType = iota
|
|
landingOperationLoginCred
|
|
landingOperationRegistCred
|
|
)
|
|
|
|
type focusTargetType int
|
|
|
|
const (
|
|
focusTargetUsername focusTargetType = iota
|
|
focusTargetPassword
|
|
)
|
|
|
|
type LandingModel struct {
|
|
*BaseModel
|
|
op landingOperationType
|
|
|
|
focus focusTargetType
|
|
username textinput.Model
|
|
password textinput.Model
|
|
|
|
info string
|
|
err error
|
|
}
|
|
|
|
func NewLandingModel(base *BaseModel) *LandingModel {
|
|
username := textinput.New()
|
|
username.Placeholder = "Username"
|
|
username.CharLimit = 32
|
|
username.Width = 32
|
|
username.Blur()
|
|
|
|
password := textinput.New()
|
|
password.Placeholder = "Password"
|
|
password.CharLimit = 32
|
|
password.Width = 32
|
|
password.Blur()
|
|
password.EchoMode = textinput.EchoPassword
|
|
password.EchoCharacter = '•'
|
|
|
|
return &LandingModel{
|
|
BaseModel: base,
|
|
op: landingOperationChoose,
|
|
|
|
username: username,
|
|
password: password,
|
|
}
|
|
}
|
|
|
|
func (m *LandingModel) reset() {
|
|
m.op = landingOperationChoose
|
|
m.username.Blur()
|
|
m.username.Reset()
|
|
m.password.Blur()
|
|
m.password.Reset()
|
|
}
|
|
|
|
type postLoginMsg struct{}
|
|
|
|
func (m *LandingModel) postLogin() tea.Cmd {
|
|
return func() tea.Msg {
|
|
resp, err := m.BaseModel.client.R().
|
|
SetBasicAuth(m.username.Value(), m.password.Value()).
|
|
Post("/auth/login")
|
|
if err == nil {
|
|
switch resp.StatusCode() {
|
|
case http.StatusOK:
|
|
m.BaseModel.client.SetBasicAuth(
|
|
m.username.Value(), m.password.Value())
|
|
m.info = "login success.\n"
|
|
m.err = nil
|
|
case http.StatusUnauthorized:
|
|
m.err = fmt.Errorf("user not exist or password incorrect, %s",
|
|
string(resp.Body()))
|
|
default:
|
|
m.err = fmt.Errorf("unknown server error, %s",
|
|
string(resp.Body()))
|
|
}
|
|
} else {
|
|
m.err = fmt.Errorf("failed to post login, %w", err)
|
|
}
|
|
return postLoginMsg{}
|
|
}
|
|
}
|
|
|
|
type postRegisterMsg struct{}
|
|
|
|
func (m *LandingModel) postRegister() tea.Cmd {
|
|
return func() tea.Msg {
|
|
resp, err := m.BaseModel.client.R().
|
|
SetBody(models.User{
|
|
Username: m.username.Value(),
|
|
Password: m.password.Value(),
|
|
}).
|
|
Post("/auth/register")
|
|
if err == nil {
|
|
switch resp.StatusCode() {
|
|
case http.StatusOK:
|
|
m.info = "register success.\n"
|
|
m.err = nil
|
|
case http.StatusBadRequest:
|
|
m.err = fmt.Errorf("username already exist, %s",
|
|
string(resp.Body()))
|
|
default:
|
|
m.err = fmt.Errorf("unknown server error, %s",
|
|
string(resp.Body()))
|
|
}
|
|
} else {
|
|
m.err = fmt.Errorf("failed to post register, %s",
|
|
string(resp.Body()))
|
|
}
|
|
return postRegisterMsg{}
|
|
}
|
|
}
|
|
|
|
func (m *LandingModel) Init() tea.Cmd {
|
|
return tea.ClearScreen
|
|
}
|
|
|
|
func (m *LandingModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
var cmds []tea.Cmd
|
|
|
|
switch msg := msg.(type) {
|
|
case tea.KeyMsg:
|
|
switch msg.String() {
|
|
case "ctrl+c":
|
|
return m, tea.Quit
|
|
case "L", "l":
|
|
if m.op == landingOperationChoose {
|
|
m.op = landingOperationLoginCred
|
|
m.focus = focusTargetUsername
|
|
cmds = append(cmds, m.username.Focus())
|
|
return m, tea.Batch(cmds...)
|
|
}
|
|
case "R", "r":
|
|
if m.op == landingOperationChoose {
|
|
m.op = landingOperationRegistCred
|
|
m.focus = focusTargetUsername
|
|
cmds = append(cmds, m.username.Focus())
|
|
return m, tea.Batch(cmds...)
|
|
}
|
|
case "shift+tab", "up":
|
|
if m.op == landingOperationLoginCred ||
|
|
m.op == landingOperationRegistCred {
|
|
switch m.focus {
|
|
case focusTargetUsername:
|
|
m.username.Blur()
|
|
m.focus = focusTargetPassword
|
|
cmds = append(cmds, m.password.Focus())
|
|
case focusTargetPassword:
|
|
m.password.Blur()
|
|
m.focus = focusTargetUsername
|
|
cmds = append(cmds, m.username.Focus())
|
|
}
|
|
}
|
|
case "tab", "down", "enter":
|
|
if m.op == landingOperationLoginCred ||
|
|
m.op == landingOperationRegistCred {
|
|
switch m.focus {
|
|
case focusTargetUsername:
|
|
m.username.Blur()
|
|
m.focus = focusTargetPassword
|
|
cmds = append(cmds, m.password.Focus())
|
|
case focusTargetPassword:
|
|
if msg.String() == "enter" {
|
|
switch m.op {
|
|
case landingOperationLoginCred:
|
|
cmds = append(cmds, m.postLogin())
|
|
case landingOperationRegistCred:
|
|
cmds = append(cmds, m.postRegister())
|
|
}
|
|
} else {
|
|
m.password.Blur()
|
|
m.focus = focusTargetUsername
|
|
cmds = append(cmds, m.username.Focus())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case postLoginMsg:
|
|
if m.err == nil {
|
|
*m.queue = append(*m.queue,
|
|
tea.NewProgram(NewLobbyModel(m.BaseModel)))
|
|
return m, tea.Quit
|
|
} else {
|
|
m.reset()
|
|
}
|
|
case postRegisterMsg:
|
|
m.reset()
|
|
}
|
|
|
|
var cmd tea.Cmd
|
|
m.username, cmd = m.username.Update(msg)
|
|
cmds = append(cmds, cmd)
|
|
m.password, cmd = m.password.Update(msg)
|
|
cmds = append(cmds, cmd)
|
|
|
|
return m, tea.Batch(cmds...)
|
|
}
|
|
|
|
func (m *LandingModel) View() string {
|
|
var b strings.Builder
|
|
|
|
switch m.op {
|
|
case landingOperationChoose:
|
|
fmt.Fprintf(&b, "Choose Operation\n(L)ogin / (R)egister\n")
|
|
case landingOperationLoginCred:
|
|
fmt.Fprintf(&b, "Login: \n")
|
|
b.WriteString(m.username.View() + "\n")
|
|
b.WriteString(m.password.View() + "\n")
|
|
case landingOperationRegistCred:
|
|
fmt.Fprintf(&b, "Register: \n")
|
|
b.WriteString(m.username.View() + "\n")
|
|
b.WriteString(m.password.View() + "\n")
|
|
}
|
|
|
|
if m.info != "" {
|
|
b.WriteString(m.info + "\n")
|
|
}
|
|
|
|
if m.err != nil {
|
|
b.WriteString("----------\n")
|
|
b.WriteString(m.err.Error() + "\n")
|
|
}
|
|
|
|
return b.String()
|
|
}
|