1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00
wtf/gcal/display.go
Anand Sudhir Prayaga 8f4c53d58a Make google calendar focussable
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
2018-08-22 13:47:44 +02:00

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
}