aboutsummaryrefslogtreecommitdiffstats
path: root/src/containers/settings/EditServiceScreen.js
diff options
context:
space:
mode:
authorLibravatar Ricardo Cino <ricardo@cino.io>2022-06-27 18:21:31 +0200
committerLibravatar GitHub <noreply@github.com>2022-06-27 17:21:31 +0100
commit0bf13689d53bd493fb4d0a4213c1801013b5aa8a (patch)
tree2b5ae44e4f1aa73b49c011954ff1cb47e3959bad /src/containers/settings/EditServiceScreen.js
parentchore: recommend specific vscode extensions to setup development [skip ci] (#... (diff)
downloadferdium-app-0bf13689d53bd493fb4d0a4213c1801013b5aa8a.tar.gz
ferdium-app-0bf13689d53bd493fb4d0a4213c1801013b5aa8a.tar.zst
ferdium-app-0bf13689d53bd493fb4d0a4213c1801013b5aa8a.zip
chore: transform containers/settings from js to tsx (#384)
Diffstat (limited to 'src/containers/settings/EditServiceScreen.js')
-rw-r--r--src/containers/settings/EditServiceScreen.js472
1 files changed, 0 insertions, 472 deletions
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js
deleted file mode 100644
index 4615a9cdf..000000000
--- a/src/containers/settings/EditServiceScreen.js
+++ /dev/null
@@ -1,472 +0,0 @@
1import { Component } from 'react';
2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react';
4import { defineMessages, injectIntl } from 'react-intl';
5
6import { RouterStore } from 'mobx-react-router';
7import UserStore from '../../stores/UserStore';
8import RecipesStore from '../../stores/RecipesStore';
9import ServicesStore from '../../stores/ServicesStore';
10import SettingsStore from '../../stores/SettingsStore';
11import Form from '../../lib/Form';
12
13import ServiceError from '../../components/settings/services/ServiceError';
14import EditServiceForm from '../../components/settings/services/EditServiceForm';
15import ErrorBoundary from '../../components/util/ErrorBoundary';
16
17import { required, url, oneRequired } from '../../helpers/validation-helpers';
18import { getSelectOptions } from '../../helpers/i18n-helpers';
19
20import { config as proxyFeature } from '../../features/serviceProxy';
21
22import { SPELLCHECKER_LOCALES } from '../../i18n/languages';
23
24import globalMessages from '../../i18n/globalMessages';
25import { DEFAULT_APP_SETTINGS, DEFAULT_SERVICE_SETTINGS } from '../../config';
26
27const messages = defineMessages({
28 name: {
29 id: 'settings.service.form.name',
30 defaultMessage: 'Name',
31 },
32 enableService: {
33 id: 'settings.service.form.enableService',
34 defaultMessage: 'Enable service',
35 },
36 enableHibernation: {
37 id: 'settings.service.form.enableHibernation',
38 defaultMessage: 'Enable hibernation',
39 },
40 enableWakeUp: {
41 id: 'settings.service.form.enableWakeUp',
42 defaultMessage: 'Enable wake up',
43 },
44 enableNotification: {
45 id: 'settings.service.form.enableNotification',
46 defaultMessage: 'Enable notifications',
47 },
48 enableBadge: {
49 id: 'settings.service.form.enableBadge',
50 defaultMessage: 'Show unread message badges',
51 },
52 enableAudio: {
53 id: 'settings.service.form.enableAudio',
54 defaultMessage: 'Enable audio',
55 },
56 team: {
57 id: 'settings.service.form.team',
58 defaultMessage: 'Team',
59 },
60 customUrl: {
61 id: 'settings.service.form.customUrl',
62 defaultMessage: 'Custom server',
63 },
64 indirectMessages: {
65 id: 'settings.service.form.indirectMessages',
66 defaultMessage: 'Show message badge for all new messages',
67 },
68 icon: {
69 id: 'settings.service.form.icon',
70 defaultMessage: 'Custom icon',
71 },
72 enableDarkMode: {
73 id: 'settings.service.form.enableDarkMode',
74 defaultMessage: 'Enable Dark Mode',
75 },
76 darkReaderBrightness: {
77 id: 'settings.service.form.darkReaderBrightness',
78 defaultMessage: 'Dark Reader Brightness',
79 },
80 darkReaderContrast: {
81 id: 'settings.service.form.darkReaderContrast',
82 defaultMessage: 'Dark Reader Contrast',
83 },
84 darkReaderSepia: {
85 id: 'settings.service.form.darkReaderSepia',
86 defaultMessage: 'Dark Reader Sepia',
87 },
88 enableProgressbar: {
89 id: 'settings.service.form.enableProgressbar',
90 defaultMessage: 'Enable Progress bar',
91 },
92 trapLinkClicks: {
93 id: 'settings.service.form.trapLinkClicks',
94 defaultMessage: 'Open URLs within Ferdium',
95 },
96 onlyShowFavoritesInUnreadCount: {
97 id: 'settings.service.form.onlyShowFavoritesInUnreadCount',
98 defaultMessage: 'Only show Favorites in unread count',
99 },
100 enableProxy: {
101 id: 'settings.service.form.proxy.isEnabled',
102 defaultMessage: 'Use Proxy',
103 },
104 proxyHost: {
105 id: 'settings.service.form.proxy.host',
106 defaultMessage: 'Proxy Host/IP',
107 },
108 proxyPort: {
109 id: 'settings.service.form.proxy.port',
110 defaultMessage: 'Port',
111 },
112 proxyUser: {
113 id: 'settings.service.form.proxy.user',
114 defaultMessage: 'User (optional)',
115 },
116 proxyPassword: {
117 id: 'settings.service.form.proxy.password',
118 defaultMessage: 'Password (optional)',
119 },
120});
121
122class EditServiceScreen extends Component {
123 onSubmit(data) {
124 const { action } = this.props.router.params;
125 const { recipes, services } = this.props.stores;
126 const { createService, updateService } = this.props.actions.service;
127 data.darkReaderSettings = {
128 brightness: data.darkReaderBrightness,
129 contrast: data.darkReaderContrast,
130 sepia: data.darkReaderSepia,
131 };
132 delete data.darkReaderContrast;
133 delete data.darkReaderBrightness;
134 delete data.darkReaderSepia;
135
136 const serviceData = data;
137 serviceData.isMuted = !serviceData.isMuted;
138
139 if (action === 'edit') {
140 updateService({ serviceId: services.activeSettings.id, serviceData });
141 } else {
142 createService({ recipeId: recipes.active.id, serviceData });
143 }
144 }
145
146 prepareForm(recipe, service, proxy) {
147 const { intl } = this.props;
148
149 const { stores, router } = this.props;
150
151 const { action } = router.params;
152
153 let defaultSpellcheckerLanguage =
154 SPELLCHECKER_LOCALES[stores.settings.app.spellcheckerLanguage];
155
156 if (stores.settings.app.spellcheckerLanguage === 'automatic') {
157 defaultSpellcheckerLanguage = intl.formatMessage(
158 globalMessages.spellcheckerAutomaticDetectionShort,
159 );
160 }
161
162 const spellcheckerLanguage = getSelectOptions({
163 locales: SPELLCHECKER_LOCALES,
164 resetToDefaultText: intl.formatMessage(
165 globalMessages.spellcheckerSystemDefault,
166 { default: defaultSpellcheckerLanguage },
167 ),
168 automaticDetectionText:
169 stores.settings.app.spellcheckerLanguage !== 'automatic'
170 ? intl.formatMessage(globalMessages.spellcheckerAutomaticDetection)
171 : '',
172 });
173
174 const config = {
175 fields: {
176 name: {
177 label: intl.formatMessage(messages.name),
178 placeholder: intl.formatMessage(messages.name),
179 value: service.id ? service.name : recipe.name,
180 },
181 isEnabled: {
182 label: intl.formatMessage(messages.enableService),
183 value: service.isEnabled,
184 default: DEFAULT_SERVICE_SETTINGS.isEnabled,
185 },
186 isHibernationEnabled: {
187 label: intl.formatMessage(messages.enableHibernation),
188 value:
189 action !== 'edit'
190 ? recipe.autoHibernate
191 : service.isHibernationEnabled,
192 default: DEFAULT_SERVICE_SETTINGS.isHibernationEnabled,
193 },
194 isWakeUpEnabled: {
195 label: intl.formatMessage(messages.enableWakeUp),
196 value: service.isWakeUpEnabled,
197 default: DEFAULT_SERVICE_SETTINGS.isWakeUpEnabled,
198 },
199 isNotificationEnabled: {
200 label: intl.formatMessage(messages.enableNotification),
201 value: service.isNotificationEnabled,
202 default: DEFAULT_SERVICE_SETTINGS.isNotificationEnabled,
203 },
204 isBadgeEnabled: {
205 label: intl.formatMessage(messages.enableBadge),
206 value: service.isBadgeEnabled,
207 default: DEFAULT_SERVICE_SETTINGS.isBadgeEnabled,
208 },
209 trapLinkClicks: {
210 label: intl.formatMessage(messages.trapLinkClicks),
211 value: service.trapLinkClicks,
212 default: DEFAULT_SERVICE_SETTINGS.trapLinkClicks,
213 },
214 isMuted: {
215 label: intl.formatMessage(messages.enableAudio),
216 value: !service.isMuted,
217 default: DEFAULT_SERVICE_SETTINGS.isMuted,
218 },
219 customIcon: {
220 label: intl.formatMessage(messages.icon),
221 value: service.hasCustomUploadedIcon ? service.icon : false,
222 default: null,
223 type: 'file',
224 },
225 isDarkModeEnabled: {
226 label: intl.formatMessage(messages.enableDarkMode),
227 value: service.isDarkModeEnabled,
228 default: stores.settings.app.darkMode,
229 },
230 darkReaderBrightness: {
231 label: intl.formatMessage(messages.darkReaderBrightness),
232 value: service.darkReaderSettings
233 ? service.darkReaderSettings.brightness
234 : undefined,
235 default: 100,
236 },
237 darkReaderContrast: {
238 label: intl.formatMessage(messages.darkReaderContrast),
239 value: service.darkReaderSettings
240 ? service.darkReaderSettings.contrast
241 : undefined,
242 default: 90,
243 },
244 darkReaderSepia: {
245 label: intl.formatMessage(messages.darkReaderSepia),
246 value: service.darkReaderSettings
247 ? service.darkReaderSettings.sepia
248 : undefined,
249 default: 10,
250 },
251 isProgressbarEnabled: {
252 label: intl.formatMessage(messages.enableProgressbar),
253 value: service.isProgressbarEnabled,
254 default: DEFAULT_SERVICE_SETTINGS.isProgressbarEnabled,
255 },
256 spellcheckerLanguage: {
257 label: intl.formatMessage(globalMessages.spellcheckerLanguage),
258 value: service.spellcheckerLanguage,
259 options: spellcheckerLanguage,
260 disabled: !stores.settings.app.enableSpellchecking,
261 },
262 userAgentPref: {
263 label: intl.formatMessage(globalMessages.userAgentPref),
264 placeholder: service.defaultUserAgent,
265 value: service.userAgentPref ? service.userAgentPref : '',
266 },
267 },
268 };
269
270 if (recipe.hasTeamId) {
271 Object.assign(config.fields, {
272 team: {
273 label: intl.formatMessage(messages.team),
274 placeholder: intl.formatMessage(messages.team),
275 value: service.team,
276 validators: [required],
277 },
278 });
279 }
280
281 if (recipe.hasCustomUrl) {
282 Object.assign(config.fields, {
283 customUrl: {
284 label: intl.formatMessage(messages.customUrl),
285 placeholder: "'http://' or 'https://' or 'file:///'",
286 value: service.customUrl || recipe.serviceURL,
287 validators: [required, url],
288 },
289 });
290 }
291
292 // More fine grained and use case specific validation rules
293 if (recipe.hasTeamId && recipe.hasCustomUrl) {
294 config.fields.team.validators = [oneRequired(['team', 'customUrl'])];
295 config.fields.customUrl.validators = [
296 url,
297 oneRequired(['team', 'customUrl']),
298 ];
299 }
300
301 // If a service can be hosted and has a teamId or customUrl
302 if (recipe.hasHostedOption && (recipe.hasTeamId || recipe.hasCustomUrl)) {
303 if (config.fields.team) {
304 config.fields.team.validators = [];
305 }
306 if (config.fields.customUrl) {
307 config.fields.customUrl.validators = [url];
308 }
309 }
310
311 if (recipe.hasIndirectMessages) {
312 Object.assign(config.fields, {
313 isIndirectMessageBadgeEnabled: {
314 label: intl.formatMessage(messages.indirectMessages),
315 value: service.isIndirectMessageBadgeEnabled,
316 default: DEFAULT_SERVICE_SETTINGS.hasIndirectMessages,
317 },
318 });
319 }
320
321 if (recipe.allowFavoritesDelineationInUnreadCount) {
322 Object.assign(config.fields, {
323 onlyShowFavoritesInUnreadCount: {
324 label: intl.formatMessage(messages.onlyShowFavoritesInUnreadCount),
325 value: service.onlyShowFavoritesInUnreadCount,
326 default: DEFAULT_APP_SETTINGS.onlyShowFavoritesInUnreadCount,
327 },
328 });
329 }
330
331 if (proxy.isEnabled) {
332 const serviceProxyConfig = stores.settings.proxy[service.id] || {};
333
334 Object.assign(config.fields, {
335 proxy: {
336 name: 'proxy',
337 label: 'proxy',
338 fields: {
339 isEnabled: {
340 label: intl.formatMessage(messages.enableProxy),
341 value: serviceProxyConfig.isEnabled,
342 default: DEFAULT_APP_SETTINGS.proxyFeatureEnabled,
343 },
344 host: {
345 label: intl.formatMessage(messages.proxyHost),
346 value: serviceProxyConfig.host,
347 default: '',
348 },
349 port: {
350 label: intl.formatMessage(messages.proxyPort),
351 value: serviceProxyConfig.port,
352 default: '',
353 },
354 user: {
355 label: intl.formatMessage(messages.proxyUser),
356 value: serviceProxyConfig.user,
357 default: '',
358 },
359 password: {
360 label: intl.formatMessage(messages.proxyPassword),
361 value: serviceProxyConfig.password,
362 default: '',
363 type: 'password',
364 },
365 },
366 },
367 });
368 }
369
370 return new Form(config);
371 }
372
373 deleteService() {
374 const { deleteService } = this.props.actions.service;
375 const { action } = this.props.router.params;
376
377 if (action === 'edit') {
378 const { activeSettings: service } = this.props.stores.services;
379 deleteService({
380 serviceId: service.id,
381 redirect: '/settings/services',
382 });
383 }
384 }
385
386 openRecipeFile(file) {
387 const { openRecipeFile } = this.props.actions.service;
388 const { action } = this.props.router.params;
389
390 if (action === 'edit') {
391 const { activeSettings: service } = this.props.stores.services;
392 openRecipeFile({
393 recipe: service.recipe.id,
394 file,
395 });
396 }
397 }
398
399 render() {
400 const { recipes, services, user } = this.props.stores;
401 const { action } = this.props.router.params;
402
403 let recipe;
404 let service = {};
405 let isLoading = false;
406
407 if (action === 'add') {
408 recipe = recipes.active;
409
410 // TODO: render error message when recipe is `null`
411 if (!recipe) {
412 return <ServiceError />;
413 }
414 } else {
415 service = services.activeSettings;
416 isLoading = services.allServicesRequest.isExecuting;
417
418 if (!isLoading && service) {
419 recipe = service.recipe;
420 }
421 }
422
423 if (isLoading) {
424 return <div>Loading...</div>;
425 }
426
427 if (!recipe) {
428 return <div>something went wrong</div>;
429 }
430
431 const form = this.prepareForm(recipe, service, proxyFeature);
432
433 return (
434 <ErrorBoundary>
435 <EditServiceForm
436 action={action}
437 recipe={recipe}
438 service={service}
439 user={user.data}
440 form={form}
441 status={services.actionStatus}
442 isSaving={
443 services.updateServiceRequest.isExecuting ||
444 services.createServiceRequest.isExecuting
445 }
446 isDeleting={services.deleteServiceRequest.isExecuting}
447 onSubmit={d => this.onSubmit(d)}
448 onDelete={() => this.deleteService()}
449 openRecipeFile={file => this.openRecipeFile(file)}
450 isProxyFeatureEnabled={proxyFeature.isEnabled}
451 />
452 </ErrorBoundary>
453 );
454 }
455}
456
457EditServiceScreen.propTypes = {
458 stores: PropTypes.shape({
459 user: PropTypes.instanceOf(UserStore).isRequired,
460 recipes: PropTypes.instanceOf(RecipesStore).isRequired,
461 services: PropTypes.instanceOf(ServicesStore).isRequired,
462 settings: PropTypes.instanceOf(SettingsStore).isRequired,
463 }).isRequired,
464 router: PropTypes.instanceOf(RouterStore).isRequired,
465 actions: PropTypes.shape({
466 service: PropTypes.instanceOf(ServicesStore).isRequired,
467 }).isRequired,
468};
469
470export default injectIntl(
471 inject('stores', 'actions')(observer(EditServiceScreen)),
472);