diff options
| author | SergeiEU <39683682+SergeiEU@users.noreply.github.com> | 2026-04-01 10:17:15 +0400 |
|---|---|---|
| committer | SergeiEU <39683682+SergeiEU@users.noreply.github.com> | 2026-04-01 10:17:15 +0400 |
| commit | 1bd203c5555046b7ee4fbfe2f822eb3d03571ad7 (patch) | |
| tree | d8c85273ede547e03a5727bf185f5d07e87b4a08 /internal/state | |
| download | vpnem-1bd203c5555046b7ee4fbfe2f822eb3d03571ad7.tar.gz vpnem-1bd203c5555046b7ee4fbfe2f822eb3d03571ad7.tar.bz2 vpnem-1bd203c5555046b7ee4fbfe2f822eb3d03571ad7.zip | |
Diffstat (limited to 'internal/state')
| -rw-r--r-- | internal/state/state.go | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/internal/state/state.go b/internal/state/state.go new file mode 100644 index 0000000..83f77b1 --- /dev/null +++ b/internal/state/state.go @@ -0,0 +1,137 @@ +package state + +import ( + "encoding/json" + "os" + "path/filepath" + "sync" + "time" +) + +// AppState holds persistent client state. +type AppState struct { + SelectedServer string `json:"selected_server"` + SelectedMode string `json:"selected_mode"` + LastSync time.Time `json:"last_sync"` + AutoConnect bool `json:"auto_connect"` + EnabledRuleSets map[string]bool `json:"enabled_rule_sets,omitempty"` + CustomBypass []string `json:"custom_bypass_processes,omitempty"` +} + +// Store manages persistent state on disk. +type Store struct { + mu sync.Mutex + path string + data AppState +} + +// NewStore creates a state store at the given path. +func NewStore(dataDir string) *Store { + return &Store{ + path: filepath.Join(dataDir, "state.json"), + data: AppState{ + SelectedMode: "Комбо (приложения + Re-filter)", + AutoConnect: false, + }, + } +} + +// Load reads state from disk. Returns default state if file doesn't exist. +func (s *Store) Load() error { + s.mu.Lock() + defer s.mu.Unlock() + + data, err := os.ReadFile(s.path) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + return json.Unmarshal(data, &s.data) +} + +// Save writes state to disk. +func (s *Store) Save() error { + s.mu.Lock() + defer s.mu.Unlock() + + if err := os.MkdirAll(filepath.Dir(s.path), 0o755); err != nil { + return err + } + + data, err := json.MarshalIndent(s.data, "", " ") + if err != nil { + return err + } + return os.WriteFile(s.path, data, 0o644) +} + +// Get returns a copy of the current state. +func (s *Store) Get() AppState { + s.mu.Lock() + defer s.mu.Unlock() + return s.data +} + +// SetServer updates the selected server. +func (s *Store) SetServer(tag string) { + s.mu.Lock() + s.data.SelectedServer = tag + s.mu.Unlock() +} + +// SetMode updates the selected routing mode. +func (s *Store) SetMode(mode string) { + s.mu.Lock() + s.data.SelectedMode = mode + s.mu.Unlock() +} + +// SetLastSync records the last sync time. +func (s *Store) SetLastSync(t time.Time) { + s.mu.Lock() + s.data.LastSync = t + s.mu.Unlock() +} + +// SetAutoConnect updates the auto-connect setting. +func (s *Store) SetAutoConnect(v bool) { + s.mu.Lock() + s.data.AutoConnect = v + s.mu.Unlock() +} + +// SetRuleSetEnabled enables/disables an optional rule-set. +func (s *Store) SetRuleSetEnabled(tag string, enabled bool) { + s.mu.Lock() + if s.data.EnabledRuleSets == nil { + s.data.EnabledRuleSets = make(map[string]bool) + } + s.data.EnabledRuleSets[tag] = enabled + s.mu.Unlock() +} + +// IsRuleSetEnabled checks if a rule-set is enabled. +func (s *Store) IsRuleSetEnabled(tag string) bool { + s.mu.Lock() + defer s.mu.Unlock() + if s.data.EnabledRuleSets == nil { + return false + } + return s.data.EnabledRuleSets[tag] +} + +// SetCustomBypass sets custom bypass processes. +func (s *Store) SetCustomBypass(processes []string) { + s.mu.Lock() + s.data.CustomBypass = processes + s.mu.Unlock() +} + +// GetCustomBypass returns custom bypass processes. +func (s *Store) GetCustomBypass() []string { + s.mu.Lock() + defer s.mu.Unlock() + return append([]string{}, s.data.CustomBypass...) +} |
