save state
This commit is contained in:
parent
8bed9a0d9b
commit
25413a6b00
|
@ -4,4 +4,4 @@
|
||||||
/gte-daemon
|
/gte-daemon
|
||||||
test.db
|
test.db
|
||||||
*.apk
|
*.apk
|
||||||
|
tasks.json
|
||||||
|
|
|
@ -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:]
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, <.Task)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tasks) Today() (map[string]string, error) {
|
func (t *Tasks) Today() (map[string]string, error) {
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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 = ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue