2020-06-20 04:40:34 +00:00
|
|
|
// Package config provides the repository for configuration and preferences.
|
|
|
|
package config
|
|
|
|
|
2020-06-20 06:55:39 +00:00
|
|
|
import (
|
2020-06-28 23:01:08 +00:00
|
|
|
"encoding/json"
|
2020-06-20 06:55:39 +00:00
|
|
|
"sort"
|
2020-06-28 23:01:08 +00:00
|
|
|
|
|
|
|
"github.com/diamondburned/cchat-gtk/internal/log"
|
|
|
|
"github.com/pkg/errors"
|
2020-06-20 06:55:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const ConfigFile = "config.json"
|
2020-06-20 04:40:34 +00:00
|
|
|
|
|
|
|
// List of config sections.
|
|
|
|
type Section uint8
|
|
|
|
|
|
|
|
const (
|
|
|
|
Appearance Section = iota
|
|
|
|
sectionLen
|
|
|
|
)
|
|
|
|
|
|
|
|
func (s Section) String() string {
|
|
|
|
switch s {
|
|
|
|
case Appearance:
|
|
|
|
return "Appearance"
|
|
|
|
default:
|
|
|
|
return "???"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-28 23:01:08 +00:00
|
|
|
type SectionEntries map[string]EntryValue
|
|
|
|
|
|
|
|
// UnmarshalJSON ignores all JSON entries with unknown keys.
|
|
|
|
func (s SectionEntries) UnmarshalJSON(b []byte) error {
|
|
|
|
var entries map[string]json.RawMessage
|
|
|
|
if err := json.Unmarshal(b, &entries); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for k, entry := range s {
|
|
|
|
v, ok := entries[k]
|
|
|
|
if ok {
|
|
|
|
if err := entry.UnmarshalJSON(v); err != nil {
|
|
|
|
// Non-fatal error.
|
|
|
|
log.Error(errors.Wrapf(err, "Failed to unmarshal key %q", k))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var sections = [sectionLen]SectionEntries{}
|
2020-06-20 04:40:34 +00:00
|
|
|
|
2020-06-28 23:01:08 +00:00
|
|
|
func AppearanceAdd(name string, value EntryValue) {
|
|
|
|
sc := sections[Appearance]
|
|
|
|
if sc == nil {
|
|
|
|
sc = make(SectionEntries, 1)
|
|
|
|
sections[Appearance] = sc
|
|
|
|
}
|
|
|
|
|
|
|
|
sc[name] = value
|
2020-06-20 04:40:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Entry struct {
|
|
|
|
Name string
|
|
|
|
Value EntryValue
|
|
|
|
}
|
|
|
|
|
2020-06-28 23:01:08 +00:00
|
|
|
func Sections() (sects [sectionLen][]Entry) {
|
|
|
|
for i, section := range sections {
|
|
|
|
var sect = make([]Entry, 0, len(section))
|
|
|
|
for k, v := range section {
|
|
|
|
sect = append(sect, Entry{k, v})
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Slice(sect, func(i, j int) bool {
|
|
|
|
return sect[i].Name < sect[j].Name
|
|
|
|
})
|
|
|
|
|
|
|
|
sects[i] = sect
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
2020-06-20 04:40:34 +00:00
|
|
|
}
|
2020-06-20 06:55:39 +00:00
|
|
|
|
2020-07-09 07:19:18 +00:00
|
|
|
// Save the global config.
|
2020-06-20 06:55:39 +00:00
|
|
|
func Save() error {
|
2020-06-28 23:01:08 +00:00
|
|
|
return MarshalToFile(ConfigFile, sections)
|
2020-06-20 06:55:39 +00:00
|
|
|
}
|
|
|
|
|
2020-07-09 07:19:18 +00:00
|
|
|
// Restore the global config. IsNotExist is not an error and will not be
|
2020-09-02 07:11:48 +00:00
|
|
|
// logged.
|
|
|
|
func Restore() {
|
|
|
|
if err := UnmarshalFromFile(ConfigFile, §ions); err != nil {
|
|
|
|
log.Error(errors.Wrap(err, "Failed to unmarshal main config.json"))
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printlnf("To restore: %#v", toRestore)
|
|
|
|
|
|
|
|
for path, v := range toRestore {
|
|
|
|
if err := UnmarshalFromFile(path, v); err != nil {
|
|
|
|
log.Error(errors.Wrapf(err, "Failed to unmarshal %s", path))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var toRestore = map[string]interface{}{}
|
|
|
|
|
|
|
|
// RegisterConfig adds the config filename into the registry of value pointers
|
|
|
|
// to unmarshal configs to.
|
|
|
|
func RegisterConfig(filename string, jsonValue interface{}) {
|
|
|
|
toRestore[filename] = jsonValue
|
2020-06-20 06:55:39 +00:00
|
|
|
}
|