|
@@ -12,14 +12,16 @@ import (
|
|
|
|
|
|
|
|
// Desktop -- консольный клиент для вар-танка
|
|
// Desktop -- консольный клиент для вар-танка
|
|
|
type Desktop struct {
|
|
type Desktop struct {
|
|
|
|
|
+ TeaModel
|
|
|
|
|
+ p *tea.Program // Объект приложения
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-var p *tea.Program
|
|
|
|
|
-
|
|
|
|
|
func NewDesktop() *Desktop {
|
|
func NewDesktop() *Desktop {
|
|
|
sf := &Desktop{}
|
|
sf := &Desktop{}
|
|
|
- p = tea.NewProgram(initialModel(), tea.WithAltScreen(), tea.WithANSICompressor())
|
|
|
|
|
- if _, err := p.Run(); err != nil {
|
|
|
|
|
|
|
+ sf.TeaModel = NewModel()
|
|
|
|
|
+ go sf.tick()
|
|
|
|
|
+ sf.p = tea.NewProgram(sf, tea.WithAltScreen(), tea.WithANSICompressor())
|
|
|
|
|
+ if _, err := sf.p.Run(); err != nil {
|
|
|
fmt.Printf("Опа! здесь какая-то ошибочка: %v", err)
|
|
fmt.Printf("Опа! здесь какая-то ошибочка: %v", err)
|
|
|
os.Exit(1)
|
|
os.Exit(1)
|
|
|
}
|
|
}
|
|
@@ -31,44 +33,48 @@ func NewDesktop() *Desktop {
|
|
|
type AMode int
|
|
type AMode int
|
|
|
|
|
|
|
|
const (
|
|
const (
|
|
|
- ModeDefault AMode = iota
|
|
|
|
|
- ModeConfig
|
|
|
|
|
- ModeConfigServer
|
|
|
|
|
- ModeInputHostServer
|
|
|
|
|
|
|
+ ModeDefault AMode = iota
|
|
|
|
|
+ ModeConfig // Режим конфигурирования
|
|
|
|
|
+ ModeConfigServer // Режим конфигуррования сервера
|
|
|
|
|
+ ModeInputHostServer // Режим ввода хоста сервера
|
|
|
|
|
+ ModeInputLoginServer // Режим ввода логина на сервер
|
|
|
|
|
+ ModeInputPassServer // Режим ввода пароля входа на сервер
|
|
|
|
|
+ ModeConnectServer // Режим подключения к серверу
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-type model struct {
|
|
|
|
|
|
|
+type TeaModel struct {
|
|
|
choices []string // выбранный пункт в списке
|
|
choices []string // выбранный пункт в списке
|
|
|
cursor int // позиция курсора в списке
|
|
cursor int // позиция курсора в списке
|
|
|
selected map[int]struct{} // что выбрано из списка
|
|
selected map[int]struct{} // что выбрано из списка
|
|
|
mode AMode // Режим показа на экране
|
|
mode AMode // Режим показа на экране
|
|
|
textInput textinput.Model
|
|
textInput textinput.Model
|
|
|
- host string
|
|
|
|
|
|
|
+ host string // Имя хоста сервера (с портом)
|
|
|
|
|
+ login string // Логин для сервера
|
|
|
|
|
+ pass string // Пароль для сервера
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func initialModel() model {
|
|
|
|
|
|
|
+func NewModel() TeaModel {
|
|
|
ti := textinput.New()
|
|
ti := textinput.New()
|
|
|
ti.Placeholder = "localhost"
|
|
ti.Placeholder = "localhost"
|
|
|
ti.Focus()
|
|
ti.Focus()
|
|
|
ti.CharLimit = 156
|
|
ti.CharLimit = 156
|
|
|
ti.Width = 20
|
|
ti.Width = 20
|
|
|
|
|
|
|
|
- m := model{
|
|
|
|
|
|
|
+ m := TeaModel{
|
|
|
// Список дел
|
|
// Список дел
|
|
|
choices: []string{"Купить картошку", "Оплатить мобилку", "Заплатить за кредит"},
|
|
choices: []string{"Купить картошку", "Оплатить мобилку", "Заплатить за кредит"},
|
|
|
selected: make(map[int]struct{}),
|
|
selected: make(map[int]struct{}),
|
|
|
textInput: ti,
|
|
textInput: ti,
|
|
|
}
|
|
}
|
|
|
- go m.tick()
|
|
|
|
|
return m
|
|
return m
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (m *model) tick() {
|
|
|
|
|
|
|
+func (sf *Desktop) tick() {
|
|
|
for {
|
|
for {
|
|
|
time.Sleep(time.Second * 1)
|
|
time.Sleep(time.Second * 1)
|
|
|
msg := tea.MouseEvent{}
|
|
msg := tea.MouseEvent{}
|
|
|
// m.Update(msg)
|
|
// m.Update(msg)
|
|
|
- p.Send(msg)
|
|
|
|
|
|
|
+ sf.p.Send(msg)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -77,38 +83,44 @@ func (sf *Desktop) Run() error {
|
|
|
return nil
|
|
return nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (m model) Init() tea.Cmd {
|
|
|
|
|
|
|
+func (sf Desktop) Init() tea.Cmd {
|
|
|
// Просто вернуть `nil`, т.е. никаких команд
|
|
// Просто вернуть `nil`, т.е. никаких команд
|
|
|
return textinput.Blink
|
|
return textinput.Blink
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
|
|
|
|
+func (sf Desktop) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
var cmd tea.Cmd
|
|
var cmd tea.Cmd
|
|
|
- switch m.mode {
|
|
|
|
|
|
|
+ switch msg := msg.(type) {
|
|
|
|
|
+ // Может клавиша нажата
|
|
|
|
|
+ case tea.KeyMsg:
|
|
|
|
|
+ switch msg.String() { // Да, нажато, а что именно?
|
|
|
|
|
+ case "ctrl+q": // Надо выйти из программы
|
|
|
|
|
+ return sf, tea.Quit
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ switch sf.mode {
|
|
|
case ModeDefault:
|
|
case ModeDefault:
|
|
|
switch msg := msg.(type) {
|
|
switch msg := msg.(type) {
|
|
|
// Может клавиша нажата
|
|
// Может клавиша нажата
|
|
|
case tea.KeyMsg:
|
|
case tea.KeyMsg:
|
|
|
switch msg.String() { // Да, нажато, а что именно?
|
|
switch msg.String() { // Да, нажато, а что именно?
|
|
|
- case "ctrl+q": // Надо выйти из программы
|
|
|
|
|
- return m, tea.Quit
|
|
|
|
|
case "up", "k": // Если "up" или "k" перемещение курсора вверх
|
|
case "up", "k": // Если "up" или "k" перемещение курсора вверх
|
|
|
- if m.cursor > 0 {
|
|
|
|
|
- m.cursor--
|
|
|
|
|
|
|
+ if sf.cursor > 0 {
|
|
|
|
|
+ sf.cursor--
|
|
|
}
|
|
}
|
|
|
case "down", "j": // Если "down" или "j" перемещение курсора вниз
|
|
case "down", "j": // Если "down" или "j" перемещение курсора вниз
|
|
|
- if m.cursor < len(m.choices)-1 {
|
|
|
|
|
- m.cursor++
|
|
|
|
|
|
|
+ if sf.cursor < len(sf.choices)-1 {
|
|
|
|
|
+ sf.cursor++
|
|
|
}
|
|
}
|
|
|
case "enter", " ": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
|
|
case "enter", " ": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
|
|
|
- _, ok := m.selected[m.cursor]
|
|
|
|
|
|
|
+ _, ok := sf.selected[sf.cursor]
|
|
|
if ok {
|
|
if ok {
|
|
|
- delete(m.selected, m.cursor)
|
|
|
|
|
|
|
+ delete(sf.selected, sf.cursor)
|
|
|
} else {
|
|
} else {
|
|
|
- m.selected[m.cursor] = struct{}{}
|
|
|
|
|
|
|
+ sf.selected[sf.cursor] = struct{}{}
|
|
|
}
|
|
}
|
|
|
case "w": // Настройки графического клиента
|
|
case "w": // Настройки графического клиента
|
|
|
- m.mode = ModeConfig
|
|
|
|
|
|
|
+ sf.mode = ModeConfig
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
case ModeConfig:
|
|
case ModeConfig:
|
|
@@ -116,12 +128,12 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
// Может клавиша нажата
|
|
// Может клавиша нажата
|
|
|
case tea.KeyMsg:
|
|
case tea.KeyMsg:
|
|
|
switch msg.String() { // Да, нажато, а что именно?
|
|
switch msg.String() { // Да, нажато, а что именно?
|
|
|
- case "ctrl+q": // Надо выйти из программы
|
|
|
|
|
- return m, tea.Quit
|
|
|
|
|
case "q": // Вернуться на шаг назад
|
|
case "q": // Вернуться на шаг назад
|
|
|
- m.mode = ModeDefault
|
|
|
|
|
|
|
+ sf.mode = ModeDefault
|
|
|
case "1": // Выбор один
|
|
case "1": // Выбор один
|
|
|
- m.mode = ModeConfigServer
|
|
|
|
|
|
|
+ sf.mode = ModeConfigServer
|
|
|
|
|
+ case "2": // Вход на сервер
|
|
|
|
|
+ sf.mode = ModeConnectServer
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
case ModeConfigServer:
|
|
case ModeConfigServer:
|
|
@@ -129,13 +141,20 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
// Может клавиша нажата
|
|
// Может клавиша нажата
|
|
|
case tea.KeyMsg:
|
|
case tea.KeyMsg:
|
|
|
switch msg.String() { // Да, нажато, а что именно?
|
|
switch msg.String() { // Да, нажато, а что именно?
|
|
|
- case "ctrl+q": // Надо выйти из программы
|
|
|
|
|
- return m, tea.Quit
|
|
|
|
|
case "q": // Вернуться на шаг назад
|
|
case "q": // Вернуться на шаг назад
|
|
|
- m.mode = ModeConfig
|
|
|
|
|
- case "1": // Выбор один
|
|
|
|
|
- m.mode = ModeInputHostServer
|
|
|
|
|
- m.textInput.Reset()
|
|
|
|
|
|
|
+ sf.mode = ModeConfig
|
|
|
|
|
+ case "1": // Выбор хоста сервера
|
|
|
|
|
+ sf.mode = ModeInputHostServer
|
|
|
|
|
+ sf.textInput.Reset()
|
|
|
|
|
+ sf.textInput.Placeholder = "localhost:18050"
|
|
|
|
|
+ case "2": // Выбор логина для входа
|
|
|
|
|
+ sf.mode = ModeInputLoginServer
|
|
|
|
|
+ sf.textInput.Reset()
|
|
|
|
|
+ sf.textInput.Placeholder = "login"
|
|
|
|
|
+ case "3": // Выбор пароля для входа
|
|
|
|
|
+ sf.mode = ModeInputPassServer
|
|
|
|
|
+ sf.textInput.Reset()
|
|
|
|
|
+ sf.textInput.Placeholder = "pass"
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
case ModeInputHostServer:
|
|
case ModeInputHostServer:
|
|
@@ -143,15 +162,55 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
// Может клавиша нажата
|
|
// Может клавиша нажата
|
|
|
case tea.KeyMsg:
|
|
case tea.KeyMsg:
|
|
|
switch msg.String() { // Да, нажато, а что именно?
|
|
switch msg.String() { // Да, нажато, а что именно?
|
|
|
- case "ctrl+q": // Надо выйти из программы
|
|
|
|
|
- return m, tea.Quit
|
|
|
|
|
case "q": // Вернуться на шаг назад
|
|
case "q": // Вернуться на шаг назад
|
|
|
- m.mode = ModeConfigServer
|
|
|
|
|
|
|
+ sf.mode = ModeConfigServer
|
|
|
|
|
+ case "enter": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
|
|
|
|
|
+ sf.host = sf.textInput.Value()
|
|
|
|
|
+ sf.mode = ModeConfigServer
|
|
|
|
|
+ default:
|
|
|
|
|
+ sf.textInput, cmd = sf.textInput.Update(msg)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ case ModeInputLoginServer:
|
|
|
|
|
+ switch msg := msg.(type) {
|
|
|
|
|
+ // Может клавиша нажата
|
|
|
|
|
+ case tea.KeyMsg:
|
|
|
|
|
+ switch msg.String() { // Да, нажато, а что именно?
|
|
|
|
|
+ case "q": // Вернуться на шаг назад
|
|
|
|
|
+ sf.mode = ModeConfigServer
|
|
|
case "enter": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
|
|
case "enter": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
|
|
|
- m.host = m.textInput.Value()
|
|
|
|
|
- m.mode = ModeConfigServer
|
|
|
|
|
|
|
+ sf.login = sf.textInput.Value()
|
|
|
|
|
+ sf.mode = ModeConfigServer
|
|
|
default:
|
|
default:
|
|
|
- m.textInput, cmd = m.textInput.Update(msg)
|
|
|
|
|
|
|
+ sf.textInput, cmd = sf.textInput.Update(msg)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ case ModeInputPassServer:
|
|
|
|
|
+ switch msg := msg.(type) {
|
|
|
|
|
+ // Может клавиша нажата
|
|
|
|
|
+ case tea.KeyMsg:
|
|
|
|
|
+ switch msg.String() { // Да, нажато, а что именно?
|
|
|
|
|
+ case "q": // Вернуться на шаг назад
|
|
|
|
|
+ sf.mode = ModeConfigServer
|
|
|
|
|
+ case "enter": // Нажатие "enter" или "пробел" переключает выбранный элемент списка
|
|
|
|
|
+ sf.pass = sf.textInput.Value()
|
|
|
|
|
+ sf.mode = ModeConfigServer
|
|
|
|
|
+ default:
|
|
|
|
|
+ sf.textInput, cmd = sf.textInput.Update(msg)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ case ModeConnectServer:
|
|
|
|
|
+ switch msg := msg.(type) {
|
|
|
|
|
+ // Может клавиша нажата
|
|
|
|
|
+ case tea.KeyMsg:
|
|
|
|
|
+ switch msg.String() { // Да, нажато, а что именно?
|
|
|
|
|
+ case "q": // Вернуться на шаг назад
|
|
|
|
|
+ sf.mode = ModeConfigServer
|
|
|
|
|
+ case "esc": // Нажатие "esc" или "пробел" прекращает подключение к серверу
|
|
|
|
|
+ sf.pass = sf.textInput.Value()
|
|
|
|
|
+ sf.mode = ModeConfigServer
|
|
|
|
|
+ default:
|
|
|
|
|
+ sf.textInput, cmd = sf.textInput.Update(msg)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -159,32 +218,51 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
// Возвращает обновлённую модель дляe Bubble Tea runtime для обработки.
|
|
// Возвращает обновлённую модель дляe Bubble Tea runtime для обработки.
|
|
|
//Здесь команду возвращать надо.
|
|
//Здесь команду возвращать надо.
|
|
|
|
|
|
|
|
- return m, cmd
|
|
|
|
|
|
|
+ return sf, cmd
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (m model) View() string {
|
|
|
|
|
|
|
+func (sf Desktop) View() string {
|
|
|
s := time.Now().Local().Format("[ WarTank ] = 2006-01-02 15:04:05.000")
|
|
s := time.Now().Local().Format("[ WarTank ] = 2006-01-02 15:04:05.000")
|
|
|
- s += fmt.Sprintf("\tХост=%q\n\n", m.host)
|
|
|
|
|
- switch m.mode {
|
|
|
|
|
|
|
+ s += fmt.Sprintf("\tХост=%q\tЛогин=%q\tПароль=%q\n\n", sf.host, sf.login, sf.pass)
|
|
|
|
|
+ switch sf.mode {
|
|
|
case ModeDefault: // Исходное содержимое
|
|
case ModeDefault: // Исходное содержимое
|
|
|
- s += m.win1()
|
|
|
|
|
|
|
+ s += sf.winDefault()
|
|
|
case ModeConfig: // Показать настройки клиента
|
|
case ModeConfig: // Показать настройки клиента
|
|
|
- s += m.win2()
|
|
|
|
|
|
|
+ s += sf.winConfig()
|
|
|
case ModeConfigServer: // Конфигурация сервера
|
|
case ModeConfigServer: // Конфигурация сервера
|
|
|
- s += m.win3()
|
|
|
|
|
|
|
+ s += sf.winConfigServer()
|
|
|
case ModeInputHostServer: // Ввод хоста для сервера
|
|
case ModeInputHostServer: // Ввод хоста для сервера
|
|
|
- s += m.win4()
|
|
|
|
|
|
|
+ s += sf.winHostServer()
|
|
|
|
|
+ case ModeInputLoginServer: // Ввод логина для входа на сервер
|
|
|
|
|
+ s += sf.winLoginServer()
|
|
|
|
|
+ case ModeInputPassServer: // ввод пароля
|
|
|
|
|
+ s += sf.winPassServer()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return s
|
|
return s
|
|
|
}
|
|
}
|
|
|
-func (m model) win4() string {
|
|
|
|
|
|
|
+
|
|
|
|
|
+func (sf Desktop) winPassServer() string {
|
|
|
|
|
+ s := "=Ввод пароля для сервера вар-танк=\n\n"
|
|
|
|
|
+ s += fmt.Sprintf(">%v\n", sf.textInput.View())
|
|
|
|
|
+ s += "\n\n[ctrl+q]-выход [q]-назад\n"
|
|
|
|
|
+ return s
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (sf Desktop) winLoginServer() string {
|
|
|
|
|
+ s := "=Ввод логина для сервера вар-танк=\n\n"
|
|
|
|
|
+ s += fmt.Sprintf(">%v\n", sf.textInput.View())
|
|
|
|
|
+ s += "\n\n[ctrl+q]-выход [q]-назад\n"
|
|
|
|
|
+ return s
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (sf Desktop) winHostServer() string {
|
|
|
s := "=Ввод хоста для сервера вар-танк=\n\n"
|
|
s := "=Ввод хоста для сервера вар-танк=\n\n"
|
|
|
- s += fmt.Sprintf(">%v\n", m.textInput.View())
|
|
|
|
|
|
|
+ s += fmt.Sprintf(">%v\n", sf.textInput.View())
|
|
|
s += "\n\n[ctrl+q]-выход [q]-назад\n"
|
|
s += "\n\n[ctrl+q]-выход [q]-назад\n"
|
|
|
return s
|
|
return s
|
|
|
}
|
|
}
|
|
|
-func (m model) win3() string {
|
|
|
|
|
|
|
+func (sf Desktop) winConfigServer() string {
|
|
|
s := "Настройки сервера вар-танк\n\n"
|
|
s := "Настройки сервера вар-танк\n\n"
|
|
|
s += "[1]-Настройки хоста сервера\n"
|
|
s += "[1]-Настройки хоста сервера\n"
|
|
|
s += "[2]-Логин для входа\n"
|
|
s += "[2]-Логин для входа\n"
|
|
@@ -193,14 +271,15 @@ func (m model) win3() string {
|
|
|
return s
|
|
return s
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (m model) win2() string {
|
|
|
|
|
|
|
+func (m TeaModel) winConfig() string {
|
|
|
s := "Настройки клиента\n\n"
|
|
s := "Настройки клиента\n\n"
|
|
|
s += "[1]-Настройки сервера\n"
|
|
s += "[1]-Настройки сервера\n"
|
|
|
|
|
+ s += "[2]-Вход на сервер\n"
|
|
|
s += "\n\n[ctrl+q]-выход [q]-назад\n"
|
|
s += "\n\n[ctrl+q]-выход [q]-назад\n"
|
|
|
return s
|
|
return s
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (m model) win1() string {
|
|
|
|
|
|
|
+func (m TeaModel) winDefault() string {
|
|
|
// Заголовок
|
|
// Заголовок
|
|
|
s := "Что нам нужно сделать?\n\n"
|
|
s := "Что нам нужно сделать?\n\n"
|
|
|
|
|
|