mirror of
https://github.com/IllusionMan1212/gorc.git
synced 2026-10-24 02:12:33 +00:00
188 lines
4.5 KiB
Go
188 lines
4.5 KiB
Go
// gorc project
|
|
// Copyright (C) 2022 IllusionMan1212
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program; if not, see https://www.gnu.org/licenses.
|
|
|
|
package login
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/charmbracelet/bubbles/textinput"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/charmbracelet/lipgloss"
|
|
"github.com/illusionman1212/gorc/cmds"
|
|
"github.com/illusionman1212/gorc/ui"
|
|
)
|
|
|
|
type State struct {
|
|
FocusIndex int
|
|
Inputs []textinput.Model
|
|
TLS bool
|
|
DialogStyle lipgloss.Style
|
|
WelcomeMsgStyle lipgloss.Style
|
|
Style lipgloss.Style
|
|
}
|
|
|
|
func NewLogin() State {
|
|
state := State{
|
|
Inputs: make([]textinput.Model, 5),
|
|
DialogStyle: DialogStyle.Copy(),
|
|
WelcomeMsgStyle: WelcomeMsgStyle.Copy(),
|
|
Style: ui.MainStyle.Copy(),
|
|
}
|
|
|
|
var t textinput.Model
|
|
for i := range state.Inputs {
|
|
t = textinput.New()
|
|
t.CursorStyle = ui.CursorStyle
|
|
t.Prompt = "| "
|
|
|
|
switch i {
|
|
case 0:
|
|
t.Placeholder = "Host"
|
|
t.Focus()
|
|
t.CharLimit = 40
|
|
t.TextStyle = ui.FocusedStyle
|
|
case 1:
|
|
t.Placeholder = "Port"
|
|
t.CharLimit = 5
|
|
case 2:
|
|
t.Placeholder = "Channel"
|
|
t.CharLimit = 32
|
|
case 3:
|
|
t.Placeholder = "Nickname"
|
|
t.CharLimit = 32
|
|
case 4:
|
|
t.Placeholder = "Password"
|
|
t.CharLimit = 32
|
|
t.EchoMode = textinput.EchoPassword
|
|
t.EchoCharacter = '•'
|
|
}
|
|
|
|
state.Inputs[i] = t
|
|
}
|
|
|
|
return state
|
|
}
|
|
|
|
func (s State) Update(msg tea.Msg) (State, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
case tea.KeyMsg:
|
|
key := msg.String()
|
|
switch key {
|
|
case " ", "enter":
|
|
// run the Connect cmd when pressing "enter" while focused on the connect button
|
|
if key == "enter" && s.FocusIndex == len(s.Inputs)+1 {
|
|
return s, cmds.Connect
|
|
}
|
|
|
|
// toggle tls state when pressing "enter" or "space" while focused on the checkbox
|
|
if (key == "enter" || key == " ") && s.FocusIndex == len(s.Inputs) {
|
|
s.TLS = !s.TLS
|
|
return s, nil
|
|
}
|
|
case "tab", "shift+tab", "up", "down":
|
|
if key == "up" || key == "shift+tab" {
|
|
s.FocusIndex--
|
|
} else {
|
|
s.FocusIndex++
|
|
}
|
|
|
|
if s.FocusIndex > len(s.Inputs)+1 {
|
|
s.FocusIndex = 0
|
|
} else if s.FocusIndex < 0 {
|
|
s.FocusIndex = len(s.Inputs) + 1
|
|
}
|
|
|
|
cmds := make([]tea.Cmd, len(s.Inputs))
|
|
for i := 0; i <= len(s.Inputs)-1; i++ {
|
|
if i == s.FocusIndex {
|
|
cmds[i] = s.Inputs[i].Focus()
|
|
s.Inputs[i].PromptStyle = ui.FocusedStyle
|
|
s.Inputs[i].TextStyle = ui.FocusedStyle
|
|
continue
|
|
}
|
|
|
|
s.Inputs[i].Blur()
|
|
s.Inputs[i].PromptStyle = ui.NoStyle
|
|
s.Inputs[i].TextStyle = ui.NoStyle
|
|
}
|
|
|
|
return s, tea.Batch(cmds...)
|
|
}
|
|
}
|
|
|
|
cmd := s.updateInputs(msg)
|
|
|
|
return s, cmd
|
|
}
|
|
|
|
func (s *State) updateInputs(msg tea.Msg) tea.Cmd {
|
|
var cmds = make([]tea.Cmd, len(s.Inputs))
|
|
|
|
for i := range s.Inputs {
|
|
s.Inputs[i], cmds[i] = s.Inputs[i].Update(msg)
|
|
}
|
|
|
|
return tea.Batch(cmds...)
|
|
}
|
|
|
|
func (s *State) SetSize(width, height int) {
|
|
s.DialogStyle = s.DialogStyle.Copy().Width(width - s.DialogStyle.GetHorizontalFrameSize())
|
|
s.DialogStyle = s.DialogStyle.Copy().Height(height*5/10 - s.DialogStyle.GetVerticalFrameSize())
|
|
|
|
s.WelcomeMsgStyle = s.WelcomeMsgStyle.Copy().Width(width)
|
|
s.WelcomeMsgStyle = s.WelcomeMsgStyle.Copy().Height(height * 5 / 10)
|
|
}
|
|
|
|
func (s State) View() string {
|
|
var sb strings.Builder
|
|
|
|
for i := range s.Inputs {
|
|
sb.WriteString(s.Inputs[i].View())
|
|
if i < len(s.Inputs)-1 {
|
|
sb.WriteRune('\n')
|
|
}
|
|
}
|
|
|
|
checkbox := &BlurredCheckbox
|
|
// if the checkbox is focused
|
|
if s.FocusIndex == len(s.Inputs) {
|
|
checkbox = &FocusedCheckbox
|
|
// if tls is enabled
|
|
if s.TLS {
|
|
checkbox = &FocusedCheckboxChecked
|
|
}
|
|
}
|
|
|
|
// if the checkbox is not focused and tls is enabled
|
|
if s.FocusIndex != len(s.Inputs) && s.TLS {
|
|
checkbox = &BlurredCheckboxChecked
|
|
}
|
|
|
|
fmt.Fprintf(&sb, "\n%s\n", *checkbox)
|
|
|
|
button := &BlurredButton
|
|
if s.FocusIndex == len(s.Inputs)+1 {
|
|
button = &FocusedButton
|
|
}
|
|
fmt.Fprintf(&sb, "\n%s\n", *button)
|
|
|
|
screen := lipgloss.JoinVertical(lipgloss.Center, s.WelcomeMsgStyle.Render(WelcomeMsg), s.DialogStyle.Render(sb.String()))
|
|
|
|
return ui.MainStyle.Render(screen)
|
|
}
|