Several Updates

* Caching the day's events (for 6 hours)
* Up the Calendar List Cache expiration to a week
* Setting things up for a 'UI' mode
This commit is contained in:
Brian Buller 2017-03-15 14:38:37 -05:00
parent c0412e3208
commit 17cfbbc5fe
7 changed files with 167 additions and 53 deletions

View File

@ -103,19 +103,18 @@ func toggleCalendar(g *gocui.Gui, v *gocui.View) error {
_, cy := v.Cursor() _, cy := v.Cursor()
var removed bool var removed bool
calList := state.account.GetCalendarList() calList := state.account.GetCalendarList()
if v != nil {
for i := range state.defaultCalendars { for i := range state.defaultCalendars {
if state.defaultCalendars[i] == calList[cy].Id { if state.defaultCalendars[i] == calList[cy].Id {
// Remove calendar from defaults // Remove calendar from defaults
state.defaultCalendars = append(state.defaultCalendars[:i], state.defaultCalendars[i+1:]...) state.defaultCalendars = append(state.defaultCalendars[:i], state.defaultCalendars[i+1:]...)
state.StatusMsg = "Calendar Removed from Defaults" state.StatusMsg = "Calendar '" + calList[cy].Summary + "' Removed from Defaults"
removed = true removed = true
} break
} }
} }
if !removed { if !removed {
// Add calendar to defaults // Add calendar to defaults
state.StatusMsg = "Calendar Added to Defaults" state.StatusMsg = "Calendar '" + calList[cy].Summary + "' Added to Defaults"
state.defaultCalendars = append(state.defaultCalendars, calList[cy].Id) state.defaultCalendars = append(state.defaultCalendars, calList[cy].Id)
} }
updateViews(g) updateViews(g)
@ -138,6 +137,10 @@ func cursorUp(g *gocui.Gui, v *gocui.View) error {
func cursorDown(g *gocui.Gui, v *gocui.View) error { func cursorDown(g *gocui.Gui, v *gocui.View) error {
if v != nil { if v != nil {
cx, cy := v.Cursor() cx, cy := v.Cursor()
calList := state.account.GetCalendarList()
if cy+1 > len(calList)-1 {
return nil
}
if err := v.SetCursor(cx, cy+1); err != nil { if err := v.SetCursor(cx, cy+1); err != nil {
ox, oy := v.Origin() ox, oy := v.Origin()
if err := v.SetOrigin(ox, oy+1); err != nil { if err := v.SetOrigin(ox, oy+1); err != nil {

89
main.go
View File

@ -6,7 +6,6 @@ import (
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"sort"
"strings" "strings"
"time" "time"
@ -69,47 +68,62 @@ func main() {
case "today": case "today":
// Show everything on the calendar for today // Show everything on the calendar for today
InitComm() InitComm()
// TODO: Get calendars flagged as default events := state.account.GetTodaysEvents()
list := state.account.GetCalendarList() if len(events) == 0 {
var todayEvents []Event fmt.Println("No Events Found")
if len(list) > 0 { } else {
for defIdx := range state.defaultCalendars { for _, e := range events {
for i := range list { isOnCal := false
if list[i].Deleted { for _, idx := range state.defaultCalendars {
// Deleted calendar, next please if idx == e.CalendarId {
isOnCal = true
break
}
}
if !isOnCal {
continue continue
} }
if state.defaultCalendars[defIdx] == list[i].Id { stTmStr := e.GetStartTimeString()
todayEvents = append(todayEvents, list[i].GetTodaysEvents()...) durStr := "(" + e.GetEndTime().Sub(e.GetStartTime()).String() + ")"
} if stTmStr == "00:00" {
} stTmStr = "All Day"
} durStr = ""
sort.Sort(ByStartTime(todayEvents))
for _, e := range todayEvents {
if e.GetStartTimeString() == "00:00:00" {
color.New(color.FgGreen).Println("[All Day ] " + e.Summary)
} else { } else {
if time.Until(e.GetStartTime()) < time.Hour { stTmStr = " " + stTmStr
color.New(color.FgYellow).Add(color.Bold).Println("[" + e.GetStartTimeString() + "] " + e.Summary) }
} else if time.Until(e.GetStartTime()) < time.Minute*30 {
color.New(color.FgRed).Add(color.Bold).Println("[" + e.GetStartTimeString() + "] " + e.Summary) eventString := "[" + stTmStr + "] " + e.Summary + " " + durStr
if time.Until(e.GetStartTime()) < 0 && time.Until(e.GetEndTime()) < 0 {
// Event is in the past
color.New(color.FgGreen).Add(color.Bold).Println(eventString)
} else if time.Until(e.GetStartTime()) < 0 && time.Until(e.GetEndTime()) > 0 {
// Event is NOW
color.New(color.FgRed).Add(color.Bold).Println(eventString)
} else if time.Until(e.GetStartTime()) < time.Hour {
// Event is in less than an hour
color.New(color.FgYellow).Add(color.Bold).Println(eventString)
} else { } else {
fmt.Println("[" + e.GetStartTimeString() + "] " + e.Summary) fmt.Println(eventString)
} }
} }
} }
} else {
fmt.Printf("No calendars found.\n")
}
case "config": case "config":
// Open the Configuration CUI screen // Open the Configuration CUI screen
InitComm() InitComm()
DoConfig() DoConfig()
case "ui":
// Open the UI mode
InitComm()
DoUIMode()
case "defaults": case "defaults":
// Show Defaults // Show Defaults
InitComm() InitComm()
for i := range state.defaultCalendars {
fmt.Println(state.defaultCalendars[i])
}
case "add": case "add":
// Quick event add to primary calendar // Quick event add to primary calendar
@ -196,6 +210,15 @@ func saveAccountState() {
fmt.Println("saveAccountState:calListUseBy error:", err) fmt.Println("saveAccountState:calListUseBy error:", err)
} }
} }
var evListJson []byte
if evListJson, err = json.Marshal(state.account.EventList); err == nil {
if err = state.cfg.SetBytes("eventList", evListJson); err != nil {
fmt.Println("saveAccountState:eventList error:", err)
}
if err = state.cfg.SetDateTime("eventListUseBy", state.account.EventListUseBy); err != nil {
fmt.Println("saveAccountState:eventListUseBy error:", err)
}
}
if err = state.cfg.SetArray("defaultCalendars", state.defaultCalendars); err != nil { if err = state.cfg.SetArray("defaultCalendars", state.defaultCalendars); err != nil {
fmt.Println("saveAccountState:defaultCalendars error:", err) fmt.Println("saveAccountState:defaultCalendars error:", err)
} }
@ -221,6 +244,20 @@ func loadAccountState() {
} else { } else {
fmt.Println("error: ", err) fmt.Println("error: ", err)
} }
var evListJson []byte
evListJson = state.cfg.GetBytes("eventList")
if err = json.Unmarshal(evListJson, &state.account.EventList); err == nil {
if len(state.account.EventList) > 0 {
if err != nil {
fmt.Println("error: ", err)
}
if state.account.EventListUseBy, err = state.cfg.GetDateTime("eventListUseBy"); err != nil {
fmt.Println("error: ", err)
}
}
} else {
fmt.Println("error: ", err)
}
// If the 'defaultCalendars' cfg is set to 'primary' (or not at all) // If the 'defaultCalendars' cfg is set to 'primary' (or not at all)
// we need to actually but the primary cal id in there // we need to actually but the primary cal id in there

View File

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"sort"
"time" "time"
"golang.org/x/oauth2" "golang.org/x/oauth2"
@ -21,6 +22,8 @@ type Account struct {
Service *calendar.Service Service *calendar.Service
CalendarList []Calendar CalendarList []Calendar
CalListUseBy time.Time CalListUseBy time.Time
EventList []Event // Today's Events
EventListUseBy time.Time
} }
func GetAccount(secret, token []byte) (*Account, error) { func GetAccount(secret, token []byte) (*Account, error) {
@ -39,9 +42,22 @@ func GetAccount(secret, token []byte) (*Account, error) {
return a, nil return a, nil
} }
// Get Todays Events gets events for today from all calendars
func (a *Account) GetTodaysEvents() []Event { func (a *Account) GetTodaysEvents() []Event {
if time.Now().Before(a.EventListUseBy) {
return a.EventList
}
var ret []Event var ret []Event
list := a.GetCalendarList()
for i := range list {
if list[i].Deleted {
continue
}
ret = append(ret, list[i].GetTodaysEvents()...)
}
sort.Sort(ByStartTime(ret))
a.EventList = ret
a.EventListUseBy = time.Now().Add(time.Hour * 6)
return ret return ret
} }
@ -63,7 +79,7 @@ func (a *Account) GetCalendarList() []Calendar {
ret = append(ret, *GoogleCalendarToLocal(c)) ret = append(ret, *GoogleCalendarToLocal(c))
} }
a.CalendarList = ret a.CalendarList = ret
a.CalListUseBy = time.Now().Add(time.Hour * 6) a.CalListUseBy = time.Now().Add(time.Hour * 24 * 7)
return ret return ret
} }

View File

@ -78,7 +78,7 @@ func (c *Calendar) GetTodaysEvents() []Event {
return ret return ret
} }
for _, e := range events.Items { for _, e := range events.Items {
ret = append(ret, *GoogleEventToLocal(e)) ret = append(ret, *GoogleEventToLocalWithId(e, c.Id))
} }
return ret return ret
} }
@ -91,7 +91,7 @@ func (c *Calendar) GetCalendarEvents() []Event {
return ret return ret
} }
for _, e := range events.Items { for _, e := range events.Items {
ret = append(ret, *GoogleEventToLocal(e)) ret = append(ret, *GoogleEventToLocalWithId(e, c.Id))
} }
return ret return ret
} }

