mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
When there are lot of events, the content in teh widget is hidden and there is no way to view the upcoming events. Making the widget focussable allows for one to scroll through the list of calendar events using the arrow keys
239 lines
5.2 KiB
Go
239 lines
5.2 KiB
Go
package gcal
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/senorprogrammer/wtf/wtf"
|
|
)
|
|
|
|
func (widget *Widget) sortedEvents() ([]*CalEvent, []*CalEvent) {
|
|
allDayEvents := []*CalEvent{}
|
|
timedEvents := []*CalEvent{}
|
|
|
|
for _, calEvent := range widget.calEvents {
|
|
if calEvent.AllDay() {
|
|
allDayEvents = append(allDayEvents, calEvent)
|
|
} else {
|
|
timedEvents = append(timedEvents, calEvent)
|
|
}
|
|
}
|
|
|
|
return allDayEvents, timedEvents
|
|
}
|
|
|
|
func (widget *Widget) display() {
|
|
if widget.calEvents == nil || len(widget.calEvents) == 0 {
|
|
return
|
|
}
|
|
|
|
widget.mutex.Lock()
|
|
defer widget.mutex.Unlock()
|
|
|
|
_, timedEvents := widget.sortedEvents()
|
|
widget.View.SetTitle(widget.ContextualTitle(widget.Name))
|
|
widget.View.SetText(widget.contentFrom(timedEvents))
|
|
}
|
|
|
|
func (widget *Widget) contentFrom(calEvents []*CalEvent) string {
|
|
if (calEvents == nil) || (len(calEvents) == 0) {
|
|
return ""
|
|
}
|
|
|
|
var str string
|
|
var prevEvent *CalEvent
|
|
|
|
if !wtf.Config.UBool("wtf.mods.gcal.showDeclined", false) {
|
|
calEvents = removeDeclined(calEvents)
|
|
}
|
|
|
|
for _, calEvent := range calEvents {
|
|
timestamp := fmt.Sprintf("[%s]%s", widget.descriptionColor(calEvent), calEvent.Timestamp())
|
|
|
|
title := fmt.Sprintf("[%s]%s",
|
|
widget.titleColor(calEvent),
|
|
widget.eventSummary(calEvent, calEvent.ConflictsWith(calEvents)),
|
|
)
|
|
|
|
lineOne := fmt.Sprintf(
|
|
"%s %s %s %s[white]\n",
|
|
widget.dayDivider(calEvent, prevEvent),
|
|
widget.responseIcon(calEvent),
|
|
timestamp,
|
|
title,
|
|
)
|
|
|
|
str = str + fmt.Sprintf("%s %s%s\n",
|
|
lineOne,
|
|
widget.location(calEvent),
|
|
widget.timeUntil(calEvent),
|
|
)
|
|
|
|
if (widget.location(calEvent) != "") || (widget.timeUntil(calEvent) != "") {
|
|
str = str + "\n"
|
|
}
|
|
|
|
prevEvent = calEvent
|
|
}
|
|
|
|
return str
|
|
}
|
|
|
|
func (widget *Widget) dayDivider(event, prevEvent *CalEvent) string {
|
|
var prevStartTime time.Time
|
|
|
|
if prevEvent != nil {
|
|
prevStartTime = prevEvent.Start()
|
|
}
|
|
|
|
// round times to midnight for comparison
|
|
toMidnight := func(t time.Time) time.Time {
|
|
t = t.Local()
|
|
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
|
|
}
|
|
prevStartDay := toMidnight(prevStartTime)
|
|
eventStartDay := toMidnight(event.Start())
|
|
|
|
if !eventStartDay.Equal(prevStartDay) {
|
|
|
|
return fmt.Sprintf("[%s::b]",
|
|
wtf.Config.UString("wtf.mods.gcal.colors.day", "forestgreen")) +
|
|
event.Start().Format(wtf.FullDateFormat) +
|
|
"\n"
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func (widget *Widget) descriptionColor(calEvent *CalEvent) string {
|
|
if calEvent.Past() {
|
|
return wtf.Config.UString("wtf.mods.gcal.colors.past", "gray")
|
|
}
|
|
|
|
return wtf.Config.UString("wtf.mods.gcal.colors.description", "white")
|
|
}
|
|
|
|
func (widget *Widget) eventSummary(calEvent *CalEvent, conflict bool) string {
|
|
summary := calEvent.event.Summary
|
|
|
|
if calEvent.Now() {
|
|
summary = fmt.Sprintf(
|
|
"%s %s",
|
|
wtf.Config.UString("wtf.mods.gcal.currentIcon", "🔸"),
|
|
summary,
|
|
)
|
|
}
|
|
|
|
if conflict {
|
|
return fmt.Sprintf("%s %s", wtf.Config.UString("wtf.mods.gcal.conflictIcon", "🚨"), summary)
|
|
}
|
|
|
|
return summary
|
|
}
|
|
|
|
// timeUntil returns the number of hours or days until the event
|
|
// If the event is in the past, returns nil
|
|
func (widget *Widget) timeUntil(calEvent *CalEvent) string {
|
|
duration := time.Until(calEvent.Start()).Round(time.Minute)
|
|
|
|
if duration < 0 {
|
|
return ""
|
|
}
|
|
|
|
days := duration / (24 * time.Hour)
|
|
duration -= days * (24 * time.Hour)
|
|
|
|
hours := duration / time.Hour
|
|
duration -= hours * time.Hour
|
|
|
|
mins := duration / time.Minute
|
|
|
|
untilStr := ""
|
|
|
|
color := "[lightblue]"
|
|
if days > 0 {
|
|
untilStr = fmt.Sprintf("%dd", days)
|
|
} else if hours > 0 {
|
|
untilStr = fmt.Sprintf("%dh", hours)
|
|
} else {
|
|
untilStr = fmt.Sprintf("%dm", mins)
|
|
if mins < 30 {
|
|
color = "[red]"
|
|
}
|
|
}
|
|
|
|
return color + untilStr + "[white]"
|
|
}
|
|
|
|
func (widget *Widget) titleColor(calEvent *CalEvent) string {
|
|
color := wtf.Config.UString("wtf.mods.gcal.colors.title", "white")
|
|
|
|
for _, untypedArr := range wtf.Config.UList("wtf.mods.gcal.colors.highlights") {
|
|
highlightElements := wtf.ToStrs(untypedArr.([]interface{}))
|
|
|
|
match, _ := regexp.MatchString(
|
|
strings.ToLower(highlightElements[0]),
|
|
strings.ToLower(calEvent.event.Summary),
|
|
)
|
|
|
|
if match == true {
|
|
color = highlightElements[1]
|
|
}
|
|
}
|
|
|
|
if calEvent.Past() {
|
|
color = wtf.Config.UString("wtf.mods.gcal.colors.past", "gray")
|
|
}
|
|
|
|
return color
|
|
}
|
|
|
|
func (widget *Widget) location(calEvent *CalEvent) string {
|
|
if wtf.Config.UBool("wtf.mods.gcal.displayLocation", true) == false {
|
|
return ""
|
|
}
|
|
|
|
if calEvent.event.Location == "" {
|
|
return ""
|
|
}
|
|
|
|
return fmt.Sprintf(
|
|
"[%s]%s ",
|
|
widget.descriptionColor(calEvent),
|
|
calEvent.event.Location,
|
|
)
|
|
}
|
|
|
|
func (widget *Widget) responseIcon(calEvent *CalEvent) string {
|
|
if false == wtf.Config.UBool("wtf.mods.gcal.displayResponseStatus", true) {
|
|
return ""
|
|
}
|
|
|
|
icon := "[gray]"
|
|
|
|
switch calEvent.ResponseFor(wtf.Config.UString("wtf.mods.gcal.email")) {
|
|
case "accepted":
|
|
return icon + "✔︎"
|
|
case "declined":
|
|
return icon + "✘"
|
|
case "needsAction":
|
|
return icon + "?"
|
|
case "tentative":
|
|
return icon + "~"
|
|
default:
|
|
return icon + " "
|
|
}
|
|
}
|
|
|
|
func removeDeclined(events []*CalEvent) []*CalEvent {
|
|
var ret []*CalEvent
|
|
for _, e := range events {
|
|
if e.ResponseFor(wtf.Config.UString("wtf.mods.gcal.email")) != "declined" {
|
|
ret = append(ret, e)
|
|
}
|
|
}
|
|
return ret
|
|
}
|