package main import ( // "errors" "github.com/charmbracelet/bubbles/list" "github.com/emersion/go-ical" "strings" "time" "sort" "fmt" "strconv" "github.com/charmbracelet/lipgloss" ) type TODO ical.Event func (i TODO) Title() string { priority := "? " prioInt, err := i.Props.Get("PRIORITY").Int() var prioStr string if err != nil { prioStr, err = i.Props.Get("PRIORITY").Text() if err == nil { prioInt, err = strconv.Atoi(prioStr) } } if err == nil { switch prioInt{ case 9: priority = "" //Low - Blue case 5: priority = "❕ " //Mid - Yellow case 1: priority = "❗ " //High - Red } } time1, err := i.Props.DateTime("DUE",nil) // today := time.Now().Truncate(24 * time.Hour) var dueTime,additionalZero string if (time1.Hour() != 0) || (time1.Minute() != 0) { if time1.Minute() <=9 { additionalZero = "0" } dueTime = fmt.Sprint(time1.Hour())+":"+additionalZero+fmt.Sprint(time1.Minute()) + " " //TODO move to sprintf // if time1.Minute() == 0 { // dueTime += "0 " // } else {dueTime += " "} } // timer, err := i.Props.Get("DUE").Int() //TODO // currentDUE = currentDUE.Add(time.Hour * time.Duration(offset)) //TODO if both times exists // if // timer+"->"+dueTime +" |" out, err := i.Props.Get(ical.PropSummary).Text() if err != nil { return "" } return priority + dueTime + out } func (i TODO) UID() string { out, err := i.Props.Get(ical.PropUID).Text() if err != nil { return "" } return out } func (i TODO) PriorityColor() lipgloss.Color { clr, err := i.Props.Get("PRIORITY").Int() c := lipgloss.Color("255") //White if err != nil { return c } switch clr{ case 9: c = lipgloss.Color("27") //Blue case 5: c = lipgloss.Color("220") //Yellow case 1: // c = lipgloss.Color("#FF9999") //Red c = lipgloss.Color("161") //Red } return c } func (i TODO) Description() string { out, err := i.Props.Get(ical.PropDescription).Text() if err != nil { return "" } return out } func (i TODO) FilterValue() string { // index out1, err1 := i.Props.Get(ical.PropSummary).Text() out2, err2 := i.Props.Get(ical.PropDescription).Text() if err1 != nil && err2 != nil { return "" } return out1 + out2 } // type itemDelegate struct{} // // func (d itemDelegate) Height() int { return 1 } // func (d itemDelegate) Spacing() int { return 0 } // func (d itemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil } // func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { // i, ok := listItem.(item) // if !ok { // return // } // // str := fmt.Sprintf("%d. %s", index+1, i) // // fn := itemStyle.Render // if index == m.Index() { // fn = func(s string) string { // return selectedItemStyle.Render("> " + s) // } // } // // fmt.Fprintf(w, fn(str)) // } func (m *model) GatherTodos() (err error) { //TODO more modular approach m.CalObjects, err = GetTODOs(m.Creds.CalendarPath) if err != nil { return } calendarObjects := m.CalObjects //TODO rm me // var todayTodos []TODO today := time.Now() todayTodosBuf, err := ParseDueDateTODOs(calendarObjects, today) // if err != nil { // return // } tomorrow := time.Now().AddDate(0, 0, 1) tomorrowTodosBuf, err := ParseDueDateTODOs(calendarObjects, tomorrow) // if err != nil { // return // } todayTodosBuf,err = SortTodos_Default(todayTodosBuf) // if err != nil { // return // } tomorrowTodosBuf,err = SortTodos_Default(tomorrowTodosBuf) // if err != nil { // return // } //TODO fmt - we can combine things below var todayTodos, tomorrowTodos []TODO for _, event := range todayTodosBuf { todayTodos = append(todayTodos, TODO(event)) } for _, event := range tomorrowTodosBuf { tomorrowTodos = append(tomorrowTodos, TODO(event)) } var itemsToday []list.Item var itemsTomorrow []list.Item for _, todo := range todayTodos { itemsToday = append(itemsToday, todo) } for _, todo := range tomorrowTodos { itemsTomorrow = append(itemsTomorrow, todo) } delegateKeys := newDelegateKeyMap() delegate := m.newItemDelegate(delegateKeys) // m.TodayTab = list.New(itemsToday, list.NewDefaultDelegate(), 0, 0) m.TodayTab = list.New(itemsToday, delegate, 0, 0) m.TodayTab.FilterInput.Reset() //TODO debug // m.TodayTab.Title = "Today" // m.TodayTab.SetShowStatusBar(false) // m.TodayTab.SetFilteringEnabled(false) // m.TodayTab.Styles.Title = titleStyle // m.TodayTab.Styles.PaginationStyle = paginationStyle // m.TodayTab.Styles.HelpStyle = helpStyle // m.TomorrowTab = list.New(itemsTomorrow, list.NewDefaultDelegate(), 0, 0) m.TomorrowTab = list.New(itemsTomorrow, delegate, 0, 0) m.TodayTab.FilterInput.Reset()//TODO debug m.TomorrowTab.Title = "Tomorrow" // m.TomorrowTab.SetShowStatusBar(false) // m.TomorrowTab.SetFilteringEnabled(false) // m.TomorrowTab.Styles.Title = titleStyle // m.TomorrowTab.Styles.PaginationStyle = paginationStyle // m.TomorrowTab.Styles.HelpStyle = helpStyle return nil } //for sorting type ByTime []ical.Event func (a ByTime) Len() int { return len(a) } func (a ByTime) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByTime) Less(i, j int) bool { time1,_ := a[i].Props.DateTime("DUE",nil) //TODO is there better way? // if time1.Hour() == 0 || time1.Minute() == 0 { // time1 = time.Date(time1.Year(), time1.Month(), time1.Day(), 23, 59, 0, 0, time.UTC) // } // timeInt1,_ := strconv.Atoi(fmt.Sprint("%d%d",time1.Hour(),time1.Minute())) s1:=fmt.Sprintf("%d%d",time1.Hour(),time1.Minute()) time2,_ := a[j].Props.DateTime("DUE",nil) // timeInt2,_ := strconv.Atoi(fmt.Sprint("%d%d",time2.Hour(),time2.Minute())) s2 := fmt.Sprintf("%d%d",time2.Hour(),time2.Minute()) timeInt1, _ := strconv.Atoi(s1) timeInt2, _ := strconv.Atoi(s2) if timeInt1 == 0 { timeInt1 = 9999 } if timeInt2 == 0 { timeInt2 = 9999 } // if time2.Hour() == 0 || time2.Minute() == 0 { // time2 = time.Date(time2.Year(), time2.Month(), time2.Day(), 23, 59, 0, 0, time.UTC) // } // return time2.After(time1) return timeInt1