tui/view.go

220 lines
4.5 KiB
Go

package main
import (
"fmt"
"log"
beryl "codeberg.org/beryl/go"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/google/uuid"
)
// this is where all the bubble tea stuff goes
type model struct {
taskView *TaskView // items on the to-do list
cursor *TaskView // which to-do list item our cursor is pointing at
isEditing bool
editing textinput.Model
isShortcut bool
}
var gm model
func initialModel() model {
ti := textinput.New()
ti.Focus()
ti.CharLimit = 156
ti.Width = 80
rawTasks, err := beryl.LoadFromFilename(fileName)
if err != nil {
log.Fatal(err)
}
//there shoudl be like a root taskview
taskView := BuildRootViewTree(rawTasks)
// log.Println(choices)
gm = model{
taskView: taskView,
cursor: taskView.Children[0],
isEditing: false,
editing: ti,
}
return gm
}
func GetHelp() string {
s := ""
s += "help\n"
s += "arrow keys for navigate\n"
s += "x to toggle task completion\n\n"
s += "e to enter edit mode on a task\n"
s += "while in edit mode:\n"
s += "arrow keys to move a task\n"
s += "enter to save\n"
s += "escape to discard\n"
s += "\nPress q/ESC to return to tasks.\n"
return s
}
func (m model) Init() tea.Cmd {
cmd := tea.EnterAltScreen
return cmd
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
// Is it a key press?
case tea.KeyMsg:
if m.isShortcut {
switch msg.String() {
case "esc", "q":
m.isShortcut = false
}
} else if m.isEditing {
switch msg.String() {
case "enter":
//save
m.cursor.Task.Title = m.editing.Value()
m.isEditing = false
m.editing.SetValue("")
case "esc":
// dont save
m.isEditing = false
m.editing.SetValue("")
// case "up":
// //if already on top
// if m.cursor > 0 {
// //move the actual thing up
// m.taskViews = moveUp(m.taskViews, m.cursor)
// // move the cursor
// m.cursor--
// }
//
// case "down":
// //if already on top
// if m.cursor < len(m.taskViews)-1 {
// //move the actual thing up
// m.taskViews = moveDown(m.taskViews, m.cursor)
// // move the cursor
// m.cursor++
// }
case "ctrl+c":
return m, tea.Quit
}
if m.isEditing {
// var cmd
var cmd tea.Cmd
m.editing, cmd = m.editing.Update(msg)
return m, cmd
}
} else {
switch msg.String() {
case "?":
m.isShortcut = true
case "ctrl+c", "q", "esc":
return m, tea.Quit
case "up", "k":
m.cursor = m.cursor.GetLast()
case "down", "j":
m.cursor = m.cursor.GetNext()
case "e":
m.isEditing = true
m.editing.SetValue(m.cursor.Task.Title)
case "x", " ":
m.cursor.Task.Completed = !m.cursor.Task.Completed
case "c":
// log.Println(m.cursor.Expanded)
m.cursor.Expanded = !m.cursor.Expanded
// works fine, but needs a conf so its d+enter
case "d":
m.cursor = m.cursor.Delete(m)
case "s":
m.cursor.Expanded = true
m.cursor = m.cursor.AddSubtask()
// m.cursor = m.taskView.Children[len(m.taskView.Children)-1]
m.isEditing = true
//todo have better key for sibling
case "p":
m.cursor = m.cursor.AddSibling()
// m.cursor = m.taskView.Children[len(m.taskView.Children)-1]
m.isEditing = true
case "a":
// newTaskView := m.cursor.AddSibling()
// log.Println(len(m.taskView.Children))
// log.Println(m.taskView)
// return m, nil
newTask := beryl.Task{}
newTaskv := TaskView{
ID: uuid.New(),
Task: &newTask,
Parent: m.taskView,
}
m.taskView.Children = append(m.taskView.Children, &newTaskv)
//ok so putting the cursot here makes it attach to the old m taskview children
m.cursor = &newTaskv
m.isEditing = true
// log.Println(len(m.taskView.Children))
}
}
}
// TODO: this should be a command
// https://github.com/charmbracelet/bubbletea/tree/master/tutorials/commands/
tasks := []*beryl.Task{}
for _, taskv := range m.taskView.Children {
tasks = append(tasks, taskv.Task)
}
beryl.WriteToFilename(tasks, fileName)
return m, nil
}
func (m model) View() string {
s := ""
if m.isShortcut {
return GetHelp()
}
s = fmt.Sprintf("%s \n\n", title[0:len(title)-3])
for i, task := range m.taskView.Children {
s += FormatTask(m, task, i)
}
// The footer
if m.isEditing {
s += "\nediting: Press enter to save and ESC to discard\n"
} else {
s += "\nPress q/ESC to quit. Press ? for help.\n"
}
// Send the UI for rendering
return s
}