Skip to content

Commit

Permalink
Update GCal module's "time until event" text more frequently
Browse files Browse the repository at this point in the history
While it's reasonable to have a refresh interval of several minutes
between the GCal module hitting the server, the fact that the module
(helpfully) displays the time until an event means that as times
approach zero, they become relatively inaccurate - "3m" might show
up next to a meeting that you were supposed to be in 2 minutes ago.
(don't worry, that hasn't happened to me yet)

This change introduces a goroutine to the GCal module that will
update the module text using the most recently cached copy of
events. By default, it runs every 30 seconds (this could be changed
to 0 to make it opt-in if desired) or however many seconds is
specified by the new config option `wtf.mods.gcal.textInterval`.

To make sure the goroutine doesn't cause any synchronization issues
if a text update were to trigger at the same time as a module
refresh, this change also adds the use of `sync.Mutex` to gate
setting GCal's text. Since both mutexes and having a goroutine within
individual modules are not the sort of thing any other code in
`wtf` does at this point in time, I'm definitely open to feedback
on whether there might be better ways to do this.

Additionally, the change in `wtf.go` fixes an issue I noticed when
testing if my `Disable()` function worked - the main `Widgets`
array wasn't being cleared out after disabling all widgets before
re-creating new copies of them, so it still held pointers to the
old ones.
  • Loading branch information
baustinanki committed Jun 19, 2018
1 parent 8a0ace3 commit 1077adb
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
45 changes: 43 additions & 2 deletions gcal/widget.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"regexp"
"strings"
"sync"
"time"

"github.com/senorprogrammer/wtf/wtf"
Expand All @@ -12,28 +13,47 @@ import (

type Widget struct {
wtf.TextWidget

events *calendar.Events
ch chan struct{}
mutex sync.Mutex
}

func NewWidget() *Widget {
widget := Widget{
TextWidget: wtf.NewTextWidget(" Calendar ", "gcal", false),
ch: make(chan struct{}),
}

go updateLoop(&widget)

return &widget
}

/* -------------------- Exported Functions -------------------- */

func (widget *Widget) Refresh() {
events, _ := Fetch()
widget.events = events

widget.UpdateRefreshedAt()

widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(events)))
widget.display()
}

func (widget *Widget) Disable() {
close(widget.ch)
widget.TextWidget.Disable()
}

/* -------------------- Unexported Functions -------------------- */

func (widget *Widget) display() {
widget.mutex.Lock()
defer widget.mutex.Unlock()
widget.View.SetText(fmt.Sprintf("%s", widget.contentFrom(widget.events)))
}

// conflicts returns TRUE if this event conflicts with another, FALSE if it does not
func (widget *Widget) conflicts(event *calendar.Event, events *calendar.Events) bool {
conflict := false
Expand Down Expand Up @@ -135,7 +155,7 @@ func (widget *Widget) eventTimestamp(event *calendar.Event) string {
} else {
startTime, _ := time.Parse(time.RFC3339, event.Start.DateTime)
return startTime.Format(wtf.FriendlyDateTimeFormat)
}
}
}

// eventIsNow returns true if the event is happening now, false if it not
Expand Down Expand Up @@ -254,3 +274,24 @@ func (widget *Widget) until(event *calendar.Event) string {

return "[lightblue]" + untilStr + "[white]"
}

func updateLoop(widget *Widget) {
interval := wtf.Config.UInt("wtf.mods.gcal.textInterval", 30)
if interval == 0 {
return
}

tick := time.NewTicker(time.Duration(interval) * time.Second)
defer tick.Stop()
outer:
for {
select {
case <-tick.C:
if widget.events != nil && len(widget.events.Items) > 0 {
widget.display()
}
case <-widget.ch:
break outer
}
}
}
1 change: 1 addition & 0 deletions wtf.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ func watchForConfigChanges(app *tview.Application, configFilePath string, grid *
loadConfigFile(configFilePath)
// Disable all widgets to stop scheduler goroutines and rmeove widgets from memory.
disableAllWidgets()
Widgets = nil
makeWidgets(app, pages)
initializeFocusTracker(app)
display := wtf.NewDisplay(Widgets)
Expand Down

0 comments on commit 1077adb

Please sign in to comment.