aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/todos/store.ts
diff options
context:
space:
mode:
authorLibravatar Muhamed <unknown>2022-11-24 02:56:10 +0530
committerLibravatar Vijay Aravamudhan <vraravam@users.noreply.github.com>2022-11-25 05:04:25 +0530
commitf92933c396db9e94ffd297c41add86de88dfc6c6 (patch)
tree57789f7f64c618086c3792833d076244d879aa75 /src/features/todos/store.ts
parentfix: use 'Route' from 'react-router-dom' package (diff)
downloadferdium-app-f92933c396db9e94ffd297c41add86de88dfc6c6.tar.gz
ferdium-app-f92933c396db9e94ffd297c41add86de88dfc6c6.tar.zst
ferdium-app-f92933c396db9e94ffd297c41add86de88dfc6c6.zip
chore: transform workspace action store and todo store into ts
Diffstat (limited to 'src/features/todos/store.ts')
-rw-r--r--src/features/todos/store.ts327
1 files changed, 327 insertions, 0 deletions
diff --git a/src/features/todos/store.ts b/src/features/todos/store.ts
new file mode 100644
index 000000000..5cf5e1d75
--- /dev/null
+++ b/src/features/todos/store.ts
@@ -0,0 +1,327 @@
1import { Webview } from 'react-electron-web-view';
2import { computed, action, observable, makeObservable } from 'mobx';
3import localStorage from 'mobx-localstorage';
4import { Actions } from '../../actions/lib/actions';
5
6import { ThemeType } from '../../themes';
7import { todoActions } from './actions';
8import {
9 CUSTOM_TODO_SERVICE,
10 TODO_SERVICE_RECIPE_IDS,
11 DEFAULT_TODOS_WIDTH,
12 TODOS_MIN_WIDTH,
13 DEFAULT_TODOS_VISIBLE,
14 DEFAULT_IS_TODO_FEATURE_ENABLED_BY_USER,
15} from '../../config';
16import { isValidExternalURL } from '../../helpers/url-helpers';
17import FeatureStore from '../utils/FeatureStore';
18import Reaction, { createReactions } from '../../stores/lib/Reaction';
19import { createActionBindings } from '../utils/ActionBinding';
20import { IPC, TODOS_ROUTES } from './constants';
21import UserAgent from '../../models/UserAgent';
22
23const debug = require('../../preload-safe-debug')(
24 'Ferdium:feature:todos:store',
25);
26
27export default class TodoStore extends FeatureStore {
28 @observable stores: any = null;
29
30 @observable isFeatureActive = false;
31
32 @observable webview: Webview | undefined;
33
34 @observable userAgentModel = new UserAgent();
35
36 isInitialized = false;
37
38 actions: Actions | undefined;
39
40 _allReactions: Reaction[] | undefined;
41
42 constructor() {
43 super();
44
45 makeObservable(this);
46 }
47
48 @computed get width() {
49 const width = this.settings.width || DEFAULT_TODOS_WIDTH;
50
51 return width < TODOS_MIN_WIDTH ? TODOS_MIN_WIDTH : width;
52 }
53
54 @computed get isTodosPanelForceHidden() {
55 return !this.isFeatureEnabledByUser;
56 }
57
58 @computed get isTodosPanelVisible() {
59 if (this.settings.isTodosPanelVisible === undefined) {
60 return DEFAULT_TODOS_VISIBLE;
61 }
62 return this.settings.isTodosPanelVisible;
63 }
64
65 @computed get isFeatureEnabledByUser() {
66 return this.settings.isFeatureEnabledByUser;
67 }
68
69 @computed get settings() {
70 return localStorage.getItem('todos') || {};
71 }
72
73 @computed get userAgent() {
74 return this.userAgentModel.userAgent;
75 }
76
77 @computed get isUsingPredefinedTodoServer() {
78 return (
79 this.stores &&
80 this.stores.settings.app.predefinedTodoServer !== CUSTOM_TODO_SERVICE
81 );
82 }
83
84 @computed get todoUrl() {
85 if (!this.stores) {
86 return null;
87 }
88 return this.isUsingPredefinedTodoServer
89 ? this.stores.settings.app.predefinedTodoServer
90 : this.stores.settings.app.customTodoServer;
91 }
92
93 @computed get isTodoUrlValid() {
94 return (
95 !this.isUsingPredefinedTodoServer || isValidExternalURL(this.todoUrl)
96 );
97 }
98
99 @computed get todoRecipeId() {
100 if (
101 this.isFeatureEnabledByUser &&
102 this.isUsingPredefinedTodoServer &&
103 this.todoUrl in TODO_SERVICE_RECIPE_IDS
104 ) {
105 return TODO_SERVICE_RECIPE_IDS[this.todoUrl];
106 }
107 return null;
108 }
109
110 // ========== PUBLIC API ========= //
111
112 @action start(stores, actions) {
113 debug('TodoStore::start');
114 this.stores = stores;
115 this.actions = actions;
116
117 // ACTIONS
118
119 this._registerActions(
120 createActionBindings([
121 [todoActions.resize, this._resize],
122 [todoActions.toggleTodosPanel, this._toggleTodosPanel],
123 [todoActions.setTodosWebview, this._setTodosWebview],
124 [todoActions.handleHostMessage, this._handleHostMessage],
125 [todoActions.handleClientMessage, this._handleClientMessage],
126 [
127 todoActions.toggleTodosFeatureVisibility,
128 this._toggleTodosFeatureVisibility,
129 ],
130 [todoActions.openDevTools, this._openDevTools],
131 [todoActions.reload, this._reload],
132 ]),
133 );
134
135 // REACTIONS
136
137 this._allReactions = createReactions([
138 this._updateTodosConfig,
139 this._firstLaunchReaction,
140 this._routeCheckReaction,
141 ]);
142
143 this._registerReactions(this._allReactions);
144
145 this.isFeatureActive = true;
146 }
147
148 @action stop() {
149 super.stop();
150 debug('TodoStore::stop');
151 // this.reset(); // TODO - [TECH DEBT][PROP NOT IN CLASS] check it later
152 this.isFeatureActive = false;
153 }
154
155 // ========== PRIVATE METHODS ========= //
156
157 _updateSettings = changes => {
158 localStorage.setItem('todos', {
159 ...this.settings,
160 ...changes,
161 });
162 };
163
164 // Actions
165
166 @action _resize = ({ width }) => {
167 this._updateSettings({
168 width,
169 });
170 };
171
172 @action _toggleTodosPanel = () => {
173 this._updateSettings({
174 isTodosPanelVisible: !this.isTodosPanelVisible,
175 });
176 };
177
178 @action _setTodosWebview = ({ webview }) => {
179 debug('_setTodosWebview', webview);
180 if (this.webview !== webview) {
181 this.webview = webview;
182 this.userAgentModel.setWebviewReference(webview);
183 }
184 };
185
186 @action _handleHostMessage = message => {
187 debug('_handleHostMessage', message);
188 if (message.action === 'todos:create') {
189 this.webview.send(IPC.TODOS_HOST_CHANNEL, message);
190 }
191 };
192
193 @action _handleClientMessage = ({
194 channel,
195 message = { action: '', data: { url: '', serviceId: '' } },
196 }) => {
197 debug('_handleClientMessage', channel, message);
198 switch (message.action) {
199 case 'todos:initialized':
200 this._onTodosClientInitialized();
201 break;
202 case 'todos:goToService':
203 this._goToService(message.data);
204 break;
205 default:
206 debug('Other message received', channel, message);
207 if (this.stores.services.isTodosServiceAdded && this.actions) {
208 this.actions.service.handleIPCMessage({
209 serviceId: this.stores.services.isTodosServiceAdded.id,
210 channel,
211 args: message,
212 });
213 }
214 }
215 };
216
217 _handleNewWindowEvent = ({ url }) => {
218 if (!this.actions) {
219 return;
220 }
221 this.actions.app.openExternalUrl({ url });
222 };
223
224 @action _toggleTodosFeatureVisibility = () => {
225 debug('_toggleTodosFeatureVisibility');
226
227 const isFeatureEnabled = !this.settings.isFeatureEnabledByUser;
228 this._updateSettings({
229 isFeatureEnabledByUser: isFeatureEnabled,
230 isTodosPanelVisible: isFeatureEnabled,
231 });
232 };
233
234 _openDevTools = () => {
235 debug('_openDevTools');
236
237 const webview = document.querySelector<Webview>('#todos-panel webview');
238 if (webview) {
239 webview.openDevTools();
240 }
241 };
242
243 _reload = () => {
244 debug('_reload');
245
246 const webview = document.querySelector<Webview>('#todos-panel webview');
247 if (webview) {
248 webview.reload();
249 }
250 };
251
252 // Todos client message handlers
253
254 _onTodosClientInitialized = async () => {
255 const { authToken } = this.stores.user;
256 const { isDarkThemeActive } = this.stores.ui;
257 const { locale } = this.stores.app;
258 if (!this.webview) return;
259 await this.webview.send(IPC.TODOS_HOST_CHANNEL, {
260 action: 'todos:configure',
261 data: {
262 authToken,
263 locale,
264 theme: isDarkThemeActive ? ThemeType.dark : ThemeType.default,
265 },
266 });
267
268 if (!this.isInitialized) {
269 this.webview.addEventListener('new-window', this._handleNewWindowEvent);
270
271 this.isInitialized = true;
272 }
273 };
274
275 _goToService = ({ url, serviceId }) => {
276 if (url) {
277 this.stores.services.one(serviceId).webview.loadURL(url);
278 }
279 if (this.actions) {
280 this.actions.service.setActive({ serviceId });
281 }
282 };
283
284 // Reactions
285
286 _updateTodosConfig = () => {
287 // Resend the config if any part changes in Franz:
288 this._onTodosClientInitialized();
289 };
290
291 _firstLaunchReaction = () => {
292 const { stats } = this.stores.settings.all;
293
294 if (this.settings.isFeatureEnabledByUser === undefined) {
295 this._updateSettings({
296 isFeatureEnabledByUser: DEFAULT_IS_TODO_FEATURE_ENABLED_BY_USER,
297 });
298 }
299
300 // Hide todos layer on first app start but show on second
301 if (stats.appStarts <= 1) {
302 this._updateSettings({
303 isTodosPanelVisible: false,
304 });
305 } else if (stats.appStarts <= 2) {
306 this._updateSettings({
307 isTodosPanelVisible: true,
308 });
309 }
310 };
311
312 _routeCheckReaction = () => {
313 const { pathname } = this.stores.router.location;
314
315 if (pathname === TODOS_ROUTES.TARGET) {
316 debug('Router is on todos route, show todos panel');
317 // todosStore.start(stores, actions);
318 this.stores.router.push('/');
319
320 if (!this.isTodosPanelVisible) {
321 this._updateSettings({
322 isTodosPanelVisible: true,
323 });
324 }
325 }
326 };
327}