refactor: define preferences data with go struct
This commit is contained in:
parent
ffc50a7fcc
commit
66ac7194e2
|
@ -39,8 +39,8 @@ func (p *preferencesService) GetPreferences() (resp types.JSResp) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *preferencesService) SetPreferences(values map[string]any) (resp types.JSResp) {
|
func (p *preferencesService) SetPreferences(pf types.Preferences) (resp types.JSResp) {
|
||||||
err := p.pref.SetPreferencesN(values)
|
err := p.pref.SetPreferences(&pf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.Msg = err.Error()
|
resp.Msg = err.Error()
|
||||||
return
|
return
|
||||||
|
@ -50,6 +50,16 @@ func (p *preferencesService) SetPreferences(values map[string]any) (resp types.J
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *preferencesService) UpdatePreferences(value map[string]any) (resp types.JSResp) {
|
||||||
|
err := p.pref.UpdatePreferences(value)
|
||||||
|
if err != nil {
|
||||||
|
resp.Msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.Success = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (p *preferencesService) RestorePreferences() (resp types.JSResp) {
|
func (p *preferencesService) RestorePreferences() (resp types.JSResp) {
|
||||||
defaultPref := p.pref.RestoreDefault()
|
defaultPref := p.pref.RestoreDefault()
|
||||||
resp.Data = map[string]any{
|
resp.Data = map[string]any{
|
||||||
|
@ -103,21 +113,20 @@ func (p *preferencesService) GetAppVersion() (resp types.JSResp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *preferencesService) SaveWindowSize(width, height int) {
|
func (p *preferencesService) SaveWindowSize(width, height int) {
|
||||||
p.SetPreferences(map[string]any{
|
p.UpdatePreferences(map[string]any{
|
||||||
"behavior.window_width": width,
|
"behavior.windowWidth": width,
|
||||||
"behavior.window_height": height,
|
"behavior.windowHeight": height,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *preferencesService) GetWindowSize() (width, height int) {
|
func (p *preferencesService) GetWindowSize() (width, height int) {
|
||||||
data := p.pref.GetPreferences()
|
data := p.pref.GetPreferences()
|
||||||
w, h := data["behavior.window_width"], data["behavior.window_height"]
|
width, height = data.Behavior.WindowWidth, data.Behavior.WindowHeight
|
||||||
var ok bool
|
if width <= 0 {
|
||||||
if width, ok = w.(int); !ok {
|
width = consts.DEFAULT_WINDOW_WIDTH
|
||||||
return consts.DEFAULT_WINDOW_WIDTH, consts.DEFAULT_WINDOW_HEIGHT
|
|
||||||
}
|
}
|
||||||
if height, ok = h.(int); !ok {
|
if height <= 0 {
|
||||||
return consts.DEFAULT_WINDOW_WIDTH, consts.DEFAULT_WINDOW_HEIGHT
|
height = consts.DEFAULT_WINDOW_HEIGHT
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"log"
|
"log"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"tinyrdm/backend/consts"
|
"tinyrdm/backend/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PreferencesStorage struct {
|
type PreferencesStorage struct {
|
||||||
|
@ -20,30 +21,11 @@ func NewPreferences() *PreferencesStorage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PreferencesStorage) DefaultPreferences() map[string]any {
|
func (p *PreferencesStorage) DefaultPreferences() types.Preferences {
|
||||||
return map[string]any{
|
return types.NewPreferences()
|
||||||
"behavior": map[string]any{
|
|
||||||
"aside_width": consts.DEFAULT_ASIDE_WIDTH,
|
|
||||||
"window_width": consts.DEFAULT_WINDOW_WIDTH,
|
|
||||||
"window_height": consts.DEFAULT_WINDOW_HEIGHT,
|
|
||||||
},
|
|
||||||
"general": map[string]any{
|
|
||||||
"language": "auto",
|
|
||||||
"font": "",
|
|
||||||
"font_size": consts.DEFAULT_FONT_SIZE,
|
|
||||||
"use_sys_proxy": false,
|
|
||||||
"use_sys_proxy_http": false,
|
|
||||||
"check_update": true,
|
|
||||||
"skip_version": "",
|
|
||||||
},
|
|
||||||
"editor": map[string]any{
|
|
||||||
"font": "",
|
|
||||||
"font_size": 14,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PreferencesStorage) getPreferences() (ret map[string]any) {
|
func (p *PreferencesStorage) getPreferences() (ret types.Preferences) {
|
||||||
b, err := p.storage.Load()
|
b, err := p.storage.Load()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ret = p.DefaultPreferences()
|
ret = p.DefaultPreferences()
|
||||||
|
@ -57,79 +39,43 @@ func (p *PreferencesStorage) getPreferences() (ret map[string]any) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PreferencesStorage) flatPreferences(data map[string]any, prefix string) map[string]any {
|
|
||||||
flattened := make(map[string]any)
|
|
||||||
for key, value := range data {
|
|
||||||
newKey := key
|
|
||||||
if prefix != "" {
|
|
||||||
newKey = prefix + "." + key
|
|
||||||
}
|
|
||||||
|
|
||||||
if nested, ok := value.(map[string]any); ok {
|
|
||||||
nestedFlattened := p.flatPreferences(nested, newKey)
|
|
||||||
for k, v := range nestedFlattened {
|
|
||||||
flattened[k] = v
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
flattened[newKey] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return flattened
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPreferences Get preferences from local
|
// GetPreferences Get preferences from local
|
||||||
func (p *PreferencesStorage) GetPreferences() (ret map[string]any) {
|
func (p *PreferencesStorage) GetPreferences() (ret types.Preferences) {
|
||||||
p.mutex.Lock()
|
p.mutex.Lock()
|
||||||
defer p.mutex.Unlock()
|
defer p.mutex.Unlock()
|
||||||
|
|
||||||
pref := p.getPreferences()
|
ret = p.getPreferences()
|
||||||
ret = p.flatPreferences(pref, "")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PreferencesStorage) Value(keys ...string) any {
|
func (p *PreferencesStorage) setPreferences(pf *types.Preferences, key string, value any) error {
|
||||||
kv := p.getPreferences()
|
parts := strings.Split(key, ".")
|
||||||
var ok bool
|
if len(parts) > 0 {
|
||||||
var a any
|
var reflectValue reflect.Value
|
||||||
total := len(keys)
|
if reflect.TypeOf(pf).Kind() == reflect.Ptr {
|
||||||
for i, key := range keys {
|
reflectValue = reflect.ValueOf(pf).Elem()
|
||||||
if a, ok = kv[key]; !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if i == total-1 {
|
|
||||||
// last key, return value
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
if kv, ok = a.(map[string]any); !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PreferencesStorage) setPreferences(pf map[string]any, key string, value any) error {
|
|
||||||
keyPath := strings.Split(key, ".")
|
|
||||||
if len(keyPath) <= 0 {
|
|
||||||
return fmt.Errorf("invalid key path(%s)", key)
|
|
||||||
}
|
|
||||||
var node any = pf
|
|
||||||
for _, k := range keyPath[:len(keyPath)-1] {
|
|
||||||
if subNode, ok := node.(map[string]any); ok {
|
|
||||||
node = subNode[k]
|
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("invalid key path(%s)", key)
|
reflectValue = reflect.ValueOf(pf)
|
||||||
}
|
}
|
||||||
}
|
for i, part := range parts {
|
||||||
|
part = strings.ToUpper(part[:1]) + part[1:]
|
||||||
if subNode, ok := node.(map[string]any); ok {
|
reflectValue = reflectValue.FieldByName(part)
|
||||||
subNode[keyPath[len(keyPath)-1]] = value
|
if reflectValue.IsValid() {
|
||||||
}
|
if i == len(parts)-1 {
|
||||||
|
reflectValue.Set(reflect.ValueOf(value))
|
||||||
return nil
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("invalid key path(%s)", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PreferencesStorage) savePreferences(pf map[string]any) error {
|
func (p *PreferencesStorage) savePreferences(pf *types.Preferences) error {
|
||||||
b, err := yaml.Marshal(&pf)
|
b, err := yaml.Marshal(pf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -140,37 +86,35 @@ func (p *PreferencesStorage) savePreferences(pf map[string]any) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPreferences assign value to key path, the key path use "." to indicate multiple level
|
// SetPreferences replace preferences
|
||||||
func (p *PreferencesStorage) SetPreferences(key string, value any) error {
|
func (p *PreferencesStorage) SetPreferences(pf *types.Preferences) error {
|
||||||
p.mutex.Lock()
|
p.mutex.Lock()
|
||||||
defer p.mutex.Unlock()
|
defer p.mutex.Unlock()
|
||||||
|
|
||||||
pf := p.getPreferences()
|
|
||||||
if err := p.setPreferences(pf, key, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return p.savePreferences(pf)
|
return p.savePreferences(pf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPreferencesN set multiple key path and value
|
// UpdatePreferences update values by key paths, the key path use "." to indicate multiple level
|
||||||
func (p *PreferencesStorage) SetPreferencesN(values map[string]any) error {
|
func (p *PreferencesStorage) UpdatePreferences(values map[string]any) error {
|
||||||
p.mutex.Lock()
|
p.mutex.Lock()
|
||||||
defer p.mutex.Unlock()
|
defer p.mutex.Unlock()
|
||||||
|
|
||||||
pf := p.getPreferences()
|
pf := p.getPreferences()
|
||||||
for path, v := range values {
|
for path, v := range values {
|
||||||
log.Println("path", path, v)
|
if err := p.setPreferences(&pf, path, v); err != nil {
|
||||||
if err := p.setPreferences(pf, path, v); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Println("after save", pf)
|
log.Println("after save", pf)
|
||||||
|
|
||||||
return p.savePreferences(pf)
|
return p.savePreferences(&pf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PreferencesStorage) RestoreDefault() map[string]any {
|
func (p *PreferencesStorage) RestoreDefault() types.Preferences {
|
||||||
|
p.mutex.Lock()
|
||||||
|
defer p.mutex.Unlock()
|
||||||
|
|
||||||
pf := p.DefaultPreferences()
|
pf := p.DefaultPreferences()
|
||||||
p.savePreferences(pf)
|
p.savePreferences(&pf)
|
||||||
return p.flatPreferences(pf, "")
|
return pf
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import "tinyrdm/backend/consts"
|
||||||
|
|
||||||
|
type Preferences struct {
|
||||||
|
Behavior PreferencesBehavior `json:"behavior" yaml:"behavior"`
|
||||||
|
General PreferencesGeneral `json:"general" yaml:"general"`
|
||||||
|
Editor PreferencesEditor `json:"editor" yaml:"editor"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPreferences() Preferences {
|
||||||
|
return Preferences{
|
||||||
|
Behavior: PreferencesBehavior{
|
||||||
|
AsideWidth: consts.DEFAULT_ASIDE_WIDTH,
|
||||||
|
WindowWidth: consts.DEFAULT_WINDOW_WIDTH,
|
||||||
|
WindowHeight: consts.DEFAULT_WINDOW_HEIGHT,
|
||||||
|
},
|
||||||
|
General: PreferencesGeneral{
|
||||||
|
Theme: "auto",
|
||||||
|
Language: "auto",
|
||||||
|
FontSize: consts.DEFAULT_FONT_SIZE,
|
||||||
|
CheckUpdate: true,
|
||||||
|
},
|
||||||
|
Editor: PreferencesEditor{
|
||||||
|
FontSize: consts.DEFAULT_FONT_SIZE,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PreferencesBehavior struct {
|
||||||
|
AsideWidth int `json:"asideWidth" yaml:"aside_width"`
|
||||||
|
WindowWidth int `json:"windowWidth" yaml:"window_width"`
|
||||||
|
WindowHeight int `json:"windowHeight" yaml:"window_height"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PreferencesGeneral struct {
|
||||||
|
Theme string `json:"theme" yaml:"theme"`
|
||||||
|
Language string `json:"language" yaml:"language"`
|
||||||
|
Font string `json:"font" yaml:"font,omitempty"`
|
||||||
|
FontSize int `json:"fontSize" yaml:"font_size"`
|
||||||
|
UseSysProxy bool `json:"useSysProxy" yaml:"use_sys_proxy,omitempty"`
|
||||||
|
UseSysProxyHttp bool `json:"useSysProxyHttp" yaml:"use_sys_proxy_http,omitempty"`
|
||||||
|
CheckUpdate bool `json:"checkUpdate" yaml:"check_update"`
|
||||||
|
SkipVersion string `json:"skipVersion" yaml:"skip_version,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PreferencesEditor struct {
|
||||||
|
Font string `json:"font" yaml:"font,omitempty"`
|
||||||
|
FontSize int `json:"fontSize" yaml:"font_size"`
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { lang } from '@/langs/index.js'
|
import { lang } from '@/langs/index.js'
|
||||||
import { camelCase, clone, find, get, isEmpty, isObject, map, set, snakeCase, split } from 'lodash'
|
import { clone, find, get, isEmpty, map, pick, set, split } from 'lodash'
|
||||||
import {
|
import {
|
||||||
CheckForUpdate,
|
CheckForUpdate,
|
||||||
GetFontList,
|
GetFontList,
|
||||||
|
@ -165,8 +165,7 @@ const usePreferencesStore = defineStore('preferences', {
|
||||||
actions: {
|
actions: {
|
||||||
_applyPreferences(data) {
|
_applyPreferences(data) {
|
||||||
for (const key in data) {
|
for (const key in data) {
|
||||||
const keys = map(split(key, '.'), camelCase)
|
set(this, key, data[key])
|
||||||
set(this, keys, data[key])
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -203,30 +202,13 @@ const usePreferencesStore = defineStore('preferences', {
|
||||||
* @returns {Promise<boolean>}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
async savePreferences() {
|
async savePreferences() {
|
||||||
const obj2Map = (prefix, obj) => {
|
const pf = pick(this, ['behavior', 'general', 'editor'])
|
||||||
const result = {}
|
|
||||||
for (const key in obj) {
|
|
||||||
if (isObject(obj[key])) {
|
|
||||||
const subResult = obj2Map(`${prefix}.${snakeCase(key)}`, obj[key])
|
|
||||||
Object.assign(result, subResult)
|
|
||||||
} else {
|
|
||||||
result[`${prefix}.${snakeCase(key)}`] = obj[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
const pf = Object.assign(
|
|
||||||
{},
|
|
||||||
obj2Map('behavior', this.behavior),
|
|
||||||
obj2Map('general', this.general),
|
|
||||||
obj2Map('editor', this.editor),
|
|
||||||
)
|
|
||||||
const { success, msg } = await SetPreferences(pf)
|
const { success, msg } = await SetPreferences(pf)
|
||||||
return success === true
|
return success === true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reset to last loaded preferences
|
* reset to last-loaded preferences
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async resetToLastPreferences() {
|
async resetToLastPreferences() {
|
||||||
|
|
Loading…
Reference in New Issue