mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-03 12:09:09 +02:00
store viewmode in ui preferences
This commit is contained in:
@@ -36,11 +36,40 @@ const preferencesFileName = "ui-preferences.json"
|
|||||||
// Wails registers this name in init() so the React frontend can subscribe.
|
// Wails registers this name in init() so the React frontend can subscribe.
|
||||||
const EventPreferencesChanged = "netbird:preferences:changed"
|
const EventPreferencesChanged = "netbird:preferences:changed"
|
||||||
|
|
||||||
|
// ViewMode is the user's preferred Main-window layout. "default" is the
|
||||||
|
// compact 380-wide layout shown on first launch; "advanced" is the wider
|
||||||
|
// 900-px layout that matches the Settings window. Persisted so the next
|
||||||
|
// launch comes up in the same mode the user last picked.
|
||||||
|
type ViewMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ViewModeDefault ViewMode = "default"
|
||||||
|
ViewModeAdvanced ViewMode = "advanced"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultViewMode is the value served when no preferences file exists yet
|
||||||
|
// or the on-disk file has an empty view-mode field.
|
||||||
|
const DefaultViewMode = ViewModeDefault
|
||||||
|
|
||||||
|
// ErrUnsupportedViewMode is returned by SetViewMode when the caller passes
|
||||||
|
// a value outside the known set.
|
||||||
|
var ErrUnsupportedViewMode = errors.New("unsupported view mode")
|
||||||
|
|
||||||
|
// IsValid reports whether v is one of the known ViewMode constants.
|
||||||
|
func (v ViewMode) IsValid() bool {
|
||||||
|
switch v {
|
||||||
|
case ViewModeDefault, ViewModeAdvanced:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// UIPreferences is the user-scope UI state mirrored to disk and to the
|
// UIPreferences is the user-scope UI state mirrored to disk and to the
|
||||||
// frontend. Pointer-free because the whole document is rewritten on every
|
// frontend. Pointer-free because the whole document is rewritten on every
|
||||||
// change — there are no per-field partial updates.
|
// change — there are no per-field partial updates.
|
||||||
type UIPreferences struct {
|
type UIPreferences struct {
|
||||||
Language i18n.LanguageCode `json:"language"`
|
Language i18n.LanguageCode `json:"language"`
|
||||||
|
ViewMode ViewMode `json:"viewMode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LanguageValidator is the dependency Store needs to reject SetLanguage
|
// LanguageValidator is the dependency Store needs to reject SetLanguage
|
||||||
@@ -86,7 +115,7 @@ func NewStore(validator LanguageValidator, emitter Emitter) (*Store, error) {
|
|||||||
path: path,
|
path: path,
|
||||||
validator: validator,
|
validator: validator,
|
||||||
emitter: emitter,
|
emitter: emitter,
|
||||||
current: UIPreferences{Language: i18n.DefaultLanguage},
|
current: UIPreferences{Language: i18n.DefaultLanguage, ViewMode: DefaultViewMode},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.load(); err != nil {
|
if err := s.load(); err != nil {
|
||||||
@@ -103,6 +132,31 @@ func (s *Store) Get() UIPreferences {
|
|||||||
return s.current
|
return s.current
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetViewMode validates and persists the user's Main-window view choice,
|
||||||
|
// then broadcasts the change so any other open window can react.
|
||||||
|
func (s *Store) SetViewMode(mode ViewMode) error {
|
||||||
|
if !mode.IsValid() {
|
||||||
|
return fmt.Errorf("%w: %q", ErrUnsupportedViewMode, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.mu.Lock()
|
||||||
|
if s.current.ViewMode == mode {
|
||||||
|
s.mu.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
next := s.current
|
||||||
|
next.ViewMode = mode
|
||||||
|
if err := s.persistLocked(next); err != nil {
|
||||||
|
s.mu.Unlock()
|
||||||
|
return fmt.Errorf("persist preferences: %w", err)
|
||||||
|
}
|
||||||
|
s.current = next
|
||||||
|
s.mu.Unlock()
|
||||||
|
|
||||||
|
s.broadcast(next)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetLanguage validates and persists a new language preference, then
|
// SetLanguage validates and persists a new language preference, then
|
||||||
// broadcasts the change to internal subscribers (tray) and the emitter
|
// broadcasts the change to internal subscribers (tray) and the emitter
|
||||||
// (frontend).
|
// (frontend).
|
||||||
@@ -171,6 +225,9 @@ func (s *Store) load() error {
|
|||||||
if loaded.Language == "" {
|
if loaded.Language == "" {
|
||||||
loaded.Language = i18n.DefaultLanguage
|
loaded.Language = i18n.DefaultLanguage
|
||||||
}
|
}
|
||||||
|
if !loaded.ViewMode.IsValid() {
|
||||||
|
loaded.ViewMode = DefaultViewMode
|
||||||
|
}
|
||||||
|
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
s.current = loaded
|
s.current = loaded
|
||||||
|
|||||||
@@ -30,3 +30,9 @@ func (s *Preferences) Get(_ context.Context) (preferences.UIPreferences, error)
|
|||||||
func (s *Preferences) SetLanguage(_ context.Context, lang i18n.LanguageCode) error {
|
func (s *Preferences) SetLanguage(_ context.Context, lang i18n.LanguageCode) error {
|
||||||
return s.store.SetLanguage(lang)
|
return s.store.SetLanguage(lang)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetViewMode validates and persists the Main-window view choice
|
||||||
|
// ("default" or "advanced").
|
||||||
|
func (s *Preferences) SetViewMode(_ context.Context, mode preferences.ViewMode) error {
|
||||||
|
return s.store.SetViewMode(mode)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user