mirror of https://github.com/Wox-launcher/Wox
refactor(setting): unify setting store architecture and introduce type-safe value wrappers
- Split Store into separate WoxSettingStore and PluginSettingStore with unified SettingStore interface - Introduce SettingValue[T] and WoxSettingValue[T] generic wrappers for type-safe setting access - Refactor PluginSetting to use PluginSettingValue[T] wrappers instead of direct field access - Remove redundant plugin_setting_test.go and consolidate setting management logic - Update plugin API, manager, and UI components to work with new setting architecture - Simplify setting store operations and improve separation of concerns between core and plugin settings This refactoring provides better type safety, cleaner separation between different setting types, and a more maintainable architecture for future setting system enhancements.
This commit is contained in:
parent
405346cc09
commit
734d0f0830
|
@ -206,7 +206,7 @@ func Run(ctx context.Context) error {
|
|||
}
|
||||
}()
|
||||
|
||||
store := setting.NewStore(tx)
|
||||
woxSettingStore := setting.NewWoxSettingStore(tx)
|
||||
|
||||
// Migrate simple settings
|
||||
settingsToMigrate := map[string]interface{}{
|
||||
|
@ -241,7 +241,7 @@ func Run(ctx context.Context) error {
|
|||
util.GetLogger().Info(ctx, fmt.Sprintf("migrating %d core settings", len(settingsToMigrate)))
|
||||
for key, value := range settingsToMigrate {
|
||||
util.GetLogger().Info(ctx, fmt.Sprintf("migrating setting %s", key))
|
||||
if err := store.Set(key, value); err != nil {
|
||||
if err := woxSettingStore.Set(key, value); err != nil {
|
||||
return fmt.Errorf("failed to migrate setting %s: %w", key, err)
|
||||
}
|
||||
}
|
||||
|
@ -262,6 +262,8 @@ func Run(ctx context.Context) error {
|
|||
}
|
||||
|
||||
pluginId := strings.TrimSuffix(file.Name(), ".json")
|
||||
pluginSettingStore := setting.NewPluginSettingStore(tx, pluginId)
|
||||
|
||||
pluginJsonPath := path.Join(pluginDir, file.Name())
|
||||
if _, err := os.Stat(pluginJsonPath); err != nil {
|
||||
continue
|
||||
|
@ -285,7 +287,7 @@ func Run(ctx context.Context) error {
|
|||
if value == "" {
|
||||
continue
|
||||
}
|
||||
if err := store.SetPluginSetting(pluginId, key, value); err != nil {
|
||||
if err := pluginSettingStore.Set(key, value); err != nil {
|
||||
util.GetLogger().Warn(ctx, fmt.Sprintf("failed to migrate plugin setting %s for %s: %v", key, pluginId, err))
|
||||
continue
|
||||
}
|
||||
|
@ -302,7 +304,7 @@ func Run(ctx context.Context) error {
|
|||
// Migrate query history
|
||||
if len(oldAppData.QueryHistories) > 0 {
|
||||
util.GetLogger().Info(ctx, fmt.Sprintf("migrating %d query histories", len(oldAppData.QueryHistories)))
|
||||
if err := store.Set("QueryHistories", oldAppData.QueryHistories); err != nil {
|
||||
if err := woxSettingStore.Set("QueryHistories", oldAppData.QueryHistories); err != nil {
|
||||
util.GetLogger().Warn(ctx, fmt.Sprintf("failed to migrate query histories: %v", err))
|
||||
}
|
||||
}
|
||||
|
@ -310,7 +312,7 @@ func Run(ctx context.Context) error {
|
|||
// Migrate favorite results
|
||||
if oldAppData.FavoriteResults != nil {
|
||||
util.GetLogger().Info(ctx, fmt.Sprintf("migrating %d favorite results", oldAppData.FavoriteResults.Len()))
|
||||
if err := store.Set("FavoriteResults", oldAppData.FavoriteResults); err != nil {
|
||||
if err := woxSettingStore.Set("FavoriteResults", oldAppData.FavoriteResults); err != nil {
|
||||
util.GetLogger().Warn(ctx, fmt.Sprintf("failed to migrate favorite results: %v", err))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,12 +107,12 @@ func (a *APIImpl) GetTranslation(ctx context.Context, key string) string {
|
|||
func (a *APIImpl) GetSetting(ctx context.Context, key string) string {
|
||||
// try to get platform specific setting first
|
||||
platformSpecificKey := key + "@" + util.GetCurrentPlatform()
|
||||
v, exist := a.pluginInstance.Setting.GetSetting(platformSpecificKey)
|
||||
v, exist := a.pluginInstance.Setting.Get(platformSpecificKey)
|
||||
if exist {
|
||||
return v
|
||||
}
|
||||
|
||||
v, exist = a.pluginInstance.Setting.GetSetting(key)
|
||||
v, exist = a.pluginInstance.Setting.Get(key)
|
||||
if exist {
|
||||
return v
|
||||
}
|
||||
|
@ -125,17 +125,11 @@ func (a *APIImpl) SaveSetting(ctx context.Context, key string, value string, isP
|
|||
finalKey = key + "@" + util.GetCurrentPlatform()
|
||||
} else {
|
||||
// if not platform specific, remove platform specific setting, otherwise it will be loaded first
|
||||
a.pluginInstance.Setting.Settings.Delete(key + "@" + util.GetCurrentPlatform())
|
||||
}
|
||||
|
||||
existValue, exist := a.pluginInstance.Setting.Settings.Load(finalKey)
|
||||
a.pluginInstance.Setting.Settings.Store(finalKey, value)
|
||||
saveErr := a.pluginInstance.SaveSetting(ctx)
|
||||
if saveErr != nil {
|
||||
a.logger.Error(ctx, fmt.Sprintf("failed to save setting: %s", saveErr.Error()))
|
||||
return
|
||||
a.pluginInstance.Setting.Delete(key + "@" + util.GetCurrentPlatform())
|
||||
}
|
||||
|
||||
existValue, exist := a.pluginInstance.Setting.Get(finalKey)
|
||||
a.pluginInstance.Setting.Set(finalKey, value)
|
||||
if !exist || (existValue != value) {
|
||||
for _, callback := range a.pluginInstance.SettingChangeCallbacks {
|
||||
callback(key, value)
|
||||
|
@ -165,13 +159,12 @@ func (a *APIImpl) OnUnload(ctx context.Context, callback func()) {
|
|||
}
|
||||
|
||||
func (a *APIImpl) RegisterQueryCommands(ctx context.Context, commands []MetadataCommand) {
|
||||
a.pluginInstance.Setting.QueryCommands = lo.Map(commands, func(command MetadataCommand, _ int) setting.PluginQueryCommand {
|
||||
a.pluginInstance.Setting.QueryCommands.Set(lo.Map(commands, func(command MetadataCommand, _ int) setting.PluginQueryCommand {
|
||||
return setting.PluginQueryCommand{
|
||||
Command: command.Command,
|
||||
Description: command.Description,
|
||||
}
|
||||
})
|
||||
a.pluginInstance.SaveSetting(ctx)
|
||||
}))
|
||||
}
|
||||
|
||||
func (a *APIImpl) AIChatStream(ctx context.Context, model common.Model, conversations []common.Conversation, options common.ChatOptions, callback common.ChatStreamFunc) error {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"wox/setting"
|
||||
)
|
||||
|
||||
|
@ -30,16 +29,18 @@ type Instance struct {
|
|||
|
||||
// trigger keywords to trigger this plugin. Maybe user defined or pre-defined in plugin.json
|
||||
func (i *Instance) GetTriggerKeywords() []string {
|
||||
if i.Setting.TriggerKeywords != nil {
|
||||
return i.Setting.TriggerKeywords
|
||||
var userDefinedKeywords = i.Setting.TriggerKeywords.Get()
|
||||
if len(userDefinedKeywords) > 0 {
|
||||
return userDefinedKeywords
|
||||
}
|
||||
|
||||
return i.Metadata.TriggerKeywords
|
||||
}
|
||||
|
||||
// query commands to query this plugin. Maybe plugin author dynamical registered or pre-defined in plugin.json
|
||||
func (i *Instance) GetQueryCommands() []MetadataCommand {
|
||||
commands := i.Metadata.Commands
|
||||
for _, command := range i.Setting.QueryCommands {
|
||||
for _, command := range i.Setting.QueryCommands.Get() {
|
||||
commands = append(commands, MetadataCommand{
|
||||
Command: command.Command,
|
||||
Description: command.Description,
|
||||
|
@ -51,7 +52,3 @@ func (i *Instance) GetQueryCommands() []MetadataCommand {
|
|||
func (i *Instance) String() string {
|
||||
return i.Metadata.Name
|
||||
}
|
||||
|
||||
func (i *Instance) SaveSetting(ctx context.Context) error {
|
||||
return setting.GetSettingManager().SavePluginSetting(ctx, i.Metadata.Id, i.Setting)
|
||||
}
|
||||
|
|
|
@ -281,7 +281,7 @@ func (m *Manager) loadHostPlugin(ctx context.Context, host Host, metadata Metada
|
|||
DevPluginDirectory: metadata.DevPluginDirectory,
|
||||
}
|
||||
instance.API = NewAPI(instance)
|
||||
pluginSetting, settingErr := setting.GetSettingManager().LoadPluginSetting(ctx, metadata.Metadata.Id, metadata.Metadata.Name, metadata.Metadata.SettingDefinitions.ToMap())
|
||||
pluginSetting, settingErr := setting.GetSettingManager().LoadPluginSetting(ctx, metadata.Metadata.Id, metadata.Metadata.SettingDefinitions.ToMap())
|
||||
if settingErr != nil {
|
||||
instance.API.Log(ctx, LogLevelError, fmt.Errorf("[SYS] failed to load plugin[%s] setting: %w", metadata.Metadata.Name, settingErr).Error())
|
||||
return settingErr
|
||||
|
@ -290,7 +290,7 @@ func (m *Manager) loadHostPlugin(ctx context.Context, host Host, metadata Metada
|
|||
|
||||
m.instances = append(m.instances, instance)
|
||||
|
||||
if pluginSetting.Disabled {
|
||||
if pluginSetting.Disabled.Get() {
|
||||
logger.Info(ctx, fmt.Errorf("[%s HOST] plugin is disabled by user, skip init: %s", host.GetRuntime(ctx), metadata.Metadata.Name).Error())
|
||||
instance.API.Log(ctx, LogLevelWarning, fmt.Sprintf("[SYS] plugin is disabled by user, skip init: %s", metadata.Metadata.Name))
|
||||
return nil
|
||||
|
@ -357,15 +357,12 @@ func (m *Manager) loadSystemPlugins(ctx context.Context) {
|
|||
instance.API = NewAPI(instance)
|
||||
|
||||
startTimestamp := util.GetSystemTimestamp()
|
||||
pluginSetting, settingErr := setting.GetSettingManager().LoadPluginSetting(ctx, metadata.Id, metadata.Name, metadata.SettingDefinitions.ToMap())
|
||||
pluginSetting, settingErr := setting.GetSettingManager().LoadPluginSetting(ctx, metadata.Id, metadata.SettingDefinitions.ToMap())
|
||||
if settingErr != nil {
|
||||
errMsg := fmt.Sprintf("failed to load system plugin[%s] setting, use default plugin setting. err: %s", metadata.Name, settingErr.Error())
|
||||
logger.Error(ctx, errMsg)
|
||||
instance.API.Log(ctx, LogLevelError, fmt.Sprintf("[SYS] %s", errMsg))
|
||||
pluginSetting = &setting.PluginSetting{
|
||||
Settings: util.NewHashMap[string, string](),
|
||||
}
|
||||
logger.Error(ctx, fmt.Sprintf("failed to load system plugin[%s] setting, use default plugin setting. err: %s", metadata.Name, settingErr.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
instance.Setting = pluginSetting
|
||||
if util.GetSystemTimestamp()-startTimestamp > 100 {
|
||||
logger.Warn(ctx, fmt.Sprintf("load system plugin[%s] setting too slow, cost %d ms", metadata.Name, util.GetSystemTimestamp()-startTimestamp))
|
||||
|
@ -695,7 +692,7 @@ func (m *Manager) GetPluginInstances() []*Instance {
|
|||
}
|
||||
|
||||
func (m *Manager) canOperateQuery(ctx context.Context, pluginInstance *Instance, query Query) bool {
|
||||
if pluginInstance.Setting.Disabled {
|
||||
if pluginInstance.Setting.Disabled.Get() {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ var logger *util.Log
|
|||
|
||||
type Manager struct {
|
||||
woxSetting *WoxSetting
|
||||
store *Store
|
||||
}
|
||||
|
||||
func GetSettingManager() *Manager {
|
||||
|
@ -28,18 +27,14 @@ func GetSettingManager() *Manager {
|
|||
panic("database not initialized")
|
||||
}
|
||||
|
||||
store := NewStore(db)
|
||||
managerInstance = &Manager{
|
||||
store: store,
|
||||
}
|
||||
store := NewWoxSettingStore(db)
|
||||
managerInstance = &Manager{}
|
||||
managerInstance.woxSetting = NewWoxSetting(store)
|
||||
})
|
||||
return managerInstance
|
||||
}
|
||||
|
||||
func (m *Manager) Init(ctx context.Context) error {
|
||||
// Initialization is now handled by GetSettingManager and lazy-loading in Value[T].
|
||||
// We just need to kick off any background processes.
|
||||
m.StartAutoBackup(ctx)
|
||||
|
||||
if err := m.checkAutostart(ctx); err != nil {
|
||||
|
@ -96,41 +91,12 @@ func (m *Manager) GetLatestQueryHistory(ctx context.Context, limit int) []common
|
|||
return result
|
||||
}
|
||||
|
||||
func (m *Manager) LoadPluginSetting(ctx context.Context, pluginId string, pluginName string, defaultSettings map[string]string) (*PluginSetting, error) {
|
||||
pluginSetting := &PluginSetting{
|
||||
Name: pluginName,
|
||||
Settings: util.NewHashMap[string, string](),
|
||||
}
|
||||
|
||||
// Load default settings first
|
||||
for key, value := range defaultSettings {
|
||||
pluginSetting.Settings.Store(key, value)
|
||||
}
|
||||
|
||||
actualSettings, err := m.store.GetAllPluginSettings(pluginId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load plugin settings: %w", err)
|
||||
}
|
||||
|
||||
// Override defaults with actual settings
|
||||
for key, value := range actualSettings {
|
||||
pluginSetting.Settings.Store(key, value)
|
||||
}
|
||||
|
||||
func (m *Manager) LoadPluginSetting(ctx context.Context, pluginId string, defaultSettings map[string]string) (*PluginSetting, error) {
|
||||
pluginSettingStore := NewPluginSettingStore(database.GetDB(), pluginId)
|
||||
pluginSetting := NewPluginSetting(pluginSettingStore, defaultSettings)
|
||||
return pluginSetting, nil
|
||||
}
|
||||
|
||||
func (m *Manager) SavePluginSetting(ctx context.Context, pluginId string, pluginSetting *PluginSetting) error {
|
||||
settings := make(map[string]string)
|
||||
|
||||
pluginSetting.Settings.Range(func(key string, value string) bool {
|
||||
settings[key] = value
|
||||
return true
|
||||
})
|
||||
|
||||
return m.store.SetAllPluginSettings(pluginId, settings)
|
||||
}
|
||||
|
||||
func (m *Manager) AddActionedResult(ctx context.Context, pluginId string, resultTitle string, resultSubTitle string, query string) {
|
||||
resultHash := NewResultHash(pluginId, resultTitle, resultSubTitle)
|
||||
actionedResult := ActionedResult{
|
||||
|
|
|
@ -1,37 +1,58 @@
|
|||
package setting
|
||||
|
||||
import (
|
||||
"wox/util"
|
||||
)
|
||||
|
||||
type PluginQueryCommand struct {
|
||||
Command string
|
||||
Description string
|
||||
}
|
||||
|
||||
type PluginSetting struct {
|
||||
Name string // readonly, for display purpose
|
||||
|
||||
// Is this plugin disabled by user
|
||||
Disabled bool
|
||||
Disabled *PluginSettingValue[bool]
|
||||
|
||||
// User defined keywords, will be used to trigger this plugin. User may not set custom trigger keywords, which will cause this property to be null
|
||||
//
|
||||
// So don't use this property directly, use Instance.TriggerKeywords instead
|
||||
TriggerKeywords []string
|
||||
TriggerKeywords *PluginSettingValue[[]string]
|
||||
|
||||
// plugin author can register query command dynamically
|
||||
// the final query command will be the combination of plugin's metadata commands defined in plugin.json and customized query command registered here
|
||||
//
|
||||
// So don't use this directly, use Instance.GetQueryCommands instead
|
||||
QueryCommands []PluginQueryCommand
|
||||
QueryCommands *PluginSettingValue[[]PluginQueryCommand]
|
||||
|
||||
Settings *util.HashMap[string, string]
|
||||
store *PluginSettingStore
|
||||
defaultSettingsInMetadata map[string]string
|
||||
}
|
||||
|
||||
func (p *PluginSetting) GetSetting(key string) (string, bool) {
|
||||
if p.Settings == nil {
|
||||
func NewPluginSetting(store *PluginSettingStore, defaultSettingsInMetadata map[string]string) *PluginSetting {
|
||||
return &PluginSetting{
|
||||
store: store,
|
||||
defaultSettingsInMetadata: defaultSettingsInMetadata,
|
||||
Disabled: NewPluginSettingValue(store, "Disabled", false),
|
||||
TriggerKeywords: NewPluginSettingValue(store, "TriggerKeywords", []string{}),
|
||||
QueryCommands: NewPluginSettingValue(store, "QueryCommands", []PluginQueryCommand{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Try to get the value of the setting. If the setting is not found, return the default value in metadata if exist, otherwise return empty string
|
||||
func (p *PluginSetting) Get(key string) (string, bool) {
|
||||
var val string
|
||||
err := p.store.Get(key, &val)
|
||||
if err != nil {
|
||||
if val, ok := p.defaultSettingsInMetadata[key]; ok {
|
||||
return val, true
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
return p.Settings.Load(key)
|
||||
|
||||
return val, true
|
||||
}
|
||||
|
||||
func (p *PluginSetting) Set(key string, value string) error {
|
||||
return p.store.Set(key, value)
|
||||
}
|
||||
|
||||
func (p *PluginSetting) Delete(key string) error {
|
||||
return p.store.Delete(key)
|
||||
}
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
package setting
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"wox/setting/definition"
|
||||
"wox/util"
|
||||
)
|
||||
|
||||
func TestUnMarshalPluginSettingItem(t *testing.T) {
|
||||
type metadataForTest struct {
|
||||
SettingDefinitions definition.PluginSettingDefinitions
|
||||
}
|
||||
|
||||
jsonStr := `
|
||||
{
|
||||
"SettingDefinitions":[
|
||||
{
|
||||
"Type":"head",
|
||||
"Value":{
|
||||
"Content":"This is head title"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type":"textbox",
|
||||
"Value":{
|
||||
"Key":"IndexDirectories",
|
||||
"DefaultValue":"test;test1",
|
||||
"Label":"Index Directories: ",
|
||||
"Suffix":" (separate by ';')"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type":"checkbox",
|
||||
"Value":{
|
||||
"Key":"OnlyIndexTxt",
|
||||
"DefaultValue": "true",
|
||||
"Label":", Only Index Txt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type":"select",
|
||||
"Value":{
|
||||
"Key":"IndexPrograms",
|
||||
"DefaultValue":"true",
|
||||
"Label":"Index Programs: ",
|
||||
"Options":[
|
||||
{"Label":"true", "Value":"true"},
|
||||
{"Label":"false", "Value":"false"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type":"newline",
|
||||
"Value":{}
|
||||
},
|
||||
{
|
||||
"Type":"label",
|
||||
"Value":{
|
||||
"Content":"IndexPrograms"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
var metadata metadataForTest
|
||||
err := json.Unmarshal([]byte(jsonStr), &metadata)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(metadata.SettingDefinitions), 6)
|
||||
assert.Equal(t, metadata.SettingDefinitions[0].Type, definition.PluginSettingDefinitionTypeHead)
|
||||
assert.Equal(t, metadata.SettingDefinitions[1].Type, definition.PluginSettingDefinitionTypeTextBox)
|
||||
assert.Equal(t, metadata.SettingDefinitions[2].Type, definition.PluginSettingDefinitionTypeCheckBox)
|
||||
assert.Equal(t, metadata.SettingDefinitions[3].Type, definition.PluginSettingDefinitionTypeSelect)
|
||||
assert.Equal(t, metadata.SettingDefinitions[4].Type, definition.PluginSettingDefinitionTypeNewLine)
|
||||
assert.Equal(t, metadata.SettingDefinitions[5].Type, definition.PluginSettingDefinitionTypeLabel)
|
||||
assert.Equal(t, len(metadata.SettingDefinitions[3].Value.(*definition.PluginSettingValueSelect).Options), 2)
|
||||
|
||||
val, exist := metadata.SettingDefinitions.GetDefaultValue("IndexDirectories")
|
||||
assert.True(t, exist)
|
||||
assert.Equal(t, val, "test;test1")
|
||||
|
||||
_, marshalErr := json.Marshal(metadata)
|
||||
assert.Nil(t, marshalErr)
|
||||
}
|
||||
|
||||
func TestMarshalPluginSetting(t *testing.T) {
|
||||
var h = util.NewHashMap[string, string]()
|
||||
h.Store("test", "test")
|
||||
h.Store("test1", "test")
|
||||
|
||||
ps := PluginSetting{
|
||||
Disabled: true,
|
||||
TriggerKeywords: nil,
|
||||
Settings: h,
|
||||
}
|
||||
|
||||
marshalData, marshalErr := json.Marshal(ps)
|
||||
assert.Nil(t, marshalErr)
|
||||
t.Log(string(marshalData))
|
||||
|
||||
var ps1 PluginSetting
|
||||
err := json.Unmarshal(marshalData, &ps1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, ps.Disabled, ps1.Disabled)
|
||||
assert.Equal(t, ps1.Settings.Len(), 2)
|
||||
}
|
|
@ -3,7 +3,6 @@ package setting
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
@ -13,57 +12,53 @@ import (
|
|||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// WoxSettingStore defines the unified interface for reading and writing settings
|
||||
type WoxSettingStore interface {
|
||||
// SettingStore defines the abstract interface for reading and writing settings
|
||||
// This is the base interface that both WoxSettingStore and PluginSettingStore adapters implement
|
||||
type SettingStore interface {
|
||||
Get(key string, target interface{}) error
|
||||
Set(key string, value interface{}) error
|
||||
Delete(key string) error
|
||||
}
|
||||
|
||||
type SynableStore interface {
|
||||
LogOplog(key string, value interface{}) error
|
||||
}
|
||||
|
||||
// PluginSettingStore defines the interface for plugin settings
|
||||
type PluginSettingStore interface {
|
||||
GetPluginSetting(pluginId, key string, target interface{}) error
|
||||
SetPluginSetting(pluginId, key string, value interface{}) error
|
||||
GetAllPluginSettings(pluginId string) (map[string]string, error)
|
||||
SetAllPluginSettings(pluginId string, settings map[string]string) error
|
||||
}
|
||||
|
||||
type Store struct {
|
||||
type WoxSettingStore struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewStore(db *gorm.DB) *Store {
|
||||
return &Store{
|
||||
func NewWoxSettingStore(db *gorm.DB) *WoxSettingStore {
|
||||
return &WoxSettingStore{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Store) Get(key string, target interface{}) error {
|
||||
func (s *WoxSettingStore) Get(key string, target interface{}) error {
|
||||
var setting database.WoxSetting
|
||||
if err := s.db.Where("key = ?", key).First(&setting).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// Return the default value (target should already contain it)
|
||||
return nil
|
||||
}
|
||||
logger.Error(context.Background(), fmt.Sprintf("Failed to read setting %s: %v", key, err))
|
||||
logger.Error(context.Background(), fmt.Sprintf("Failed to read wox setting %s: %v", key, err))
|
||||
return err
|
||||
}
|
||||
|
||||
return s.deserializeValue(setting.Value, target)
|
||||
return deserializeValue(setting.Value, target)
|
||||
}
|
||||
|
||||
func (s *Store) Set(key string, value interface{}) error {
|
||||
strValue, err := s.serializeValue(value)
|
||||
func (s *WoxSettingStore) Set(key string, value interface{}) error {
|
||||
strValue, err := serializeValue(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to serialize value: %w", err)
|
||||
}
|
||||
|
||||
// Use GORM's Save for upsert behavior
|
||||
return s.db.Save(&database.WoxSetting{Key: key, Value: strValue}).Error
|
||||
}
|
||||
|
||||
func (s *Store) LogOplog(key string, value interface{}) error {
|
||||
strValue, err := s.serializeValue(value)
|
||||
func (s *WoxSettingStore) Delete(key string) error {
|
||||
return s.db.Delete(&database.WoxSetting{Key: key}).Error
|
||||
}
|
||||
|
||||
func (s *WoxSettingStore) LogOplog(key string, value interface{}) error {
|
||||
strValue, err := serializeValue(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to serialize value for oplog: %w", err)
|
||||
}
|
||||
|
@ -79,66 +74,43 @@ func (s *Store) LogOplog(key string, value interface{}) error {
|
|||
return s.db.Create(&oplog).Error
|
||||
}
|
||||
|
||||
func (s *Store) GetPluginSetting(pluginId, key string, target interface{}) error {
|
||||
// PluginSettingStore defines the interface for plugin settings
|
||||
type PluginSettingStore struct {
|
||||
db *gorm.DB
|
||||
pluginId string
|
||||
}
|
||||
|
||||
func NewPluginSettingStore(db *gorm.DB, pluginId string) *PluginSettingStore {
|
||||
return &PluginSettingStore{
|
||||
db: db,
|
||||
pluginId: pluginId,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PluginSettingStore) Get(key string, target interface{}) error {
|
||||
var setting database.PluginSetting
|
||||
if err := s.db.Where("plugin_id = ? AND key = ?", pluginId, key).First(&setting).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// Return the default value (target should already contain it)
|
||||
return nil
|
||||
}
|
||||
logger.Error(context.Background(), fmt.Sprintf("Failed to read plugin setting %s.%s: %v", pluginId, key, err))
|
||||
if err := s.db.Where("plugin_id = ? AND key = ?", s.pluginId, key).First(&setting).Error; err != nil {
|
||||
logger.Error(context.Background(), fmt.Sprintf("Failed to read plugin setting %s.%s: %v", s.pluginId, key, err))
|
||||
return err
|
||||
}
|
||||
|
||||
return s.deserializeValue(setting.Value, target)
|
||||
return deserializeValue(setting.Value, target)
|
||||
}
|
||||
|
||||
func (s *Store) SetPluginSetting(pluginId, key string, value interface{}) error {
|
||||
strValue, err := s.serializeValue(value)
|
||||
func (s *PluginSettingStore) Set(key string, value interface{}) error {
|
||||
strValue, err := serializeValue(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to serialize plugin setting value: %w", err)
|
||||
}
|
||||
|
||||
// Use GORM's Save for upsert behavior
|
||||
return s.db.Save(&database.PluginSetting{PluginID: pluginId, Key: key, Value: strValue}).Error
|
||||
return s.db.Save(&database.PluginSetting{PluginID: s.pluginId, Key: key, Value: strValue}).Error
|
||||
}
|
||||
|
||||
func (s *Store) GetAllPluginSettings(pluginId string) (map[string]string, error) {
|
||||
var settings []database.PluginSetting
|
||||
if err := s.db.Where("plugin_id = ?", pluginId).Find(&settings).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to read plugin settings for %s: %w", pluginId, err)
|
||||
}
|
||||
|
||||
result := make(map[string]string)
|
||||
for _, setting := range settings {
|
||||
result[setting.Key] = setting.Value
|
||||
}
|
||||
return result, nil
|
||||
func (s *PluginSettingStore) Delete(key string) error {
|
||||
return s.db.Delete(&database.PluginSetting{PluginID: s.pluginId, Key: key}).Error
|
||||
}
|
||||
|
||||
func (s *Store) SetAllPluginSettings(pluginId string, settings map[string]string) error {
|
||||
return s.db.Transaction(func(tx *gorm.DB) error {
|
||||
// Clear existing settings for this plugin
|
||||
if err := tx.Where("plugin_id = ?", pluginId).Delete(&database.PluginSetting{}).Error; err != nil {
|
||||
return fmt.Errorf("failed to clear existing plugin settings: %w", err)
|
||||
}
|
||||
|
||||
// Insert new settings
|
||||
for key, value := range settings {
|
||||
if err := tx.Create(&database.PluginSetting{
|
||||
PluginID: pluginId,
|
||||
Key: key,
|
||||
Value: value,
|
||||
}).Error; err != nil {
|
||||
return fmt.Errorf("failed to save plugin setting %s.%s: %w", pluginId, key, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Store) serializeValue(value interface{}) (string, error) {
|
||||
func serializeValue(value interface{}) (string, error) {
|
||||
if value == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
@ -157,7 +129,7 @@ func (s *Store) serializeValue(value interface{}) (string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Store) deserializeValue(strValue string, target interface{}) error {
|
||||
func deserializeValue(strValue string, target interface{}) error {
|
||||
rv := reflect.ValueOf(target)
|
||||
if rv.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("target must be a pointer")
|
||||
|
|
|
@ -9,35 +9,46 @@ import (
|
|||
// ValidatorFunc is a function type for validating setting values
|
||||
type ValidatorFunc[T any] func(T) bool
|
||||
|
||||
// Value is a generic type that represents a single, observable setting.
|
||||
// SettingValue is a generic type that represents a single, observable setting.
|
||||
// It handles lazy loading and persisting of its value.
|
||||
type Value[T any] struct {
|
||||
key string
|
||||
type SettingValue[T any] struct {
|
||||
key string
|
||||
value T
|
||||
|
||||
defaultValue T
|
||||
value T
|
||||
isLoaded bool
|
||||
store WoxSettingStore
|
||||
settingStore SettingStore
|
||||
syncStore SynableStore
|
||||
validator ValidatorFunc[T]
|
||||
syncable bool
|
||||
isLoaded bool
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
type WoxSettingValue[T any] struct {
|
||||
*SettingValue[T]
|
||||
}
|
||||
|
||||
// platform specific setting value. Don't set this value directly, use get,set instead
|
||||
type PlatformValue[T any] struct {
|
||||
*Value[struct {
|
||||
*WoxSettingValue[struct {
|
||||
MacValue T
|
||||
WinValue T
|
||||
LinuxValue T
|
||||
}]
|
||||
}
|
||||
|
||||
type PluginSettingValue[T any] struct {
|
||||
*SettingValue[T]
|
||||
pluginId string
|
||||
}
|
||||
|
||||
func (p *PlatformValue[T]) Get() T {
|
||||
if util.IsWindows() {
|
||||
return p.Value.Get().WinValue
|
||||
return p.SettingValue.Get().WinValue
|
||||
} else if util.IsMacOS() {
|
||||
return p.Value.Get().MacValue
|
||||
return p.SettingValue.Get().MacValue
|
||||
} else if util.IsLinux() {
|
||||
return p.Value.Get().LinuxValue
|
||||
return p.SettingValue.Get().LinuxValue
|
||||
}
|
||||
|
||||
panic("unknown platform")
|
||||
|
@ -46,43 +57,45 @@ func (p *PlatformValue[T]) Get() T {
|
|||
func (p *PlatformValue[T]) Set(t T) {
|
||||
if util.IsWindows() {
|
||||
p.value.WinValue = t
|
||||
p.Value.Set(p.value)
|
||||
p.SettingValue.Set(p.value)
|
||||
return
|
||||
} else if util.IsMacOS() {
|
||||
p.value.MacValue = t
|
||||
p.Value.Set(p.value)
|
||||
p.SettingValue.Set(p.value)
|
||||
return
|
||||
} else if util.IsLinux() {
|
||||
p.value.LinuxValue = t
|
||||
p.Value.Set(p.value)
|
||||
p.SettingValue.Set(p.value)
|
||||
return
|
||||
}
|
||||
|
||||
panic("unknown platform")
|
||||
}
|
||||
|
||||
// NewValue creates a new setting value using the unified store interface.
|
||||
func NewValue[T any](store WoxSettingStore, key string, defaultValue T) *Value[T] {
|
||||
return &Value[T]{
|
||||
store: store,
|
||||
key: key,
|
||||
defaultValue: defaultValue,
|
||||
func NewWoxSettingValue[T any](store *WoxSettingStore, key string, defaultValue T) *WoxSettingValue[T] {
|
||||
return &WoxSettingValue[T]{
|
||||
SettingValue: &SettingValue[T]{
|
||||
settingStore: store,
|
||||
key: key,
|
||||
defaultValue: defaultValue,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewValueWithValidator creates a new setting value with a validator function using the unified store interface.
|
||||
func NewValueWithValidator[T any](store WoxSettingStore, key string, defaultValue T, validator ValidatorFunc[T]) *Value[T] {
|
||||
return &Value[T]{
|
||||
store: store,
|
||||
key: key,
|
||||
defaultValue: defaultValue,
|
||||
validator: validator,
|
||||
func NewWoxSettingValueWithValidator[T any](store *WoxSettingStore, key string, defaultValue T, validator ValidatorFunc[T]) *WoxSettingValue[T] {
|
||||
return &WoxSettingValue[T]{
|
||||
SettingValue: &SettingValue[T]{
|
||||
settingStore: store,
|
||||
key: key,
|
||||
defaultValue: defaultValue,
|
||||
validator: validator,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewPlatformValue[T any](store WoxSettingStore, key string, winValue T, macValue T, linuxValue T) *PlatformValue[T] {
|
||||
func NewPlatformValue[T any](store *WoxSettingStore, key string, winValue T, macValue T, linuxValue T) *PlatformValue[T] {
|
||||
return &PlatformValue[T]{
|
||||
Value: NewValue(store, key, struct {
|
||||
WoxSettingValue: NewWoxSettingValue(store, key, struct {
|
||||
MacValue T
|
||||
WinValue T
|
||||
LinuxValue T
|
||||
|
@ -94,8 +107,19 @@ func NewPlatformValue[T any](store WoxSettingStore, key string, winValue T, macV
|
|||
}
|
||||
}
|
||||
|
||||
func NewPluginSettingValue[T any](store *PluginSettingStore, key string, defaultValue T) *PluginSettingValue[T] {
|
||||
return &PluginSettingValue[T]{
|
||||
SettingValue: &SettingValue[T]{
|
||||
settingStore: store,
|
||||
key: key,
|
||||
defaultValue: defaultValue,
|
||||
},
|
||||
pluginId: store.pluginId,
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the value of the setting, loading it from the store if necessary.
|
||||
func (v *Value[T]) Get() T {
|
||||
func (v *SettingValue[T]) Get() T {
|
||||
v.mu.RLock()
|
||||
if v.isLoaded {
|
||||
defer v.mu.RUnlock()
|
||||
|
@ -112,8 +136,8 @@ func (v *Value[T]) Get() T {
|
|||
|
||||
// Load from unified store
|
||||
v.value = v.defaultValue // Start with default value
|
||||
if v.store != nil {
|
||||
if err := v.store.Get(v.key, &v.value); err != nil {
|
||||
if v.settingStore != nil {
|
||||
if err := v.settingStore.Get(v.key, &v.value); err != nil {
|
||||
// Log error and keep default value
|
||||
v.value = v.defaultValue
|
||||
}
|
||||
|
@ -129,25 +153,27 @@ func (v *Value[T]) Get() T {
|
|||
}
|
||||
|
||||
// Set updates the value of the setting and persists it to the store.
|
||||
func (v *Value[T]) Set(newValue T) error {
|
||||
func (v *SettingValue[T]) Set(newValue T) error {
|
||||
v.mu.Lock()
|
||||
defer v.mu.Unlock()
|
||||
|
||||
var err error
|
||||
if v.store != nil {
|
||||
err = v.store.Set(v.key, newValue)
|
||||
if v.settingStore != nil {
|
||||
err = v.settingStore.Set(v.key, newValue)
|
||||
} else {
|
||||
return fmt.Errorf("no store available")
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
v.value = newValue
|
||||
v.isLoaded = true
|
||||
|
||||
if v.syncable {
|
||||
return v.store.LogOplog(v.key, newValue)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
v.value = newValue
|
||||
v.isLoaded = true
|
||||
|
||||
if v.syncable {
|
||||
return v.syncStore.LogOplog(v.key, newValue)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,19 +14,19 @@ type WoxSetting struct {
|
|||
EnableAutostart *PlatformValue[bool]
|
||||
MainHotkey *PlatformValue[string]
|
||||
SelectionHotkey *PlatformValue[string]
|
||||
UsePinYin *Value[bool]
|
||||
SwitchInputMethodABC *Value[bool]
|
||||
HideOnStart *Value[bool]
|
||||
HideOnLostFocus *Value[bool]
|
||||
ShowTray *Value[bool]
|
||||
LangCode *Value[i18n.LangCode]
|
||||
UsePinYin *WoxSettingValue[bool]
|
||||
SwitchInputMethodABC *WoxSettingValue[bool]
|
||||
HideOnStart *WoxSettingValue[bool]
|
||||
HideOnLostFocus *WoxSettingValue[bool]
|
||||
ShowTray *WoxSettingValue[bool]
|
||||
LangCode *WoxSettingValue[i18n.LangCode]
|
||||
QueryHotkeys *PlatformValue[[]QueryHotkey]
|
||||
QueryShortcuts *Value[[]QueryShortcut]
|
||||
LastQueryMode *Value[LastQueryMode]
|
||||
ShowPosition *Value[PositionType]
|
||||
AIProviders *Value[[]AIProvider]
|
||||
EnableAutoBackup *Value[bool]
|
||||
EnableAutoUpdate *Value[bool]
|
||||
QueryShortcuts *WoxSettingValue[[]QueryShortcut]
|
||||
LastQueryMode *WoxSettingValue[LastQueryMode]
|
||||
ShowPosition *WoxSettingValue[PositionType]
|
||||
AIProviders *WoxSettingValue[[]AIProvider]
|
||||
EnableAutoBackup *WoxSettingValue[bool]
|
||||
EnableAutoUpdate *WoxSettingValue[bool]
|
||||
CustomPythonPath *PlatformValue[string]
|
||||
CustomNodejsPath *PlatformValue[string]
|
||||
|
||||
|
@ -35,18 +35,18 @@ type WoxSetting struct {
|
|||
HttpProxyUrl *PlatformValue[string]
|
||||
|
||||
// UI related
|
||||
AppWidth *Value[int]
|
||||
MaxResultCount *Value[int]
|
||||
ThemeId *Value[string]
|
||||
AppWidth *WoxSettingValue[int]
|
||||
MaxResultCount *WoxSettingValue[int]
|
||||
ThemeId *WoxSettingValue[string]
|
||||
|
||||
// Window position for last location mode
|
||||
LastWindowX *Value[int]
|
||||
LastWindowY *Value[int]
|
||||
LastWindowX *WoxSettingValue[int]
|
||||
LastWindowY *WoxSettingValue[int]
|
||||
|
||||
// Data that was previously in WoxAppData
|
||||
QueryHistories *Value[[]QueryHistory]
|
||||
FavoriteResults *Value[*util.HashMap[ResultHash, bool]]
|
||||
ActionedResults *Value[*util.HashMap[ResultHash, []ActionedResult]]
|
||||
QueryHistories *WoxSettingValue[[]QueryHistory]
|
||||
FavoriteResults *WoxSettingValue[*util.HashMap[ResultHash, bool]]
|
||||
ActionedResults *WoxSettingValue[*util.HashMap[ResultHash, []ActionedResult]]
|
||||
}
|
||||
|
||||
type LastQueryMode = string
|
||||
|
@ -113,7 +113,7 @@ type QueryHistory struct {
|
|||
Timestamp int64
|
||||
}
|
||||
|
||||
func NewWoxSetting(store WoxSettingStore) *WoxSetting {
|
||||
func NewWoxSetting(store *WoxSettingStore) *WoxSetting {
|
||||
usePinYin := false
|
||||
defaultLangCode := i18n.LangCodeEnUs
|
||||
switchInputMethodABC := false
|
||||
|
@ -126,33 +126,33 @@ func NewWoxSetting(store WoxSettingStore) *WoxSetting {
|
|||
return &WoxSetting{
|
||||
MainHotkey: NewPlatformValue(store, "MainHotkey", "alt+space", "option+space", "ctrl+space"),
|
||||
SelectionHotkey: NewPlatformValue(store, "SelectionHotkey", "ctrl+alt+space", "command+option+space", "ctrl+shift+j"),
|
||||
UsePinYin: NewValue(store, "UsePinYin", usePinYin),
|
||||
SwitchInputMethodABC: NewValue(store, "SwitchInputMethodABC", switchInputMethodABC),
|
||||
ShowTray: NewValue(store, "ShowTray", true),
|
||||
HideOnLostFocus: NewValue(store, "HideOnLostFocus", true),
|
||||
HideOnStart: NewValue(store, "HideOnStart", false),
|
||||
LangCode: NewValueWithValidator(store, "LangCode", defaultLangCode, func(code i18n.LangCode) bool {
|
||||
UsePinYin: NewWoxSettingValue(store, "UsePinYin", usePinYin),
|
||||
SwitchInputMethodABC: NewWoxSettingValue(store, "SwitchInputMethodABC", switchInputMethodABC),
|
||||
ShowTray: NewWoxSettingValue(store, "ShowTray", true),
|
||||
HideOnLostFocus: NewWoxSettingValue(store, "HideOnLostFocus", true),
|
||||
HideOnStart: NewWoxSettingValue(store, "HideOnStart", false),
|
||||
LangCode: NewWoxSettingValueWithValidator(store, "LangCode", defaultLangCode, func(code i18n.LangCode) bool {
|
||||
return i18n.IsSupportedLangCode(string(code))
|
||||
}),
|
||||
LastQueryMode: NewValue(store, "LastQueryMode", LastQueryModeEmpty),
|
||||
ShowPosition: NewValue(store, "ShowPosition", PositionTypeMouseScreen),
|
||||
AppWidth: NewValue(store, "AppWidth", 800),
|
||||
MaxResultCount: NewValue(store, "MaxResultCount", 10),
|
||||
ThemeId: NewValue(store, "ThemeId", DefaultThemeId),
|
||||
LastQueryMode: NewWoxSettingValue(store, "LastQueryMode", LastQueryModeEmpty),
|
||||
ShowPosition: NewWoxSettingValue(store, "ShowPosition", PositionTypeMouseScreen),
|
||||
AppWidth: NewWoxSettingValue(store, "AppWidth", 800),
|
||||
MaxResultCount: NewWoxSettingValue(store, "MaxResultCount", 10),
|
||||
ThemeId: NewWoxSettingValue(store, "ThemeId", DefaultThemeId),
|
||||
EnableAutostart: NewPlatformValue(store, "EnableAutostart", false, false, false),
|
||||
HttpProxyEnabled: NewPlatformValue(store, "HttpProxyEnabled", false, false, false),
|
||||
HttpProxyUrl: NewPlatformValue(store, "HttpProxyUrl", "", "", ""),
|
||||
CustomPythonPath: NewPlatformValue(store, "CustomPythonPath", "", "", ""),
|
||||
CustomNodejsPath: NewPlatformValue(store, "CustomNodejsPath", "", "", ""),
|
||||
EnableAutoBackup: NewValue(store, "EnableAutoBackup", true),
|
||||
EnableAutoUpdate: NewValue(store, "EnableAutoUpdate", true),
|
||||
LastWindowX: NewValue(store, "LastWindowX", -1),
|
||||
LastWindowY: NewValue(store, "LastWindowY", -1),
|
||||
EnableAutoBackup: NewWoxSettingValue(store, "EnableAutoBackup", true),
|
||||
EnableAutoUpdate: NewWoxSettingValue(store, "EnableAutoUpdate", true),
|
||||
LastWindowX: NewWoxSettingValue(store, "LastWindowX", -1),
|
||||
LastWindowY: NewWoxSettingValue(store, "LastWindowY", -1),
|
||||
QueryHotkeys: NewPlatformValue(store, "QueryHotkeys", []QueryHotkey{}, []QueryHotkey{}, []QueryHotkey{}),
|
||||
QueryShortcuts: NewValue(store, "QueryShortcuts", []QueryShortcut{}),
|
||||
AIProviders: NewValue(store, "AIProviders", []AIProvider{}),
|
||||
QueryHistories: NewValue(store, "QueryHistories", []QueryHistory{}),
|
||||
FavoriteResults: NewValue(store, "FavoriteResults", util.NewHashMap[ResultHash, bool]()),
|
||||
ActionedResults: NewValue(store, "ActionedResults", util.NewHashMap[ResultHash, []ActionedResult]()),
|
||||
QueryShortcuts: NewWoxSettingValue(store, "QueryShortcuts", []QueryShortcut{}),
|
||||
AIProviders: NewWoxSettingValue(store, "AIProviders", []AIProvider{}),
|
||||
QueryHistories: NewWoxSettingValue(store, "QueryHistories", []QueryHistory{}),
|
||||
FavoriteResults: NewWoxSettingValue(store, "FavoriteResults", util.NewHashMap[ResultHash, bool]()),
|
||||
ActionedResults: NewWoxSettingValue(store, "ActionedResults", util.NewHashMap[ResultHash, []ActionedResult]()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package dto
|
|||
import (
|
||||
"wox/common"
|
||||
"wox/plugin"
|
||||
"wox/setting"
|
||||
"wox/setting/definition"
|
||||
)
|
||||
|
||||
|
@ -23,10 +22,22 @@ type PluginDto struct {
|
|||
Commands []plugin.MetadataCommand
|
||||
SupportedOS []string
|
||||
SettingDefinitions definition.PluginSettingDefinitions // only available when plugin is installed
|
||||
Setting setting.PluginSetting // only available when plugin is installed
|
||||
Setting PluginSettingDto // only available when plugin is installed
|
||||
Features []plugin.MetadataFeature // only available when plugin is installed
|
||||
IsSystem bool
|
||||
IsDev bool
|
||||
IsInstalled bool
|
||||
IsDisable bool // only available when plugin is installed
|
||||
}
|
||||
|
||||
type PluginSettingDto struct {
|
||||
Disabled bool
|
||||
TriggerKeywords []string
|
||||
QueryCommands []PluginQueryCommandDto
|
||||
Settings map[string]string
|
||||
}
|
||||
|
||||
type PluginQueryCommandDto struct {
|
||||
Command string
|
||||
Description string
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
"wox/plugin"
|
||||
"wox/setting"
|
||||
"wox/setting/definition"
|
||||
"wox/ui/dto"
|
||||
"wox/util"
|
||||
|
@ -240,16 +241,25 @@ func convertPluginDto(ctx context.Context, pluginDto dto.PluginDto, pluginInstan
|
|||
}
|
||||
}
|
||||
|
||||
var definitionSettings = util.NewHashMap[string, string]()
|
||||
var nonDynamicSettings = make(map[string]string)
|
||||
for _, item := range pluginDto.SettingDefinitions {
|
||||
if item.Value != nil {
|
||||
settingValue := pluginInstance.API.GetSetting(ctx, item.Value.GetKey())
|
||||
definitionSettings.Store(item.Value.GetKey(), settingValue)
|
||||
nonDynamicSettings[item.Value.GetKey()] = settingValue
|
||||
}
|
||||
}
|
||||
pluginDto.Setting = *pluginInstance.Setting
|
||||
//only return user pre-defined settings
|
||||
pluginDto.Setting.Settings = definitionSettings
|
||||
pluginDto.Setting = dto.PluginSettingDto{
|
||||
Disabled: pluginInstance.Setting.Disabled.Get(),
|
||||
TriggerKeywords: pluginInstance.Setting.TriggerKeywords.Get(),
|
||||
QueryCommands: lo.Map(pluginInstance.Setting.QueryCommands.Get(), func(item setting.PluginQueryCommand, _ int) dto.PluginQueryCommandDto {
|
||||
return dto.PluginQueryCommandDto{
|
||||
Command: item.Command,
|
||||
Description: item.Description,
|
||||
}
|
||||
}),
|
||||
//only return user pre-defined settings
|
||||
Settings: nonDynamicSettings,
|
||||
}
|
||||
pluginDto.Features = pluginInstance.Metadata.Features
|
||||
pluginDto.TriggerKeywords = pluginInstance.GetTriggerKeywords()
|
||||
}
|
||||
|
|
|
@ -192,7 +192,9 @@ func convertPluginInstanceToDto(ctx context.Context, pluginInstance *plugin.Inst
|
|||
installedPlugin.IsSystem = pluginInstance.IsSystemPlugin
|
||||
installedPlugin.IsDev = pluginInstance.IsDevPlugin
|
||||
installedPlugin.IsInstalled = true
|
||||
installedPlugin.IsDisable = pluginInstance.Setting.Disabled
|
||||
installedPlugin.IsDisable = pluginInstance.Setting.Disabled.Get()
|
||||
installedPlugin.TriggerKeywords = pluginInstance.GetTriggerKeywords()
|
||||
installedPlugin.Commands = pluginInstance.GetQueryCommands()
|
||||
|
||||
//load screenshot urls from store if exist
|
||||
storePlugin, foundErr := plugin.GetStoreManager().GetStorePluginManifestById(ctx, pluginInstance.Metadata.Id)
|
||||
|
@ -230,10 +232,7 @@ func handlePluginInstall(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
plugins := plugin.GetStoreManager().GetStorePluginManifests(ctx)
|
||||
findPlugin, exist := lo.Find(plugins, func(item plugin.StorePluginManifest) bool {
|
||||
if item.Id == pluginId {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return item.Id == pluginId
|
||||
})
|
||||
if !exist {
|
||||
writeErrorResponse(w, fmt.Sprintf("Plugin '%s' not found in the store", pluginId))
|
||||
|
@ -287,8 +286,6 @@ func handlePluginUninstall(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func handlePluginDisable(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := util.NewTraceContext()
|
||||
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
idResult := gjson.GetBytes(body, "id")
|
||||
if !idResult.Exists() {
|
||||
|
@ -310,19 +307,11 @@ func handlePluginDisable(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
findPlugin.Setting.Disabled = true
|
||||
err := findPlugin.SaveSetting(ctx)
|
||||
if err != nil {
|
||||
writeErrorResponse(w, "can't disable plugin: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
findPlugin.Setting.Disabled.Set(true)
|
||||
writeSuccessResponse(w, "")
|
||||
}
|
||||
|
||||
func handlePluginEnable(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := util.NewTraceContext()
|
||||
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
idResult := gjson.GetBytes(body, "id")
|
||||
if !idResult.Exists() {
|
||||
|
@ -341,13 +330,7 @@ func handlePluginEnable(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
findPlugin.Setting.Disabled = false
|
||||
err := findPlugin.SaveSetting(ctx)
|
||||
if err != nil {
|
||||
writeErrorResponse(w, "can't enable plugin: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
findPlugin.Setting.Disabled.Set(false)
|
||||
writeSuccessResponse(w, "")
|
||||
}
|
||||
|
||||
|
@ -587,8 +570,6 @@ func handleSettingWoxUpdate(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func handleSettingPluginUpdate(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := util.NewTraceContext()
|
||||
|
||||
type keyValuePair struct {
|
||||
PluginId string
|
||||
Key string
|
||||
|
@ -615,11 +596,9 @@ func handleSettingPluginUpdate(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
if kv.Key == "Disabled" {
|
||||
pluginInstance.Setting.Disabled = kv.Value == "true"
|
||||
pluginInstance.SaveSetting(ctx)
|
||||
pluginInstance.Setting.Disabled.Set(kv.Value == "true")
|
||||
} else if kv.Key == "TriggerKeywords" {
|
||||
pluginInstance.Setting.TriggerKeywords = strings.Split(kv.Value, ",")
|
||||
pluginInstance.SaveSetting(ctx)
|
||||
pluginInstance.Setting.TriggerKeywords.Set(strings.Split(kv.Value, ","))
|
||||
} else {
|
||||
var isPlatformSpecific = false
|
||||
for _, settingDefinition := range pluginInstance.Metadata.SettingDefinitions {
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"time"
|
||||
"wox/i18n"
|
||||
"wox/setting"
|
||||
|
||||
"wox/util"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
|
|
Loading…
Reference in New Issue