You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
synctv/internal/settings/string.go

227 lines
4.4 KiB
Go

package settings
import (
"fmt"
"sync"
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/model"
)
type StringSetting interface {
Setting
Set(string) error
Get() string
Default() string
Parse(string) (string, error)
Stringify(string) string
SetBeforeInit(func(StringSetting, string) (string, error))
SetBeforeSet(func(StringSetting, string) (string, error))
}
var _ StringSetting = (*String)(nil)
type String struct {
setting
defaultValue string
lock sync.RWMutex
value string
validator func(string) error
beforeInit, beforeSet func(StringSetting, string) (string, error)
}
type StringSettingOption func(*String)
func WithInitPriorityString(priority int) StringSettingOption {
return func(s *String) {
s.SetInitPriority(priority)
}
}
func WithValidatorString(validator func(string) error) StringSettingOption {
return func(s *String) {
s.validator = validator
}
}
func WithBeforeInitString(beforeInit func(StringSetting, string) (string, error)) StringSettingOption {
return func(s *String) {
s.SetBeforeInit(beforeInit)
}
}
func WithBeforeSetString(beforeSet func(StringSetting, string) (string, error)) StringSettingOption {
return func(s *String) {
s.SetBeforeSet(beforeSet)
}
}
func newString(name string, value string, group model.SettingGroup, options ...StringSettingOption) *String {
s := &String{
setting: setting{
name: name,
group: group,
settingType: model.SettingTypeString,
},
defaultValue: value,
value: value,
}
for _, option := range options {
option(s)
}
return s
}
func (s *String) SetInitPriority(priority int) {
s.initPriority = priority
}
func (s *String) SetBeforeInit(beforeInit func(StringSetting, string) (string, error)) {
s.beforeInit = beforeInit
}
func (s *String) SetBeforeSet(beforeSet func(StringSetting, string) (string, error)) {
s.beforeSet = beforeSet
}
func (s *String) Parse(value string) (string, error) {
if s.validator != nil {
return value, s.validator(value)
}
return value, nil
}
func (s *String) Stringify(value string) string {
return value
}
func (s *String) Init(value string) error {
v, err := s.Parse(value)
if err != nil {
return err
}
if s.beforeInit != nil {
v, err = s.beforeInit(s, v)
if err != nil {
return err
}
}
s.set(v)
return nil
}
func (s *String) Default() string {
return s.defaultValue
}
func (s *String) DefaultString() string {
return s.Stringify(s.defaultValue)
}
func (s *String) DefaultInterface() any {
return s.Default()
}
func (s *String) String() string {
return s.Stringify(s.Get())
}
func (s *String) SetString(value string) error {
v, err := s.Parse(value)
if err != nil {
return err
}
if s.beforeSet != nil {
v, err = s.beforeSet(s, v)
if err != nil {
return err
}
}
err = db.UpdateSettingItemValue(s.name, s.Stringify(v))
if err != nil {
return err
}
s.set(v)
return nil
}
func (s *String) set(value string) {
s.lock.Lock()
defer s.lock.Unlock()
s.value = value
}
func (s *String) Set(v string) (err error) {
if s.validator != nil {
err = s.validator(v)
if err != nil {
return err
}
}
if s.beforeSet != nil {
v, err = s.beforeSet(s, v)
if err != nil {
return err
}
}
err = db.UpdateSettingItemValue(s.name, s.Stringify(v))
if err != nil {
return err
}
s.set(v)
return
}
func (s *String) Get() string {
s.lock.RLock()
defer s.lock.RUnlock()
return s.value
}
func (s *String) Interface() any {
return s.Get()
}
func NewStringSetting(k string, v string, g model.SettingGroup, options ...StringSettingOption) StringSetting {
_, loaded := Settings[k]
if loaded {
panic(fmt.Sprintf("setting %s already exists", k))
}
return CoverStringSetting(k, v, g, options...)
}
func CoverStringSetting(k string, v string, g model.SettingGroup, options ...StringSettingOption) StringSetting {
s := newString(k, v, g, options...)
Settings[k] = s
if GroupSettings[g] == nil {
GroupSettings[g] = make(map[string]Setting)
}
GroupSettings[g][k] = s
return s
}
func LoadStringSetting(k string) (StringSetting, bool) {
s, ok := Settings[k]
if !ok {
return nil, false
}
ss, ok := s.(StringSetting)
return ss, ok
}
func LoadOrNewStringSetting(k string, v string, g model.SettingGroup, options ...StringSettingOption) StringSetting {
s, ok := LoadStringSetting(k)
if ok {
return s
}
return NewStringSetting(k, v, g, options...)
}