github.com/wtfutil/wtf@v0.43.0/modules/gcal/display.go (about) 1 package gcal 2 3 import ( 4 "fmt" 5 "regexp" 6 "strings" 7 "time" 8 9 "github.com/wtfutil/wtf/utils" 10 ) 11 12 func (widget *Widget) display() { 13 widget.Redraw(widget.content) 14 } 15 16 func (widget *Widget) content() (string, string, bool) { 17 title := widget.settings.Title 18 calEvents := widget.calEvents 19 20 if widget.err != nil { 21 return title, widget.err.Error(), true 22 } 23 24 if (calEvents == nil) || (len(calEvents) == 0) { 25 return title, "No calendar events", false 26 } 27 28 var str string 29 var prevEvent *CalEvent 30 31 if !widget.settings.showDeclined { 32 calEvents = widget.removeDeclined(calEvents) 33 } 34 35 for _, calEvent := range calEvents { 36 if calEvent.AllDay() && !widget.settings.showAllDay { 37 continue 38 } 39 40 ts := calEvent.Timestamp(widget.settings.hourFormat, widget.settings.showEndTime) 41 timestamp := fmt.Sprintf("[%s]%s", widget.eventTimeColor(), ts) 42 if calEvent.AllDay() { 43 timestamp = "" 44 } 45 46 eventTitle := fmt.Sprintf("[%s]%s", 47 widget.titleColor(calEvent), 48 widget.eventSummary(calEvent, calEvent.ConflictsWith(calEvents)), 49 ) 50 51 lineOne := fmt.Sprintf( 52 "%s %s %s %s[white]\n", 53 widget.dayDivider(calEvent, prevEvent), 54 widget.responseIcon(calEvent), 55 timestamp, 56 eventTitle, 57 ) 58 59 str += fmt.Sprintf("%s %s%s\n", 60 lineOne, 61 widget.location(calEvent), 62 widget.timeUntil(calEvent), 63 ) 64 65 if (widget.location(calEvent) != "") || (widget.timeUntil(calEvent) != "") { 66 str += "\n" 67 } 68 69 prevEvent = calEvent 70 } 71 72 return title, str, false 73 } 74 75 func (widget *Widget) dayDivider(event, prevEvent *CalEvent) string { 76 var prevStartTime time.Time 77 78 if prevEvent != nil { 79 prevStartTime = prevEvent.Start() 80 } 81 82 // round times to midnight for comparison 83 toMidnight := func(t time.Time) time.Time { 84 t = t.Local() 85 return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) 86 } 87 prevStartDay := toMidnight(prevStartTime) 88 eventStartDay := toMidnight(event.Start()) 89 90 if !eventStartDay.Equal(prevStartDay) { 91 return fmt.Sprintf("[%s]", 92 widget.settings.colors.day) + 93 event.Start().Format(utils.FullDateFormat) + 94 "\n" 95 } 96 97 return "" 98 } 99 100 func (widget *Widget) descriptionColor(calEvent *CalEvent) string { 101 if calEvent.Past() { 102 return widget.settings.colors.past 103 } 104 105 return widget.settings.colors.description 106 } 107 108 func (widget *Widget) eventTimeColor() string { 109 return widget.settings.colors.eventTime 110 } 111 112 func (widget *Widget) eventSummary(calEvent *CalEvent, conflict bool) string { 113 summary := calEvent.event.Summary 114 115 if calEvent.Now() { 116 summary = fmt.Sprintf( 117 "%s %s", 118 widget.settings.currentIcon, 119 summary, 120 ) 121 } 122 123 if conflict { 124 return fmt.Sprintf("%s %s", widget.settings.conflictIcon, summary) 125 } 126 127 return summary 128 } 129 130 // timeUntil returns the number of hours or days until the event 131 // If the event is in the past, returns nil 132 func (widget *Widget) timeUntil(calEvent *CalEvent) string { 133 duration := time.Until(calEvent.Start()).Round(time.Minute) 134 135 if duration < 0 { 136 return "" 137 } 138 139 days := duration / (24 * time.Hour) 140 duration -= days * (24 * time.Hour) 141 142 hours := duration / time.Hour 143 duration -= hours * time.Hour 144 145 mins := duration / time.Minute 146 147 untilStr := "" 148 149 color := "[lightblue]" 150 switch { 151 case days > 0: 152 untilStr = fmt.Sprintf("%dd", days) 153 case hours > 0: 154 untilStr = fmt.Sprintf("%dh", hours) 155 default: 156 untilStr = fmt.Sprintf("%dm", mins) 157 if mins < 30 { 158 color = "[red]" 159 } 160 } 161 162 return color + untilStr + "[white]" 163 } 164 165 func (widget *Widget) titleColor(calEvent *CalEvent) string { 166 color := widget.settings.colors.title 167 168 for _, untypedArr := range widget.settings.colors.highlights { 169 highlightElements := utils.ToStrs(untypedArr.([]interface{})) 170 171 match, _ := regexp.MatchString( 172 strings.ToLower(highlightElements[0]), 173 strings.ToLower(calEvent.event.Summary), 174 ) 175 176 if match { 177 color = highlightElements[1] 178 } 179 } 180 181 if calEvent.Past() { 182 color = widget.settings.colors.past 183 } 184 185 return color 186 } 187 188 func (widget *Widget) location(calEvent *CalEvent) string { 189 if !widget.settings.withLocation { 190 return "" 191 } 192 193 if calEvent.event.Location == "" { 194 return "" 195 } 196 197 return fmt.Sprintf( 198 "[%s]%s ", 199 widget.descriptionColor(calEvent), 200 calEvent.event.Location, 201 ) 202 } 203 204 func (widget *Widget) responseIcon(calEvent *CalEvent) string { 205 if !widget.settings.displayResponseStatus { 206 return "" 207 } 208 209 icon := "[gray]" 210 211 switch calEvent.ResponseFor(widget.settings.email) { 212 case "accepted": 213 return icon + "✔" 214 case "declined": 215 return icon + "✘" 216 case "needsAction": 217 return icon + "?" 218 case "tentative": 219 return icon + "~" 220 default: 221 return icon + " " 222 } 223 } 224 225 func (widget *Widget) removeDeclined(events []*CalEvent) []*CalEvent { 226 var ret []*CalEvent 227 for _, e := range events { 228 if e.ResponseFor(widget.settings.email) != "declined" { 229 ret = append(ret, e) 230 } 231 } 232 return ret 233 }