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
|
||||
}
|
||||
|
||||
func (p *preferencesService) SetPreferences(values map[string]any) (resp types.JSResp) {
|
||||
err := p.pref.SetPreferencesN(values)
|
||||
func (p *preferencesService) SetPreferences(pf types.Preferences) (resp types.JSResp) {
|
||||
err := p.pref.SetPreferences(&pf)
|
||||
if err != nil {
|
||||
resp.Msg = err.Error()
|
||||
return
|
||||
|
@ -50,6 +50,16 @@ func (p *preferencesService) SetPreferences(values map[string]any) (resp types.J
|
|||
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) {
|
||||
defaultPref := p.pref.RestoreDefault()
|
||||
resp.Data = map[string]any{
|
||||
|
@ -103,21 +113,20 @@ func (p *preferencesService) GetAppVersion() (resp types.JSResp) {
|
|||
}
|
||||
|
||||
func (p *preferencesService) SaveWindowSize(width, height int) {
|
||||
p.SetPreferences(map[string]any{
|
||||
"behavior.window_width": width,
|
||||
"behavior.window_height": height,
|
||||
p.UpdatePreferences(map[string]any{
|
||||
"behavior.windowWidth": width,
|
||||
"behavior.windowHeight": height,
|
||||
})
|
||||
}
|
||||
|
||||
func (p *preferencesService) GetWindowSize() (width, height int) {
|
||||
data := p.pref.GetPreferences()
|
||||
w, h := data["behavior.window_width"], data["behavior.window_height"]
|
||||
var ok bool
|
||||
if width, ok = w.(int); !ok {
|
||||
return consts.DEFAULT_WINDOW_WIDTH, consts.DEFAULT_WINDOW_HEIGHT
|
||||
width, height = data.Behavior.WindowWidth, data.Behavior.WindowHeight
|
||||
if width <= 0 {
|
||||
width = consts.DEFAULT_WINDOW_WIDTH
|
||||
}
|
||||
if height, ok = h.(int); !ok {
|
||||
return consts.DEFAULT_WINDOW_WIDTH, consts.DEFAULT_WINDOW_HEIGHT
|
||||
if height <= 0 {
|
||||
height = consts.DEFAULT_WINDOW_HEIGHT
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -4,9 +4,10 @@ import (
|
|||
"fmt"
|
||||
"gopkg.in/yaml.v3"
|
||||
"log"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"tinyrdm/backend/consts"
|
||||
"tinyrdm/backend/types"
|
||||
)
|
||||
|
||||
type PreferencesStorage struct {
|
||||
|
@ -20,30 +21,11 @@ func NewPreferences() *PreferencesStorage {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *PreferencesStorage) DefaultPreferences() map[string]any {
|
||||
return map[string]any{
|
||||
"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) DefaultPreferences() types.Preferences {
|
||||
return types.NewPreferences()
|
||||
}
|
||||
|
||||
func (p *PreferencesStorage) getPreferences() (ret map[string]any) {
|
||||
func (p *PreferencesStorage) getPreferences() (ret types.Preferences) {
|
||||
b, err := p.storage.Load()
|
||||
if err != nil {
|
||||
ret = p.DefaultPreferences()
|
||||
|
@ -57,79 +39,43 @@ func (p *PreferencesStorage) getPreferences() (ret map[string]any) {
|
|||
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
|
||||
func (p *PreferencesStorage) GetPreferences() (ret map[string]any) {
|
||||
func (p *PreferencesStorage) GetPreferences() (ret types.Preferences) {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
|
||||
pref := p.getPreferences()
|
||||
ret = p.flatPreferences(pref, "")
|
||||
ret = p.getPreferences()
|
||||
return
|
||||
}
|
||||
|
||||
func (p *PreferencesStorage) Value(keys ...string) any {
|
||||
kv := p.getPreferences()
|
||||
var ok bool
|
||||
var a any
|
||||
total := len(keys)
|
||||
for i, key := range keys {
|
||||
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]
|
||||
func (p *PreferencesStorage) setPreferences(pf *types.Preferences, key string, value any) error {
|
||||
parts := strings.Split(key, ".")
|
||||
if len(parts) > 0 {
|
||||
var reflectValue reflect.Value
|
||||
if reflect.TypeOf(pf).Kind() == reflect.Ptr {
|
||||
reflectValue = reflect.ValueOf(pf).Elem()
|
||||
} 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:]
|
||||
reflectValue = reflectValue.FieldByName(part)
|
||||
if reflectValue.IsValid() {
|
||||
if i == len(parts)-1 {
|
||||
reflectValue.Set(reflect.ValueOf(value))
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if subNode, ok := node.(map[string]any); ok {
|
||||
subNode[keyPath[len(keyPath)-1]] = value
|
||||
}
|
||||
|
||||
return nil
|
||||
return fmt.Errorf("invalid key path(%s)", key)
|
||||
}
|
||||
|
||||
func (p *PreferencesStorage) savePreferences(pf map[string]any) error {
|
||||
b, err := yaml.Marshal(&pf)
|
||||
func (p *PreferencesStorage) savePreferences(pf *types.Preferences) error {
|
||||
b, err := yaml.Marshal(pf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -140,37 +86,35 @@ func (p *PreferencesStorage) savePreferences(pf map[string]any) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// SetPreferences assign value to key path, the key path use "." to indicate multiple level
|
||||
func (p *PreferencesStorage) SetPreferences(key string, value any) error {
|
||||
// SetPreferences replace preferences
|
||||
func (p *PreferencesStorage) SetPreferences(pf *types.Preferences) error {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
|
||||
pf := p.getPreferences()
|
||||
if err := p.setPreferences(pf, key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
return p.savePreferences(pf)
|
||||
}
|
||||
|
||||
// SetPreferencesN set multiple key path and value
|
||||
func (p *PreferencesStorage) SetPreferencesN(values map[string]any) error {
|
||||
// UpdatePreferences update values by key paths, the key path use "." to indicate multiple level
|
||||
func (p *PreferencesStorage) UpdatePreferences(values map[string]any) error {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
|
||||
pf := p.getPreferences()
|
||||
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
|
||||
}
|
||||
}
|
||||
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()
|
||||
p.savePreferences(pf)
|
||||
return p.flatPreferences(pf, "")
|
||||
p.savePreferences(&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 { 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 {
|
||||
CheckForUpdate,
|
||||
GetFontList,
|
||||
|
@ -165,8 +165,7 @@ const usePreferencesStore = defineStore('preferences', {
|
|||
actions: {
|
||||
_applyPreferences(data) {
|
||||
for (const key in data) {
|
||||
const keys = map(split(key, '.'), camelCase)
|
||||
set(this, keys, data[key])
|
||||
set(this, key, data[key])
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -203,30 +202,13 @@ const usePreferencesStore = defineStore('preferences', {
|
|||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async savePreferences() {
|
||||
const obj2Map = (prefix, obj) => {
|
||||
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 pf = pick(this, ['behavior', 'general', 'editor'])
|
||||
const { success, msg } = await SetPreferences(pf)
|
||||
return success === true
|
||||
},
|
||||
|
||||
/**
|
||||
* reset to last loaded preferences
|
||||
* reset to last-loaded preferences
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async resetToLastPreferences() {
|
||||
|
|
Loading…
Reference in New Issue