tempus/tui.go

271 lines
5.9 KiB
Go
Raw Normal View History

2024-06-21 18:38:41 +00:00
package main
import (
"fmt"
// "os"
// "strings"
"github.com/charmbracelet/bubbles/list"
"github.com/charmbracelet/bubbles/textinput"
// textblink "github.com/charmbracelet/bubbles/textinput"
// "github.com/erikgeiser/promptkit/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"golang.org/x/term"
)
var docStyle = lipgloss.NewStyle().Margin(1, 2)
var loginStyle = lipgloss.NewStyle().Width(40).Align(lipgloss.Center).BorderStyle(lipgloss.NormalBorder())
var inputStyle = lipgloss.NewStyle()
func (i TODO) Title() string { return i.Name }
func (i TODO) Description() string { return i.Desc }
func (i TODO) FilterValue() string { return i.Name }
type model struct {
Tabs []string
// TabContent []string
LoggedIn bool
ActiveWindow string
TodayTab list.Model
TomorrowTab list.Model
loginInputs []textinput.Model
focused int
err error
}
func (m model) Init() tea.Cmd {
return textinput.Blink
// return nil
}
const (
url = iota
login
pass
)
//TODO add changing calendar
func InitModel() model {
var inputs []textinput.Model = make([]textinput.Model, 3)
inputs[url] = textinput.New()
inputs[url].Placeholder = "https://nextcloud.example/remote.php/dav"
inputs[url].Focus()
// inputs[url].CharLimit = 20
inputs[url].Width = 30
inputs[url].Prompt = ""
// inputs[url].Validate = urlValidator
inputs[login] = textinput.New()
inputs[login].Placeholder = "username"
// inputs[login].CharLimit = 5
inputs[login].Width = 30
inputs[login].Prompt = ""
// inputs[login].Validate = loginValidator
inputs[pass] = textinput.New()
inputs[pass].Placeholder = "MySecurePassword"
// inputs[pass].CharLimit = 3
inputs[pass].Width = 30
inputs[pass].Prompt = ""
// inputs[pass].Validate = passValidator
output := model{
Tabs: []string{"Today", "Tomorrow", "Add"},
loginInputs: inputs,
focused: 0,
err: nil,
// TabContent: []string{"ERROR?", "Mascara Tab", "Foundation Tab"},
}
return output
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
if m.ActiveWindow == "login" {
switch keypress := msg.String(); keypress {
case "ctrl+c", "q":
return m, tea.Quit
case "enter":
if m.focused == len(m.loginInputs)-1 {
//TODO submit
// try login -> store -> move to getting stuff
return m, tea.Quit
}
m.nextInput()
case "shift+tab", "up":
m.prevInput()
case "tab", "down":
m.nextInput()
}
for i := range m.loginInputs {
m.loginInputs[i].Blur()
}
m.loginInputs[m.focused].Focus()
}
switch keypress := msg.String(); keypress {
case "ctrl+c", "q":
return m, tea.Quit
// case "right", "l", "n", "tab":
//TODO add to help
case "tab":
if m.LoggedIn {
h, v := docStyle.GetFrameSize()
width, height, _ := term.GetSize(0)
switch m.ActiveWindow {
case "today":
m.ActiveWindow = "tomorrow"
m.TomorrowTab.SetSize(width-h, height-v)
case "tomorrow":
m.ActiveWindow = "today"
m.TodayTab.SetSize(width-h, height-v)
}
return m, nil
}
// case "a" {
// TODO add new element
// return m, tea.Quit
// }
case "t":
// TODO add new element
return m, tea.Quit
}
case tea.WindowSizeMsg:
h, v := docStyle.GetFrameSize()
switch m.ActiveWindow {
case "login":
m.TodayTab.SetSize(msg.Width-h, msg.Height-v)
case "today":
m.TodayTab.SetSize(msg.Width-h, msg.Height-v)
case "tomorrow":
m.TomorrowTab.SetSize(msg.Width-h, msg.Height-v)
}
}
var cmd tea.Cmd
// text input
switch m.ActiveWindow {
case "login":
for i := range m.loginInputs {
m.loginInputs[i], cmd = m.loginInputs[i].Update(msg)
}
case "today":
m.TodayTab, cmd = m.TodayTab.Update(msg)
case "tomorrow":
m.TomorrowTab, cmd = m.TomorrowTab.Update(msg)
}
// m.TodayTab, cmd = m.TodayTab.Update(msg)
// m.TomorrowTab, cmd = m.TomorrowTab.Update(msg)
return m, cmd
}
func (m model) View() string {
var tabOutput string
switch m.ActiveWindow {
case "login":
width, height, _ := term.GetSize(0)
width -=2
height -=2
loginStyle = loginStyle.
// Width(30).
// Height(height/5).
MarginTop(height/5).
MarginLeft(width/2-20)
// MarginRight(width/3)
tabOutput = loginStyle.Render(m.RenderLogin())
// w, h := lipgloss.Size(tabOutput)
case "today":
tabOutput = docStyle.Render(m.TodayTab.View())
case "tomorrow":
tabOutput = docStyle.Render(m.TomorrowTab.View())
case "":
width, height, _ := term.GetSize(0)
width -=2
height -=2
loginStyle = loginStyle.
Width(width/3).
Height(1).
MarginTop(height/2).
MarginLeft(width/3+2).
MarginRight(width/3)
tabOutput = loginStyle.Render("ERROR")
}
// if m.activeTab == 0 {
// tabOutput = docStyle.Render(m.TodayTab.View())
// }
// if m.activeTab == 1 {
// tabOutput = docStyle.Render(m.TomorrowTab.View())
// }
return tabOutput
}
func (m model) RenderLogin() string {
return fmt.Sprintf(
`%s
%s
%s
%s
%s
%s
%s
%s
`,
inputStyle.Width(30).Align(lipgloss.Center).Render("Login"),
inputStyle.Width(30).Foreground(lipgloss.AdaptiveColor{Dark: "50"}).Render("WebDAV server URL"),
m.loginInputs[url].View(),
inputStyle.Width(30).Foreground(lipgloss.AdaptiveColor{Dark: "50"}).Render("Login"),
m.loginInputs[login].View(),
inputStyle.Width(30).Foreground(lipgloss.AdaptiveColor{Dark: "50"}).Render("Password"),
m.loginInputs[pass].View(), //TODO hide
inputStyle.Render("Continue ->"),
)
// .Align(lipgloss.Center).BorderStyle(lipgloss.NormalBorder())
}
func (m *model) nextInput() {
m.focused = (m.focused + 1) % len(m.loginInputs)
}
// prevInput focuses the previous input field
func (m *model) prevInput() {
m.focused--
// Wrap around
if m.focused < 0 {
m.focused = len(m.loginInputs) - 1
}
}