backive/ui/ui_main.go

236 lines
5.0 KiB
Go
Raw Normal View History

2022-03-07 23:24:02 +01:00
package ui
import (
"bytes"
2022-06-07 21:20:16 +02:00
"encoding/json"
2022-03-12 23:08:57 +01:00
"fmt"
"io"
"log"
2022-06-07 21:20:16 +02:00
"net"
"os"
"path"
"strconv"
"time"
2022-03-12 23:08:57 +01:00
2022-03-07 23:24:02 +01:00
"fyne.io/fyne/v2"
2022-03-17 20:56:24 +01:00
"fyne.io/fyne/v2/driver/desktop"
2022-03-17 21:01:26 +01:00
"fyne.io/fyne/v2/theme"
2022-03-07 23:24:02 +01:00
"github.com/qwc/backive"
)
var mockOsWriteFile = os.WriteFile
var mockOsReadFile = os.ReadFile
2022-08-14 21:40:37 +02:00
type uiSettings struct {
hideUntil time.Time
globalLevel int
}
2022-03-07 23:24:02 +01:00
var (
app fyne.App
window fyne.Window
config backive.Configuration
doNotShowUntil time.Time = time.Unix(0, 0)
c net.Conn
2022-08-14 21:40:37 +02:00
uisettings uiSettings
messageLevel int
apphomedir string
2022-03-07 23:24:02 +01:00
)
2022-08-14 21:40:37 +02:00
// Init the fyne application
func Init(a fyne.App, w fyne.Window, conf backive.Configuration) {
2022-03-07 23:24:02 +01:00
app = a
2022-03-17 20:56:24 +01:00
a.SetIcon(theme.FyneLogo())
makeTray(app)
2022-06-07 21:20:16 +02:00
config = conf
apphomedir, _ := os.UserHomeDir()
apphomedir = path.Join(apphomedir, ".config", "backive", "ui.json")
2022-08-14 22:55:57 +02:00
LoadSettings()
2022-06-07 21:20:16 +02:00
go PollConnection()
log.Println("UI started")
2022-03-07 23:24:02 +01:00
}
2022-06-07 21:20:16 +02:00
2022-08-14 21:40:37 +02:00
// PollConnection polls in an endless loop the connection
2022-06-07 21:20:16 +02:00
func PollConnection() {
var err error
// Loop for connection and receiving data
2022-06-07 21:20:16 +02:00
for {
// connect when client 'c' is nil
2022-06-07 21:20:16 +02:00
if c == nil {
log.Println("Creating connection")
2022-06-07 21:20:16 +02:00
c, err = net.Dial("unix", config.Settings.UIUnixSocketLocation)
} else {
err = fmt.Errorf("Connection already established")
log.Println(err)
2022-06-07 21:20:16 +02:00
}
// handle error on connection
2022-06-07 21:20:16 +02:00
if err != nil {
log.Println(err)
2022-06-07 21:20:16 +02:00
// ignore
err = nil
c = nil
2022-06-07 21:20:16 +02:00
// sleep a while and then retry
time.Sleep(10 * time.Second)
}
// receive msgs
if c != nil {
data := make([]byte, 2048)
for {
buf := make([]byte, 512)
nr, err := c.Read(buf)
log.Printf("Read %d bytes...", nr)
if err == io.ErrClosedPipe {
c = nil
err = nil
break
}
if err != nil && err != io.EOF {
log.Println(err)
break
}
data = append(data, buf[0:nr]...)
if err == io.EOF {
break
}
}
sdata := string(bytes.Trim(data, "\x00"))
var message map[string]string
log.Printf("Reading JSON: %s", sdata)
errjson := json.Unmarshal([]byte(sdata), &message)
if errjson != nil {
log.Println(errjson)
continue
}
ShowNotification(message)
}
2022-06-07 21:20:16 +02:00
}
}
2022-08-14 21:40:37 +02:00
// ShowNotification shows a single notification
2022-06-07 21:20:16 +02:00
func ShowNotification(data map[string]string) {
if ShallShow(data) {
app.SendNotification(
fyne.NewNotification(
2022-06-07 21:20:16 +02:00
data["header"],
data["message"],
),
)
}
}
2022-08-14 21:40:37 +02:00
// ShallShow checks if a message should be shown by level
2022-06-07 21:20:16 +02:00
func ShallShow(data map[string]string) bool {
level, err := strconv.ParseUint(data["level"], 10, 64)
if err != nil {
return false
}
if level <= 10 {
return true
}
if int(level) <= uisettings.globalLevel && messageLevel > 0 {
return false
}
if int(level) <= uisettings.globalLevel {
return true
}
return false
}
2022-08-14 21:40:37 +02:00
// SetHideUntil sets the time until messages should be hidden
func SetHideUntil(until time.Time) {
uisettings.hideUntil = until
2022-08-14 22:55:57 +02:00
SaveSettings()
}
2022-08-14 21:40:37 +02:00
// SetMessageLevel does exactly that.
func SetMessageLevel(level int) {
if level <= 10 {
messageLevel = level
} else {
uisettings.globalLevel = level
messageLevel = 0
SaveSettings()
}
}
2022-08-14 21:40:37 +02:00
// SaveSettings stores the settings in $HOME/.config/backive/ui.json
func SaveSettings() {
// save internal settings to file in homedir
jsonstr, merr := json.Marshal(uisettings)
if merr != nil {
panic(merr)
}
log.Printf("Writing database output to file: %s", jsonstr)
saveDir, _ := path.Split(apphomedir)
backive.CreateDirectoryIfNotExists(saveDir)
err := mockOsWriteFile(apphomedir, []byte(jsonstr), 0644)
if err != nil {
panic(err)
}
log.Println("Saved Settings.")
}
2022-08-14 21:40:37 +02:00
// LoadSettings loads the settings from the place where SaveSettings stored them.
func LoadSettings() {
// load settings
if _, err := os.Stat(apphomedir); err == nil {
data, rferr := mockOsReadFile(apphomedir)
if rferr != nil {
panic(rferr)
}
json.Unmarshal(data, &uisettings)
log.Println("Loaded Settings.")
} /*else if os.IsNotExist(err) {
// no data
}*/
}
2022-08-14 21:40:37 +02:00
// makeTray creates the tray menus needed.
2022-03-17 20:56:24 +01:00
func makeTray(app fyne.App) {
if desk, ok := app.(desktop.App); ok {
hideReminders := fyne.NewMenuItem(
2022-08-14 22:06:09 +02:00
"Hide reminders for",
nil,
)
hideReminders.ChildMenu = fyne.NewMenu(
"",
2022-08-14 22:06:09 +02:00
fyne.NewMenuItem("today", func() {
doNotShowUntil = time.Now().AddDate(0, 0, 1)
SetHideUntil(doNotShowUntil)
}),
2022-08-14 22:06:09 +02:00
fyne.NewMenuItem("a hour", func() {
doNotShowUntil = time.Now().Add(time.Hour)
SetHideUntil(doNotShowUntil)
}),
)
levelMenu := fyne.NewMenuItem(
"Set notification level", nil,
)
levelMenu.ChildMenu = fyne.NewMenu(
"",
fyne.NewMenuItem(
"Only problems and tasks finished (resets to previous with restart)",
func() { SetMessageLevel(10) },
),
fyne.NewMenuItem(
"+ Reminders (default)",
func() { SetMessageLevel(20) },
),
fyne.NewMenuItem(
"+ Informational messages",
func() { SetMessageLevel(30) },
),
fyne.NewMenuItem(
"+ Verbose/Debug messages",
func() { SetMessageLevel(40) },
),
)
menu := fyne.NewMenu(
"backive",
hideReminders,
levelMenu,
)
2022-03-17 20:56:24 +01:00
desk.SetSystemTrayMenu(menu)
}
}