Caching calendar list

Started work on config screen
This commit is contained in:
Brian Buller 2017-02-23 11:20:29 -06:00
parent 113b161e0f
commit 22e770cc64
2 changed files with 214 additions and 48 deletions

View File

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"time"
"golang.org/x/oauth2" "golang.org/x/oauth2"
"golang.org/x/oauth2/google" "golang.org/x/oauth2/google"
@ -16,8 +17,10 @@ import (
) )
type Account struct { type Account struct {
CC *CalClient CC *CalClient
Service *calendar.Service Service *calendar.Service
CalendarList []Calendar
CalListUseBy time.Time
} }
func GetAccount(secret, token []byte) (*Account, error) { func GetAccount(secret, token []byte) (*Account, error) {
@ -43,20 +46,24 @@ func (a *Account) GetTodaysEvents() []Event {
} }
func (a *Account) GetDefaultCalendar() *Calendar { func (a *Account) GetDefaultCalendar() *Calendar {
c, _ := state.account.Service.CalendarList.Get("primary").Do() c, _ := a.Service.CalendarList.Get("primary").Do()
return GoogleCalendarToLocal(c) return GoogleCalendarToLocal(c)
} }
func (a *Account) GetCalendarList() []Calendar { func (a *Account) GetCalendarList() []Calendar {
// TODO: Check if we have the calendar list cached if time.Now().Before(a.CalListUseBy) {
return a.CalendarList
}
var ret []Calendar var ret []Calendar
calList, err := state.account.Service.CalendarList.List().Do() calList, err := a.Service.CalendarList.List().Do()
if err != nil { if err != nil {
return ret return ret
} }
for _, c := range calList.Items { for _, c := range calList.Items {
ret = append(ret, *GoogleCalendarToLocal(c)) ret = append(ret, *GoogleCalendarToLocal(c))
} }
a.CalendarList = ret
a.CalListUseBy = time.Now().Add(time.Hour * 6)
return ret return ret
} }

245
main.go
View File

