save state

This commit is contained in:
Erik Winter 2022-10-23 12:45:21 +02:00
parent 8bed9a0d9b
commit 25413a6b00
9 changed files with 133 additions and 24 deletions

2
.gitignore vendored
View File

@ -4,4 +4,4 @@
/gte-daemon /gte-daemon
test.db test.db
*.apk *.apk
tasks.json

View File

@ -16,7 +16,7 @@ func NewLogger() *Logger {
} }
func (l *Logger) Log(line string) { func (l *Logger) Log(line string) {
l.lines = append(l.lines, fmt.Sprintf("%s: %s", time.Now().Format(time.Stamp), line)) l.lines = append(l.lines, fmt.Sprintf("%s: %s", time.Now().Format(time.StampMicro), line))
if len(l.lines) > 50 { if len(l.lines) > 50 {
l.lines = l.lines[1:] l.lines = l.lines[1:]
} }

View File

@ -18,8 +18,8 @@ type Tasks struct {
disp *storage.Dispatcher disp *storage.Dispatcher
} }
func NewTasks(conf *Configuration) (*Tasks, error) { func NewTasks(conf *Configuration, tasks []*task.Task) *Tasks {
local := storage.NewMemory() local := storage.NewMemory(tasks...)
remote := storage.NewRemoteRepository(mstore.NewIMAP(conf.IMAP())) remote := storage.NewRemoteRepository(mstore.NewIMAP(conf.IMAP()))
disp := storage.NewDispatcher(msend.NewSSLSMTP(conf.SMTP())) disp := storage.NewDispatcher(msend.NewSSLSMTP(conf.SMTP()))
@ -27,7 +27,23 @@ func NewTasks(conf *Configuration) (*Tasks, error) {
local: local, local: local,
remote: remote, remote: remote,
disp: disp, disp: disp,
}, nil }
}
func (t *Tasks) All() ([]*task.Task, error) {
lts, err := t.local.FindAll()
if err != nil {
return []*task.Task{}, err
}
for _, lt := range lts {
lt.ApplyUpdate()
}
ts := []*task.Task{}
for _, lt := range lts {
ts = append(ts, &lt.Task)
}
return ts, nil
} }
func (t *Tasks) Today() (map[string]string, error) { func (t *Tasks) Today() (map[string]string, error) {

View File

@ -13,10 +13,10 @@ func main() {
conf.Load() conf.Load()
logger := component.NewLogger() logger := component.NewLogger()
runner := runner.NewRunner(conf, logger) r := runner.NewRunner(conf, logger)
tabs := runner.Init() tabs := r.Init()
w.SetContent(tabs) w.SetContent(tabs)
go runner.Run() go r.Run()
w.ShowAndRun() w.ShowAndRun()
} }

View File

@ -1,14 +1,18 @@
package runner package runner
import ( import (
"encoding/json"
"fmt" "fmt"
"io"
"sync" "sync"
"time" "time"
"ewintr.nl/gte/cmd/android-app/component" "ewintr.nl/gte/cmd/android-app/component"
"ewintr.nl/gte/cmd/android-app/screen" "ewintr.nl/gte/cmd/android-app/screen"
"ewintr.nl/gte/internal/task"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/storage"
) )
var runnerLock = sync.Mutex{} var runnerLock = sync.Mutex{}
@ -45,11 +49,12 @@ func (r *Runner) Init() fyne.CanvasObject {
configTab := container.NewTabItem("config", configScreen.Content()) configTab := container.NewTabItem("config", configScreen.Content())
r.screens = append(r.screens, configScreen) r.screens = append(r.screens, configScreen)
tasks, err := component.NewTasks(r.conf) stored, err := load()
if err != nil { if err != nil {
r.logger.Log(err.Error()) r.logger.Log(err.Error())
} }
r.tasks = tasks r.logger.Log(fmt.Sprintf("loaded %d tasks from file", len(stored)))
r.tasks = component.NewTasks(r.conf, stored)
taskScreen := screen.NewTasks(r.requests) taskScreen := screen.NewTasks(r.requests)
taskTab := container.NewTabItem("tasks", taskScreen.Content()) taskTab := container.NewTabItem("tasks", taskScreen.Content())
r.screens = append(r.screens, taskScreen) r.screens = append(r.screens, taskScreen)
@ -88,8 +93,19 @@ func (r *Runner) processRequest() {
r.logger.Log(fmt.Sprintf("task sync: dispatched: %d, fetched: %d", countDisp, countFetch)) r.logger.Log(fmt.Sprintf("task sync: dispatched: %d, fetched: %d", countDisp, countFetch))
//} //}
r.status = "ready" r.status = "ready"
r.logger.Log("sync request done")
r.logger.Log("fetching all")
all, err := r.tasks.All()
if err != nil {
r.logger.Log(err.Error())
break
}
r.logger.Log("saving all")
if err := save(all); err != nil {
r.logger.Log(err.Error())
break
}
r.logger.Log("sync request done")
case screen.MarkTaskDoneRequest: case screen.MarkTaskDoneRequest:
if err := r.tasks.MarkDone(v.ID); err != nil { if err := r.tasks.MarkDone(v.ID); err != nil {
r.logger.Log(err.Error()) r.logger.Log(err.Error())
@ -111,6 +127,7 @@ func (r *Runner) refresher() {
if err != nil { if err != nil {
r.logger.Log(err.Error()) r.logger.Log(err.Error())
} }
r.logger.Log(fmt.Sprintf("found %d tasks", len(tasks)))
sTasks := []screen.Task{} sTasks := []screen.Task{}
for id, action := range tasks { for id, action := range tasks {
sTasks = append(sTasks, screen.Task{ sTasks = append(sTasks, screen.Task{
@ -139,3 +156,50 @@ func (r *Runner) backgroundSync() {
<-ticker.C <-ticker.C
} }
} }
func load() ([]*task.Task, error) {
uri := storage.NewFileURI("tasks.json")
fr, err := storage.Reader(uri)
if err != nil {
return []*task.Task{}, err
}
defer fr.Close()
exists, err := storage.Exists(uri)
if !exists {
return []*task.Task{}, fmt.Errorf("uri does not exist")
}
if err != nil {
return []*task.Task{}, err
}
data, err := io.ReadAll(fr)
if err != nil {
return []*task.Task{}, err
}
storedTasks := []*task.Task{}
if err := json.Unmarshal(data, &storedTasks); err != nil {
return []*task.Task{}, err
}
return storedTasks, nil
}
func save(tasks []*task.Task) error {
uri := storage.NewFileURI("tasks.json")
fw, err := storage.Writer(uri)
if err != nil {
return err
}
data, err := json.Marshal(tasks)
if err != nil {
return err
}
if _, err := fw.Write(data); err != nil {
return err
}
defer fw.Close()
return nil
}

View File

@ -21,6 +21,7 @@ type Tasks struct {
tasks []Task tasks []Task
taskLabels binding.StringList taskLabels binding.StringList
selectedTask string selectedTask string
list *widget.List
out chan interface{} out chan interface{}
} }
@ -44,6 +45,9 @@ func (t *Tasks) Refresh(state State) {
tls = append(tls, t.Action) tls = append(tls, t.Action)
} }
t.taskLabels.Set(tls) t.taskLabels.Set(tls)
if t.selectedTask == "" {
t.list.UnselectAll()
}
} }
func (t *Tasks) Content() fyne.CanvasObject { func (t *Tasks) Content() fyne.CanvasObject {
@ -53,7 +57,7 @@ func (t *Tasks) Content() fyne.CanvasObject {
doneButton := widget.NewButton("done", func() { doneButton := widget.NewButton("done", func() {
t.markDone() t.markDone()
}) })
list := widget.NewListWithData( t.list = widget.NewListWithData(
t.taskLabels, t.taskLabels,
func() fyne.CanvasObject { func() fyne.CanvasObject {
return widget.NewLabel("template") return widget.NewLabel("template")
@ -62,14 +66,14 @@ func (t *Tasks) Content() fyne.CanvasObject {
o.(*widget.Label).Bind(i.(binding.String)) o.(*widget.Label).Bind(i.(binding.String))
}, },
) )
list.OnSelected = t.selectItem t.list.OnSelected = t.selectItem
return container.NewBorder( return container.NewBorder(
container.NewHBox(statusLabel), container.NewHBox(statusLabel),
doneButton, doneButton,
nil, nil,
nil, nil,
list, t.list,
) )
} }
@ -89,4 +93,5 @@ func (t *Tasks) markDone() {
t.out <- MarkTaskDoneRequest{ t.out <- MarkTaskDoneRequest{
ID: t.selectedTask, ID: t.selectedTask,
} }
t.selectedTask = ""
} }

View File

@ -13,9 +13,17 @@ type Memory struct {
latestSync time.Time latestSync time.Time
} }
func NewMemory() *Memory { func NewMemory(initTasks ...*task.Task) *Memory {
tasks := map[string]*task.LocalTask{}
for _, t := range initTasks {
tasks[t.Id] = &task.LocalTask{
Task: *t,
LocalUpdate: &task.LocalUpdate{},
}
}
return &Memory{ return &Memory{
tasks: map[string]*task.LocalTask{}, tasks: tasks,
} }
} }

View File

@ -1,6 +1,7 @@
package task package task
import ( import (
"encoding/json"
"fmt" "fmt"
"sort" "sort"
"strings" "strings"
@ -49,6 +50,21 @@ type Date struct {
t time.Time t time.Time
} }
func (d *Date) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}
func (d *Date) UnmarshalJSON(data []byte) error {
dateString := ""
if err := json.Unmarshal(data, &dateString); err != nil {
return err
}
nd := NewDateFromString(dateString)
d.t = nd.Time()
return nil
}
func NewDate(year, month, day int) Date { func NewDate(year, month, day int) Date {
if year == 0 || month == 0 || month > 12 || day == 0 { if year == 0 || month == 0 || month > 12 || day == 0 {

View File

@ -64,15 +64,15 @@ type Task struct {
// local situations. It will be filtered out in LocalRepository.SetTasks() // local situations. It will be filtered out in LocalRepository.SetTasks()
Message *mstore.Message Message *mstore.Message
Id string Id string `json:"id"`
Version int Version int `json:"version"`
Folder string Folder string `json:"folder"`
Action string Action string `json:"action"`
Project string Project string `json:"project"`
Due Date Due Date `json:"date"`
Recur Recurrer Recur Recurrer `json:"-"`
Done bool Done bool `json:"done"`
} }
func NewFromMessage(msg *mstore.Message) *Task { func NewFromMessage(msg *mstore.Message) *Task {