summaryrefslogtreecommitdiffhomepage
path: root/gui/src/main/gui-settings.ts
blob: d1d620ba541eba05f20275a97676fe1bb467d504 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { app } from 'electron';
import log from 'electron-log';
import * as fs from 'fs';
import * as path from 'path';
import { IGuiSettingsState, SYSTEM_PREFERRED_LOCALE_KEY } from '../shared/gui-settings-state';

const settingsSchema = {
  preferredLocale: 'string',
  autoConnect: 'boolean',
  enableSystemNotifications: 'boolean',
  monochromaticIcon: 'boolean',
  startMinimized: 'boolean',
};

const defaultSettings: IGuiSettingsState = {
  preferredLocale: SYSTEM_PREFERRED_LOCALE_KEY,
  autoConnect: true,
  enableSystemNotifications: true,
  monochromaticIcon: false,
  startMinimized: false,
};

export default class GuiSettings {
  get state(): IGuiSettingsState {
    return this.stateValue;
  }

  set preferredLocale(newValue: string) {
    this.changeStateAndNotify({ ...this.stateValue, preferredLocale: newValue });
  }

  get preferredLocale(): string {
    return this.stateValue.preferredLocale;
  }

  set enableSystemNotifications(newValue: boolean) {
    this.changeStateAndNotify({ ...this.stateValue, enableSystemNotifications: newValue });
  }

  get enableSystemNotifications(): boolean {
    return this.stateValue.enableSystemNotifications;
  }

  set autoConnect(newValue: boolean) {
    this.changeStateAndNotify({ ...this.stateValue, autoConnect: newValue });
  }

  get autoConnect(): boolean {
    return this.stateValue.autoConnect;
  }

  set monochromaticIcon(newValue: boolean) {
    this.changeStateAndNotify({ ...this.stateValue, monochromaticIcon: newValue });
  }

  get monochromaticIcon(): boolean {
    return this.stateValue.monochromaticIcon;
  }

  set startMinimized(newValue: boolean) {
    this.changeStateAndNotify({ ...this.stateValue, startMinimized: newValue });
  }

  get startMinimized(): boolean {
    return this.stateValue.startMinimized;
  }

  public onChange?: (newState: IGuiSettingsState, oldState: IGuiSettingsState) => void;

  private stateValue: IGuiSettingsState = { ...defaultSettings };

  public load() {
    try {
      const settingsFile = this.filePath();
      const contents = fs.readFileSync(settingsFile, 'utf8');
      const rawJson = JSON.parse(contents);

      this.stateValue = {
        ...defaultSettings,
        ...this.validateSettings(rawJson),
      };
    } catch (error) {
      log.error(`Failed to read GUI settings file: ${error}`);
    }
  }

  public store() {
    try {
      const settingsFile = this.filePath();

      fs.writeFileSync(settingsFile, JSON.stringify(this.stateValue));
    } catch (error) {
      log.error(`Failed to write GUI settings file: ${error}`);
    }
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  private validateSettings(settings: any) {
    Object.entries(settingsSchema).forEach(([key, expectedType]) => {
      const actualType = typeof settings[key];
      if (key in settings && actualType !== expectedType) {
        throw new Error(`Expected ${key} to be of type ${expectedType} but was ${actualType}`);
      }
    });

    return settings as Partial<IGuiSettingsState>;
  }

  private filePath() {
    return path.join(app.getPath('userData'), 'gui_settings.json');
  }

  private changeStateAndNotify(newState: IGuiSettingsState) {
    const oldState = this.stateValue;
    this.stateValue = newState;

    this.store();

    if (this.onChange) {
      this.onChange({ ...newState }, oldState);
    }
  }
}