@ -1,14 +1,17 @@
package main package main
import ( import (
"encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"sort" "sort"
"strings" "strings"
"time"
"github.com/br0xen/user-config" "github.com/br0xen/user-config"
"github.com/jroimartin/gocui"
) )
const ( const (
@ -17,11 +20,14 @@ const (
) )
type AppState struct { type AppState struct {
Name string Name string
Version int Version int
ClientSecret []byte ClientSecret []byte
cfg *userConfig.Config cfg *userConfig.Config
account *Account account *Account
defaultCalendars []string
StatusMsg string
} }
var state *AppState var state *AppState
@ -38,9 +44,6 @@ func main() {
if len(os.Args) > 1 { if len(os.Args) > 1 {
op = os.Args[1] op = os.Args[1]
switch os.Args[1] {
case "--reinit":
}
} else { } else {
op = "today" op = "today"
} }
@ -54,6 +57,7 @@ func main() {
fmt.Println("Deleting Key: " + v) fmt.Println("Deleting Key: " + v)
state.cfg.DeleteKey(v) state.cfg.DeleteKey(v)
} }
case "today": case "today":
// Show everything on the calendar for today // Show everything on the calendar for today
InitComm() InitComm()
@ -61,12 +65,16 @@ func main() {
list := state.account.GetCalendarList() list := state.account.GetCalendarList()
var todayEvents []Event var todayEvents []Event
if len(list) > 0 { if len(list) > 0 {
for i := range list { for defIdx := range state.defaultCalendars {
if list[i].Deleted { for i := range list {
// Deleted calendar, next please if list[i].Deleted {
continue // Deleted calendar, next please
continue
}
if state.defaultCalendars[defIdx] == list[i].Id {
todayEvents = append(todayEvents, list[i].GetTodaysEvents()...)
}
} }
todayEvents = append(todayEvents, list[i].GetTodaysEvents()...)
} }
sort.Sort(ByStartTime(todayEvents)) sort.Sort(ByStartTime(todayEvents))
for _, e := range todayEvents { for _, e := range todayEvents {
@ -80,6 +88,10 @@ func main() {
fmt.Printf("No calendars found.\n") fmt.Printf("No calendars found.\n")
} }
case "config":
InitComm()
DoConfig()
case "defaults": case "defaults":
// Show Defaults // Show Defaults
InitComm() InitComm()
@ -97,34 +109,8 @@ func main() {
// Just initialize communications and bail // Just initialize communications and bail
InitComm() InitComm()
} }
// All done, save the account state
//fmt.Println("\n-====-\n") saveAccountState()
/*
t := time.Now().Format(time.RFC3339)
events, err := srv.Events.List("primary").ShowDeleted(false).
SingleEvents(true).TimeMin(t).MaxResults(10).OrderBy("startTime").Do()
if err != nil {
log.Fatalf("Unable to retrieve next ten of the user's events. %v", err)
}
fmt.Println("Upcoming events:")
if len(events.Items) > 0 {
for _, i := range events.Items {
var when string
// If the DateTime is an empty string the Event is an all-day Event.
// So only Date is available.
if i.Start.DateTime != "" {
when = i.Start.DateTime
} else {
when = i.Start.Date
}
fmt.Printf("%s (%s)\n", i.Summary, when)
}
} else {
fmt.Printf("No upcoming events found.\n")
}
*/
} }
func InitComm() { func InitComm() {
@ -140,15 +126,20 @@ func InitComm() {
// Save the Raw Token // Save the Raw Token
state.cfg.SetBytes("Token", state.account.CC.GetRawToken()) state.cfg.SetBytes("Token", state.account.CC.GetRawToken())
// If the 'defaultCalendars' cfg is set to 'primary', we need to actually but the primary cal id in there // If the 'defaultCalendars' cfg is set to 'primary' (or not at all)
// we need to actually but the primary cal id in there
var defCal []string var defCal []string
defCal, err = state.cfg.GetArray("defaultCalendars") defCal, err = state.cfg.GetArray("defaultCalendars")
if len(defCal) == 0 || (len(defCal) == 1 && defCal[0] == "primary") { if len(defCal) == 0 || (len(defCal) == 1 && defCal[0] == "primary") {
gCal, err := state.account.Service.CalendarList.Get("primary").Do() gCal, err := state.account.Service.CalendarList.Get("primary").Do()
if err == nil { if err == nil {
state.cfg.SetArray("defaultCalendars", []string{gCal.Id}) defCal = []string{gCal.Id}
state.cfg.SetArray("defaultCalendars", defCal)
} }
} }
state.defaultCalendars = defCal
loadAccountState()
} }
func DoVersionCheck() { func DoVersionCheck() {
@ -178,3 +169,171 @@ func DoVersionCheck() {
confVer, _ = state.cfg.GetInt("version") confVer, _ = state.cfg.GetInt("version")
} }
} }
// saveAccountState saves all the bits of cache from the account
// into our config
func saveAccountState() {
var err error
var calListJson []byte
if calListJson, err = json.Marshal(state.account.CalendarList); err == nil {
if err = state.cfg.SetBytes("calendarList", calListJson); err != nil {
fmt.Println("saveAccountState:calendarList error:", err)
}
if err = state.cfg.SetDateTime("calListUseBy", state.account.CalListUseBy); err != nil {
fmt.Println("saveAccountState:calListUseBy error:", err)
}
}
if err = state.cfg.SetArray("defaultCalendars", state.defaultCalendars); err != nil {
fmt.Println("saveAccountState:defaultCalendars error:", err)
}
}
// loadAccountState loads all the bits of cache from the config
// into the account
func loadAccountState() {
var err error
var calListJson []byte
calListJson = state.cfg.GetBytes("calendarList")
if err = json.Unmarshal(calListJson, &state.account.CalendarList); err == nil {
if len(state.account.CalendarList) > 0 {
if err != nil {
fmt.Println("error: ", err)
}
if state.account.CalListUseBy, err = state.cfg.GetDateTime("calListUseBy"); err != nil {
fmt.Println("error: ", err)
}
}
} else {
fmt.Println("error: ", err)
}
}
// BEGIN CONFIG SCREEN FUNCTIONS //
func DoConfig() {
g, err := gocui.NewGui(gocui.Output256)
if err != nil {
log.Panicln(err)
}
defer g.Close()
g.Cursor = true
g.SetManagerFunc(configLayout)
// Set up some keybindings
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("default_calendars", gocui.KeyArrowUp, gocui.ModNone, cursorUp); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("default_calendars", 'k', gocui.ModNone, cursorUp); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("default_calendars", gocui.KeyArrowDown, gocui.ModNone, cursorDown); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("default_calendars", 'j', gocui.ModNone, cursorDown); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("default_calendars", gocui.KeySpace, gocui.ModNone, toggleCalendar); err != nil {
log.Panicln(err)
}
if err := g.SetKeybinding("default_calendars", gocui.KeyEnter, gocui.ModNone, toggleCalendar); err != nil {
log.Panicln(err)
}
// Kick off the main loop
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)
}
}
func configLayout(g *gocui.Gui) error {
list := state.account.GetCalendarList()
height := len(list) + 4
width, _ := g.Size()
if v, err := g.SetView("default_calendars", 0, 0, width-1, height); err != nil {
v.Highlight = true
v.SelBgColor = gocui.ColorGreen
v.SelFgColor = gocui.ColorBlack
if err != gocui.ErrUnknownView {
return err
}
drawCalList(g, v)
if _, err := g.SetCurrentView("default_calendars"); err != nil {
return err
}
}
return nil
}
func quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit
}
func toggleCalendar(g *gocui.Gui, v *gocui.View) error {
_, cy := v.Cursor()
calList := state.account.GetCalendarList()
if v != nil {
for i := range state.defaultCalendars {
state.StatusMsg = time.Now().Format(time.RFC3339)
if state.defaultCalendars[i] == calList[cy].Id {
}
}
}
drawCalList(g, v)
return nil
}
func cursorUp(g *gocui.Gui, v *gocui.View) error {
if v != nil {
ox, oy := v.Origin()
cx, cy := v.Cursor()
if err := v.SetCursor(cx, cy-1); err != nil && oy > 0 {
if err := v.SetOrigin(ox, oy-1); err != nil {
return err
}
}
}
return nil
}
func cursorDown(g *gocui.Gui, v *gocui.View) error {
if v != nil {
cx, cy := v.Cursor()
if err := v.SetCursor(cx, cy+1); err != nil {
ox, oy := v.Origin()
if err := v.SetOrigin(ox, oy+1); err != nil {
return err
}
}
}
return nil
}
func drawCalList(g *gocui.Gui, v *gocui.View) error {
width, _ := g.Size()
list := state.account.GetCalendarList()
for i := range list {
isDef := false
for defIdx := range state.defaultCalendars {
if list[i].Id == state.defaultCalendars[defIdx] {
isDef = true
break
}
}
calSumTxt := "["
if isDef {
calSumTxt += "*"
} else {
calSumTxt += " "
}
calSumTxt += "] " + list[i].Summary
spc := strings.Repeat(" ", width-len(calSumTxt)-2)
fmt.Fprintln(v, calSumTxt+spc)
}
fmt.Fprintln(v, "Status: "+state.StatusMsg)
return nil
}
// END CONFIG SCREEN FUNCTIONS //