149 lines
4.6 KiB
Go
149 lines
4.6 KiB
Go
package settings
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type Store struct {
|
|
mu sync.RWMutex
|
|
path string
|
|
}
|
|
|
|
type Settings struct {
|
|
Theme string `yaml:"theme" json:"theme"`
|
|
RepoURL string `yaml:"repoUrl" json:"repoUrl"`
|
|
TTLDays int `yaml:"ttlDays" json:"ttlDays"`
|
|
MaxPayloadBytes int `yaml:"maxPayloadBytes" json:"maxPayloadBytes"`
|
|
AutoPurgePayloads bool `yaml:"autoPurgePayloads" json:"autoPurgePayloads"`
|
|
AutoPurgePayloadBytes int `yaml:"autoPurgePayloadBytes" json:"autoPurgePayloadBytes"`
|
|
AutoExpandDepth int `yaml:"autoExpandDepth" json:"autoExpandDepth"`
|
|
ImageDetection bool `yaml:"imageDetectionEnabled" json:"imageDetectionEnabled"`
|
|
HighlightMs int `yaml:"highlightMs" json:"highlightMs"`
|
|
MQTTProfiles []MQTTProfile `yaml:"mqttProfiles" json:"mqttProfiles"`
|
|
ActiveProfileID string `yaml:"activeProfileId" json:"activeProfileId"`
|
|
ApplyViewFilter bool `yaml:"applyViewFilter" json:"applyViewFilter"`
|
|
ExpandTreeOnStart bool `yaml:"expandTreeOnStart" json:"expandTreeOnStart"`
|
|
TopicFilters []TopicFilter `yaml:"topicFilters" json:"topicFilters"`
|
|
UIFontSize int `yaml:"uiFontSize" json:"uiFontSize"`
|
|
TopicFontSize int `yaml:"topicFontSize" json:"topicFontSize"`
|
|
PayloadFontSize int `yaml:"payloadFontSize" json:"payloadFontSize"`
|
|
StatsRefreshMs int `yaml:"statsRefreshMs" json:"statsRefreshMs"`
|
|
ResizeHandlePx int `yaml:"resizeHandlePx" json:"resizeHandlePx"`
|
|
}
|
|
|
|
type MQTTProfile struct {
|
|
ID string `yaml:"id" json:"id"`
|
|
Name string `yaml:"name" json:"name"`
|
|
Host string `yaml:"host" json:"host"`
|
|
Port int `yaml:"port" json:"port"`
|
|
Username string `yaml:"username" json:"username"`
|
|
Password string `yaml:"password" json:"password"`
|
|
IsDefault bool `yaml:"isDefault" json:"isDefault"`
|
|
}
|
|
|
|
type TopicFilter struct {
|
|
Topic string `yaml:"topic" json:"topic"`
|
|
Save bool `yaml:"save" json:"save"`
|
|
View bool `yaml:"view" json:"view"`
|
|
}
|
|
|
|
func NewStore(path string) *Store {
|
|
return &Store{path: path}
|
|
}
|
|
|
|
func (s *Store) Load(defaults Settings) (Settings, error) {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
|
|
content, err := os.ReadFile(s.path)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return defaults, nil
|
|
}
|
|
return defaults, fmt.Errorf("lecture settings: %w", err)
|
|
}
|
|
|
|
var loaded Settings
|
|
if err := yaml.Unmarshal(content, &loaded); err != nil {
|
|
return defaults, fmt.Errorf("yaml settings: %w", err)
|
|
}
|
|
|
|
return merge(defaults, loaded), nil
|
|
}
|
|
|
|
func (s *Store) Save(next Settings) error {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
dir := filepath.Dir(s.path)
|
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
|
return fmt.Errorf("mkdir settings: %w", err)
|
|
}
|
|
|
|
content, err := yaml.Marshal(next)
|
|
if err != nil {
|
|
return fmt.Errorf("marshal settings: %w", err)
|
|
}
|
|
|
|
return os.WriteFile(s.path, content, 0o644)
|
|
}
|
|
|
|
func merge(base, override Settings) Settings {
|
|
merged := base
|
|
if override.Theme != "" {
|
|
merged.Theme = override.Theme
|
|
}
|
|
if override.RepoURL != "" {
|
|
merged.RepoURL = override.RepoURL
|
|
}
|
|
if override.TTLDays != 0 {
|
|
merged.TTLDays = override.TTLDays
|
|
}
|
|
if override.MaxPayloadBytes != 0 {
|
|
merged.MaxPayloadBytes = override.MaxPayloadBytes
|
|
}
|
|
merged.AutoPurgePayloads = override.AutoPurgePayloads
|
|
if override.AutoPurgePayloadBytes != 0 {
|
|
merged.AutoPurgePayloadBytes = override.AutoPurgePayloadBytes
|
|
}
|
|
if override.AutoExpandDepth != 0 {
|
|
merged.AutoExpandDepth = override.AutoExpandDepth
|
|
}
|
|
merged.ImageDetection = override.ImageDetection
|
|
if override.HighlightMs != 0 {
|
|
merged.HighlightMs = override.HighlightMs
|
|
}
|
|
if len(override.MQTTProfiles) > 0 {
|
|
merged.MQTTProfiles = override.MQTTProfiles
|
|
}
|
|
if override.ActiveProfileID != "" {
|
|
merged.ActiveProfileID = override.ActiveProfileID
|
|
}
|
|
merged.ApplyViewFilter = override.ApplyViewFilter
|
|
merged.ExpandTreeOnStart = override.ExpandTreeOnStart
|
|
if len(override.TopicFilters) > 0 {
|
|
merged.TopicFilters = override.TopicFilters
|
|
}
|
|
if override.UIFontSize != 0 {
|
|
merged.UIFontSize = override.UIFontSize
|
|
}
|
|
if override.TopicFontSize != 0 {
|
|
merged.TopicFontSize = override.TopicFontSize
|
|
}
|
|
if override.PayloadFontSize != 0 {
|
|
merged.PayloadFontSize = override.PayloadFontSize
|
|
}
|
|
if override.StatsRefreshMs != 0 {
|
|
merged.StatsRefreshMs = override.StatsRefreshMs
|
|
}
|
|
if override.ResizeHandlePx != 0 {
|
|
merged.ResizeHandlePx = override.ResizeHandlePx
|
|
}
|
|
return merged
|
|
}
|