View File

@ -10,6 +10,7 @@ import (
type Event struct { type Event struct {
//Attachments []EventAttachment // Google Drive files //Attachments []EventAttachment // Google Drive files
Attendees []EventAttendee Attendees []EventAttendee
CalendarId string
ColorId string ColorId string
Created string Created string
Creator *EventAttendee Creator *EventAttendee
@ -51,9 +52,9 @@ func (e *Event) ToCLIString() string {
func (e *Event) GetStartTimeString() string { func (e *Event) GetStartTimeString() string {
tm, err := time.Parse(time.RFC3339, e.Start.DateTime) tm, err := time.Parse(time.RFC3339, e.Start.DateTime)
if err != nil { if err != nil {
return "00:00:00" return "00:00"
} }
return tm.Local().Format("15:04:05") return tm.Local().Format("15:04")
} }
func (e *Event) GetStartTime() time.Time { func (e *Event) GetStartTime() time.Time {
@ -61,6 +62,25 @@ func (e *Event) GetStartTime() time.Time {
return tm return tm
} }
func (e *Event) GetEndTimeString() string {
tm, err := time.Parse(time.RFC3339, e.End.DateTime)
if err != nil {
return "00:00"
}
return tm.Local().Format("15:04")
}
func (e *Event) GetEndTime() time.Time {
tm, _ := time.Parse(time.RFC3339, e.End.DateTime)
return tm
}
func GoogleEventToLocalWithId(e *calendar.Event, cId string) *Event {
ret := GoogleEventToLocal(e)
ret.CalendarId = cId
return ret
}
func GoogleEventToLocal(e *calendar.Event) *Event { func GoogleEventToLocal(e *calendar.Event) *Event {
return &Event{ return &Event{
//Attachments []EventAttachment // Google Drive files //Attachments []EventAttachment // Google Drive files

View File

@ -3,9 +3,10 @@ package main
import "github.com/jroimartin/gocui" import "github.com/jroimartin/gocui"
type screen interface { type screen interface {
setViewDefaults(*gocui.View) getGoCuiGui() *gocui.Gui
setViewTextAndCursor(*gocui.View, string) updateViews(*gocui.Gui)
getViewValue(*gocui.Gui) layoutManger(*gocui.Gui) error
addView(string, int, int, int, int)
} }
type position struct { type position struct {

37
ui_mode.go Normal file
View File

@ -0,0 +1,37 @@
package main
import (
"log"
"github.com/jroimartin/gocui"
)
func DoUIMode() {
g, err := gocui.NewGui(gocui.Output256)
if err != nil {
log.Panicln(err)
}
defer g.Close()
g.Cursor = true
g.SetManagerFunc(uiLayout)
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func updateUiViews(g *gocui.Gui) {
for _, v := range g.Views() {
v.Clear()
}
}
func uiLayout(g *gocui.Gui) error {
if v, err := g.SetView("cal_view", 0, 0, 20, 20); err != nil {
if err != gocui.ErrUnknownView {
return err
}
_ = v
}
return nil
}