diff options
Diffstat (limited to 'src/stores/UIStore.ts')
-rw-r--r-- | src/stores/UIStore.ts | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/stores/UIStore.ts b/src/stores/UIStore.ts new file mode 100644 index 000000000..306b14cb1 --- /dev/null +++ b/src/stores/UIStore.ts | |||
@@ -0,0 +1,135 @@ | |||
1 | import { action, observable, computed, reaction } from 'mobx'; | ||
2 | import { nativeTheme } from '@electron/remote'; | ||
3 | |||
4 | import { Stores } from 'src/stores.types'; | ||
5 | import { ApiInterface } from 'src/api'; | ||
6 | import { Actions } from 'src/actions/lib/actions'; | ||
7 | import { Theme, theme, ThemeType } from '../themes'; | ||
8 | import TypedStore from './lib/TypedStore'; | ||
9 | |||
10 | export default class UIStore extends TypedStore { | ||
11 | @observable showServicesUpdatedInfoBar = false; | ||
12 | |||
13 | @observable isOsDarkThemeActive = nativeTheme.shouldUseDarkColors; | ||
14 | |||
15 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | ||
16 | super(stores, api, actions); | ||
17 | // Register action handlers | ||
18 | this.actions.ui.openSettings.listen(this._openSettings.bind(this)); | ||
19 | this.actions.ui.closeSettings.listen(this._closeSettings.bind(this)); | ||
20 | this.actions.ui.toggleServiceUpdatedInfoBar.listen( | ||
21 | this._toggleServiceUpdatedInfoBar.bind(this), | ||
22 | ); | ||
23 | |||
24 | // Listen for theme change | ||
25 | nativeTheme.on('updated', () => { | ||
26 | this.isOsDarkThemeActive = nativeTheme.shouldUseDarkColors; | ||
27 | this.actions.service.shareSettingsWithServiceProcess(); | ||
28 | }); | ||
29 | } | ||
30 | |||
31 | setup(): void { | ||
32 | reaction( | ||
33 | () => this.isDarkThemeActive, | ||
34 | () => { | ||
35 | this._setupThemeInDOM(); | ||
36 | }, | ||
37 | { fireImmediately: true }, | ||
38 | ); | ||
39 | reaction( | ||
40 | () => this.isSplitModeActive, | ||
41 | () => { | ||
42 | this._setupModeInDOM(); | ||
43 | }, | ||
44 | { fireImmediately: true }, | ||
45 | ); | ||
46 | reaction( | ||
47 | () => this.splitColumnsNo, | ||
48 | () => { | ||
49 | this._setupColumnsInDOM(); | ||
50 | }, | ||
51 | { fireImmediately: true }, | ||
52 | ); | ||
53 | } | ||
54 | |||
55 | @computed get showMessageBadgesEvenWhenMuted() { | ||
56 | const settings = this.stores.settings.all; | ||
57 | |||
58 | return ( | ||
59 | (settings.app.isAppMuted && settings.app.showMessageBadgeWhenMuted) || | ||
60 | !settings.app.isAppMuted | ||
61 | ); | ||
62 | } | ||
63 | |||
64 | @computed get isDarkThemeActive() { | ||
65 | const isWithAdaptableInDarkMode = | ||
66 | this.stores.settings.all.app.adaptableDarkMode && | ||
67 | this.isOsDarkThemeActive; | ||
68 | const isWithoutAdaptableInDarkMode = | ||
69 | this.stores.settings.all.app.darkMode && | ||
70 | !this.stores.settings.all.app.adaptableDarkMode; | ||
71 | const isInDarkMode = this.stores.settings.all.app.darkMode; | ||
72 | return !!( | ||
73 | isWithAdaptableInDarkMode || | ||
74 | isWithoutAdaptableInDarkMode || | ||
75 | isInDarkMode | ||
76 | ); | ||
77 | } | ||
78 | |||
79 | @computed get isSplitModeActive(): boolean { | ||
80 | return this.stores.settings.app.splitMode; | ||
81 | } | ||
82 | |||
83 | @computed get splitColumnsNo(): number { | ||
84 | return this.stores.settings.app.splitColumns; | ||
85 | } | ||
86 | |||
87 | @computed get theme(): Theme { | ||
88 | const themeId = | ||
89 | this.isDarkThemeActive || this.stores.settings.app.darkMode | ||
90 | ? ThemeType.dark | ||
91 | : ThemeType.default; | ||
92 | const { accentColor } = this.stores.settings.app; | ||
93 | return theme(themeId, accentColor); | ||
94 | } | ||
95 | |||
96 | // Actions | ||
97 | @action _openSettings({ path = '/settings' }): void { | ||
98 | const settingsPath = path !== '/settings' ? `/settings/${path}` : path; | ||
99 | this.stores.router.push(settingsPath); | ||
100 | } | ||
101 | |||
102 | @action _closeSettings(): void { | ||
103 | this.stores.router.push('/'); | ||
104 | } | ||
105 | |||
106 | @action _toggleServiceUpdatedInfoBar({ visible }): void { | ||
107 | let visibility = visible; | ||
108 | if (visibility === null) { | ||
109 | visibility = !this.showServicesUpdatedInfoBar; | ||
110 | } | ||
111 | this.showServicesUpdatedInfoBar = visibility; | ||
112 | } | ||
113 | |||
114 | // Reactions | ||
115 | _setupThemeInDOM(): void { | ||
116 | if (!this.isDarkThemeActive) { | ||
117 | document.body.classList.remove('theme__dark'); | ||
118 | } else { | ||
119 | document.body.classList.add('theme__dark'); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | _setupModeInDOM(): void { | ||
124 | if (!this.isSplitModeActive) { | ||
125 | document.body.classList.remove('mode__split'); | ||
126 | } else { | ||
127 | document.body.classList.add('mode__split'); | ||
128 | document.body.dataset.columns = this.splitColumnsNo.toString(); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | _setupColumnsInDOM(): void { | ||
133 | document.body.dataset.columns = this.splitColumnsNo.toString(); | ||
134 | } | ||
135 | } | ||