273 lines
5.7 KiB
Go
273 lines
5.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
beryl "codeberg.org/beryl/go"
|
|
"github.com/google/uuid"
|
|
"golang.org/x/exp/slices"
|
|
)
|
|
|
|
type TaskView struct {
|
|
ID uuid.UUID
|
|
Task *beryl.Task
|
|
Parent *TaskView
|
|
Children []*TaskView
|
|
Expanded bool
|
|
}
|
|
|
|
func (taskv *TaskView) Delete(m model) *TaskView {
|
|
parent := taskv.Parent
|
|
idx := taskv.GetIDX()
|
|
if parent == nil {
|
|
return taskv
|
|
}
|
|
|
|
if parent.ID == m.taskView.ID {
|
|
parent = m.taskView
|
|
}
|
|
|
|
// delete task with same idx in parent task
|
|
if parent.Task != nil {
|
|
parent.Task.SubTasks = append(parent.Task.SubTasks[:idx], parent.Task.SubTasks[idx+1:]...)
|
|
}
|
|
// delete taskv with idx
|
|
parent.Children = append(parent.Children[:idx], parent.Children[idx+1:]...)
|
|
// return pointer of current idx
|
|
|
|
newCount := len(parent.Children)
|
|
|
|
if newCount == 0 {
|
|
return parent
|
|
}
|
|
if newCount == 1 {
|
|
return parent.Children[0]
|
|
}
|
|
|
|
if idx == 0 {
|
|
return parent.Children[idx]
|
|
}
|
|
return parent.Children[idx-1]
|
|
}
|
|
|
|
func (taskv *TaskView) AddSubtask() *TaskView {
|
|
newTask := beryl.Task{}
|
|
newTaskv := TaskView{
|
|
ID: uuid.New(),
|
|
Task: &newTask,
|
|
Parent: taskv,
|
|
}
|
|
taskv.Task.SubTasks = append(taskv.Task.SubTasks, &newTask)
|
|
taskv.Children = append(taskv.Children, &newTaskv)
|
|
|
|
return &newTaskv
|
|
|
|
}
|
|
|
|
func (taskv *TaskView) AddSibling() *TaskView {
|
|
idx := taskv.GetIDX()
|
|
|
|
//create actual task
|
|
newTask := beryl.Task{}
|
|
newTaskv := TaskView{
|
|
ID: uuid.New(),
|
|
Task: &newTask,
|
|
Parent: taskv.Parent,
|
|
}
|
|
if taskv.Parent.Task != nil {
|
|
// taskv.Parent.Task.SubTasks = append(taskv.Parent.Task.SubTasks, &newTask)
|
|
taskv.Parent.Task.SubTasks = append(taskv.Parent.Task.SubTasks[:idx+1], taskv.Parent.Task.SubTasks[idx:]...)
|
|
taskv.Parent.Task.SubTasks[idx] = &newTask
|
|
}
|
|
|
|
// get slice before idx, and after idx
|
|
// taskv.Parent.Children = append(taskv.Parent.Children, &newTaskv)
|
|
taskv.Parent.Children = append(taskv.Parent.Children[:idx+1], taskv.Parent.Children[idx:]...)
|
|
taskv.Parent.Children[idx] = &newTaskv
|
|
return &newTaskv
|
|
|
|
}
|
|
|
|
func (taskv TaskView) DownLast() *TaskView {
|
|
//check for children
|
|
// if none or collapsed return
|
|
|
|
numChildren := len(taskv.Children)
|
|
if !taskv.Expanded || numChildren == 0 {
|
|
return &taskv
|
|
}
|
|
|
|
// get last child
|
|
lastChild := taskv.Children[numChildren-1]
|
|
|
|
// return recurse on that child
|
|
return lastChild.DownLast()
|
|
}
|
|
|
|
func (taskv TaskView) GetLast() *TaskView {
|
|
parent := taskv.Parent
|
|
idx := taskv.GetIDX()
|
|
if parent.Parent == nil && idx == 0 {
|
|
return &taskv
|
|
}
|
|
|
|
//are we the 0th tast? return
|
|
if idx == 0 {
|
|
return taskv.Parent
|
|
}
|
|
|
|
// get task above
|
|
aboveSibling := parent.Children[idx-1]
|
|
|
|
// if not expanded, return it
|
|
if !aboveSibling.Expanded {
|
|
return aboveSibling
|
|
}
|
|
|
|
// count children
|
|
aboveChildren := len(aboveSibling.Children)
|
|
|
|
// if none, return it
|
|
if aboveChildren == 0 {
|
|
return aboveSibling
|
|
}
|
|
|
|
// call get last on it
|
|
return aboveSibling.Children[aboveChildren-1].DownLast()
|
|
}
|
|
|
|
func (taskv *TaskView) UpNext() *TaskView {
|
|
// get parent
|
|
parent := taskv.Parent
|
|
|
|
if parent == nil {
|
|
//taskv is the root task, just return the last item, we're not supposed to get all the way up here
|
|
// this should probably just return the actual final thing
|
|
return taskv.Children[len(taskv.Children)-1]
|
|
// return nil
|
|
}
|
|
// get current idx
|
|
idx := taskv.GetIDX()
|
|
// get parent children length
|
|
siblings := len(parent.Children)
|
|
// check if parent has a next child
|
|
if siblings > idx+1 {
|
|
return parent.Children[idx+1]
|
|
} else {
|
|
return parent.UpNext()
|
|
}
|
|
}
|
|
|
|
func (taskv *TaskView) GetNext() *TaskView {
|
|
if taskv.Expanded && len(taskv.Children) > 0 {
|
|
return taskv.Children[0]
|
|
}
|
|
|
|
idx := taskv.GetIDX()
|
|
length := len(taskv.Parent.Children)
|
|
if length > idx+1 {
|
|
return taskv.Parent.Children[idx+1]
|
|
}
|
|
|
|
// if the last item in arr
|
|
if length == idx+1 {
|
|
result := taskv.UpNext()
|
|
if result == nil {
|
|
return taskv
|
|
} else {
|
|
return result
|
|
}
|
|
}
|
|
// recursivly look up the parent tree to see if there is ever another sibling
|
|
return taskv
|
|
}
|
|
|
|
func (taskv TaskView) GetIDX() int {
|
|
return slices.IndexFunc(taskv.Parent.Children, func(c *TaskView) bool { return c.ID == taskv.ID })
|
|
}
|
|
|
|
func BuildRootViewTree(tasks []*beryl.Task) *TaskView {
|
|
tree := TaskView{}
|
|
// root
|
|
tree.Children = BuildViewTree(tasks, &tree)
|
|
|
|
// for _, child := tree.Children {
|
|
// tree.
|
|
// }
|
|
return &tree
|
|
}
|
|
|
|
func BuildViewTree(tasks []*beryl.Task, parent *TaskView) []*TaskView {
|
|
tree := []*TaskView{}
|
|
for _, task := range tasks {
|
|
newView := TaskView{
|
|
ID: uuid.New(),
|
|
Task: task,
|
|
Parent: parent,
|
|
Expanded: true,
|
|
}
|
|
children := BuildViewTree(task.SubTasks, &newView)
|
|
newView.Children = children
|
|
tree = append(tree, &newView)
|
|
}
|
|
|
|
return tree
|
|
|
|
}
|
|
|
|
// todo: what does move up and down mean in the context of subtask?
|
|
// func moveUp(arr []TaskView, i int) []TaskView {
|
|
// temp := arr[i]
|
|
// arr[i] = arr[i-1]
|
|
// arr[i-1] = temp
|
|
// return arr
|
|
// }
|
|
//
|
|
// func moveDown(arr []*beryl.Task, i int) []*beryl.Task {
|
|
// temp := arr[i]
|
|
// arr[i] = arr[i+1]
|
|
// arr[i+1] = temp
|
|
// return arr
|
|
// }
|
|
|
|
func FormatTask(m model, choice *TaskView, i int) string {
|
|
|
|
s := ""
|
|
|
|
cursor := "-" // no cursor
|
|
if m.cursor.ID == choice.ID {
|
|
cursor = ">" // cursor!
|
|
}
|
|
|
|
checked := " " // not selected
|
|
if choice.Task.Completed {
|
|
checked = "x" // selected!
|
|
}
|
|
|
|
if choice.ID == m.cursor.ID && m.isEditing {
|
|
s += fmt.Sprintf("%s [%s] ", cursor, checked)
|
|
s += m.editing.View()
|
|
|
|
} else {
|
|
s += fmt.Sprintf("%s [%s] %s", cursor, checked, choice.Task.Title)
|
|
}
|
|
|
|
// s += fmt.Sprintf(" me:%p p:%p", choice, choice.Parent)
|
|
|
|
s += "\n"
|
|
|
|
if choice.Expanded {
|
|
subString := ""
|
|
for _, choice2 := range choice.Children {
|
|
subString += FormatTask(m, choice2, -1)
|
|
}
|
|
|
|
subString = strings.Replace(subString, "- [", "\t- [", -1)
|
|
subString = strings.Replace(subString, "> [", "\t> [", -1)
|
|
s += subString
|
|
}
|
|
|
|
return s
|
|
}
|