aboutsummaryrefslogtreecommitdiffstats
path: root/src/models
diff options
context:
space:
mode:
authorLibravatar Markus Hatvan <markus_hatvan@aon.at>2021-09-14 19:58:52 +0200
committerLibravatar GitHub <noreply@github.com>2021-09-14 19:58:52 +0200
commit95df3522a15631abc51a4295cae0ea401a8d4e1e (patch)
treee5eb0f368c947683f01458e912f21756fb0d99cb /src/models
parentdocs: add sad270 as a contributor for bug, userTesting [skip ci] (#1941) (diff)
downloadferdium-app-95df3522a15631abc51a4295cae0ea401a8d4e1e.tar.gz
ferdium-app-95df3522a15631abc51a4295cae0ea401a8d4e1e.tar.zst
ferdium-app-95df3522a15631abc51a4295cae0ea401a8d4e1e.zip
feat: add eslint-plugin-unicorn (#1936)
Diffstat (limited to 'src/models')
-rw-r--r--src/models/News.ts6
-rw-r--r--src/models/Recipe.ts6
-rw-r--r--src/models/RecipePreview.ts6
-rw-r--r--src/models/Service.js142
-rw-r--r--src/models/User.ts4
-rw-r--r--src/models/UserAgent.js19
6 files changed, 116 insertions, 67 deletions
diff --git a/src/models/News.ts b/src/models/News.ts
index a6ff86dda..4fc21f590 100644
--- a/src/models/News.ts
+++ b/src/models/News.ts
@@ -1,5 +1,3 @@
1// @flow
2
3import { ifUndefinedString, ifUndefinedBoolean } from '../jsUtils'; 1import { ifUndefinedString, ifUndefinedBoolean } from '../jsUtils';
4 2
5interface INews { 3interface INews {
@@ -20,11 +18,11 @@ export default class News {
20 18
21 constructor(data: INews) { 19 constructor(data: INews) {
22 if (!data) { 20 if (!data) {
23 throw Error('News config not valid'); 21 throw new Error('News config not valid');
24 } 22 }
25 23
26 if (!data.id) { 24 if (!data.id) {
27 throw Error('News requires Id'); 25 throw new Error('News requires Id');
28 } 26 }
29 27
30 this.id = data.id; 28 this.id = data.id;
diff --git a/src/models/Recipe.ts b/src/models/Recipe.ts
index 0a93fbc5a..6022fb520 100644
--- a/src/models/Recipe.ts
+++ b/src/models/Recipe.ts
@@ -68,16 +68,16 @@ export default class Recipe {
68 // TODO: Need to reconcile which of these are optional/mandatory 68 // TODO: Need to reconcile which of these are optional/mandatory
69 constructor(data: IRecipe) { 69 constructor(data: IRecipe) {
70 if (!data) { 70 if (!data) {
71 throw Error('Recipe config not valid'); 71 throw new Error('Recipe config not valid');
72 } 72 }
73 73
74 if (!data.id) { 74 if (!data.id) {
75 // Ferdi 4 recipes do not have an Id 75 // Ferdi 4 recipes do not have an Id
76 throw Error(`Recipe '${data.name}' requires Id`); 76 throw new Error(`Recipe '${data.name}' requires Id`);
77 } 77 }
78 78
79 if (!semver.valid(data.version)) { 79 if (!semver.valid(data.version)) {
80 throw Error(`Version ${data.version} of recipe '${data.name}' is not a valid semver version`); 80 throw new Error(`Version ${data.version} of recipe '${data.name}' is not a valid semver version`);
81 } 81 }
82 82
83 this.id = data.id || this.id; 83 this.id = data.id || this.id;
diff --git a/src/models/RecipePreview.ts b/src/models/RecipePreview.ts
index 4d2cc8450..fb8cb3e3e 100644
--- a/src/models/RecipePreview.ts
+++ b/src/models/RecipePreview.ts
@@ -1,5 +1,3 @@
1// @flow
2
3interface IRecipePreview { 1interface IRecipePreview {
4 id: string; 2 id: string;
5 name: string; 3 name: string;
@@ -21,11 +19,11 @@ export default class RecipePreview {
21 19
22 constructor(data: IRecipePreview) { 20 constructor(data: IRecipePreview) {
23 if (!data) { 21 if (!data) {
24 throw Error('RecipePreview config not valid'); 22 throw new Error('RecipePreview config not valid');
25 } 23 }
26 24
27 if (!data.id) { 25 if (!data.id) {
28 throw Error(`RecipePreview '${data.name}' requires Id`); 26 throw new Error(`RecipePreview '${data.name}' requires Id`);
29 } 27 }
30 28
31 Object.assign(this, data); 29 Object.assign(this, data);
diff --git a/src/models/Service.js b/src/models/Service.js
index 4ee054b2b..cc001f98d 100644
--- a/src/models/Service.js
+++ b/src/models/Service.js
@@ -8,7 +8,11 @@ import { todosStore } from '../features/todos';
8import { isValidExternalURL } from '../helpers/url-helpers'; 8import { isValidExternalURL } from '../helpers/url-helpers';
9import UserAgent from './UserAgent'; 9import UserAgent from './UserAgent';
10import { DEFAULT_SERVICE_ORDER } from '../config'; 10import { DEFAULT_SERVICE_ORDER } from '../config';
11import { ifUndefinedString, ifUndefinedBoolean, ifUndefinedNumber } from '../jsUtils'; 11import {
12 ifUndefinedString,
13 ifUndefinedBoolean,
14 ifUndefinedNumber,
15} from '../jsUtils';
12 16
13const debug = require('debug')('Ferdi:Service'); 17const debug = require('debug')('Ferdi:Service');
14 18
@@ -95,11 +99,11 @@ export default class Service {
95 99
96 constructor(data, recipe) { 100 constructor(data, recipe) {
97 if (!data) { 101 if (!data) {
98 throw Error('Service config not valid'); 102 throw new Error('Service config not valid');
99 } 103 }
100 104
101 if (!recipe) { 105 if (!recipe) {
102 throw Error('Service recipe not valid'); 106 throw new Error('Service recipe not valid');
103 } 107 }
104 108
105 this.recipe = recipe; 109 this.recipe = recipe;
@@ -115,22 +119,51 @@ export default class Service {
115 119
116 this.order = ifUndefinedNumber(data.order, this.order); 120 this.order = ifUndefinedNumber(data.order, this.order);
117 this.isEnabled = ifUndefinedBoolean(data.isEnabled, this.isEnabled); 121 this.isEnabled = ifUndefinedBoolean(data.isEnabled, this.isEnabled);
118 this.isNotificationEnabled = ifUndefinedBoolean(data.isNotificationEnabled, this.isNotificationEnabled); 122 this.isNotificationEnabled = ifUndefinedBoolean(
119 this.isBadgeEnabled = ifUndefinedBoolean(data.isBadgeEnabled, this.isBadgeEnabled); 123 data.isNotificationEnabled,
120 this.isIndirectMessageBadgeEnabled = ifUndefinedBoolean(data.isIndirectMessageBadgeEnabled, this.isIndirectMessageBadgeEnabled); 124 this.isNotificationEnabled,
125 );
126 this.isBadgeEnabled = ifUndefinedBoolean(
127 data.isBadgeEnabled,
128 this.isBadgeEnabled,
129 );
130 this.isIndirectMessageBadgeEnabled = ifUndefinedBoolean(
131 data.isIndirectMessageBadgeEnabled,
132 this.isIndirectMessageBadgeEnabled,
133 );
121 this.isMuted = ifUndefinedBoolean(data.isMuted, this.isMuted); 134 this.isMuted = ifUndefinedBoolean(data.isMuted, this.isMuted);
122 this.isDarkModeEnabled = ifUndefinedBoolean(data.isDarkModeEnabled, this.isDarkModeEnabled); 135 this.isDarkModeEnabled = ifUndefinedBoolean(
123 this.darkReaderSettings = ifUndefinedString(data.darkReaderSettings, this.darkReaderSettings); 136 data.isDarkModeEnabled,
124 this.hasCustomUploadedIcon = ifUndefinedBoolean(data.hasCustomIcon, this.hasCustomUploadedIcon); 137 this.isDarkModeEnabled,
138 );
139 this.darkReaderSettings = ifUndefinedString(
140 data.darkReaderSettings,
141 this.darkReaderSettings,
142 );
143 this.hasCustomUploadedIcon = ifUndefinedBoolean(
144 data.hasCustomIcon,
145 this.hasCustomUploadedIcon,
146 );
125 this.proxy = ifUndefinedString(data.proxy, this.proxy); 147 this.proxy = ifUndefinedString(data.proxy, this.proxy);
126 this.spellcheckerLanguage = ifUndefinedString(data.spellcheckerLanguage, this.spellcheckerLanguage); 148 this.spellcheckerLanguage = ifUndefinedString(
127 this.userAgentPref = ifUndefinedString(data.userAgentPref, this.userAgentPref); 149 data.spellcheckerLanguage,
128 this.isHibernationEnabled = ifUndefinedBoolean(data.isHibernationEnabled, this.isHibernationEnabled); 150 this.spellcheckerLanguage,
151 );
152 this.userAgentPref = ifUndefinedString(
153 data.userAgentPref,
154 this.userAgentPref,
155 );
156 this.isHibernationEnabled = ifUndefinedBoolean(
157 data.isHibernationEnabled,
158 this.isHibernationEnabled,
159 );
129 160
130 // Check if "Hibernate on Startup" is enabled and hibernate all services except active one 161 // Check if "Hibernate on Startup" is enabled and hibernate all services except active one
131 const { hibernateOnStartup } = window.ferdi.stores.settings.app; 162 const { hibernateOnStartup } = window.ferdi.stores.settings.app;
132 // The service store is probably not loaded yet so we need to use localStorage data to get active service 163 // The service store is probably not loaded yet so we need to use localStorage data to get active service
133 const isActive = window.localStorage.service && JSON.parse(window.localStorage.service).activeService === this.id; 164 const isActive =
165 window.localStorage.service &&
166 JSON.parse(window.localStorage.service).activeService === this.id;
134 if (hibernateOnStartup && !isActive) { 167 if (hibernateOnStartup && !isActive) {
135 this.isHibernationRequested = true; 168 this.isHibernationRequested = true;
136 } 169 }
@@ -189,9 +222,14 @@ export default class Service {
189 if (this.recipe.hasCustomUrl && this.customUrl) { 222 if (this.recipe.hasCustomUrl && this.customUrl) {
190 let url; 223 let url;
191 try { 224 try {
192 url = normalizeUrl(this.customUrl, { stripWWW: false, removeTrailingSlash: false }); 225 url = normalizeUrl(this.customUrl, {
193 } catch (err) { 226 stripWWW: false,
194 console.error(`Service (${this.recipe.name}): '${this.customUrl}' is not a valid Url.`); 227 removeTrailingSlash: false,
228 });
229 } catch {
230 console.error(
231 `Service (${this.recipe.name}): '${this.customUrl}' is not a valid Url.`,
232 );
195 } 233 }
196 234
197 if (typeof this.recipe.buildUrl === 'function') { 235 if (typeof this.recipe.buildUrl === 'function') {
@@ -241,7 +279,9 @@ export default class Service {
241 } 279 }
242 280
243 initializeWebViewEvents({ handleIPCMessage, openWindow, stores }) { 281 initializeWebViewEvents({ handleIPCMessage, openWindow, stores }) {
244 const webviewWebContents = webContents.fromId(this.webview.getWebContentsId()); 282 const webviewWebContents = webContents.fromId(
283 this.webview.getWebContentsId(),
284 );
245 285
246 this.userAgentModel.setWebviewReference(this.webview); 286 this.userAgentModel.setWebviewReference(this.webview);
247 287
@@ -270,9 +310,15 @@ export default class Service {
270 debug(this.name, 'knownCertificateHosts is not defined in the recipe'); 310 debug(this.name, 'knownCertificateHosts is not defined in the recipe');
271 } 311 }
272 312
273 this.webview.addEventListener('ipc-message', async (e) => { 313 this.webview.addEventListener('ipc-message', async e => {
274 if (e.channel === 'inject-js-unsafe') { 314 if (e.channel === 'inject-js-unsafe') {
275 await Promise.all(e.args.map((script) => this.webview.executeJavaScript(`"use strict"; (() => { ${script} })();`))); 315 await Promise.all(
316 e.args.map(script =>
317 this.webview.executeJavaScript(
318 `"use strict"; (() => { ${script} })();`,
319 ),
320 ),
321 );
276 } else { 322 } else {
277 handleIPCMessage({ 323 handleIPCMessage({
278 serviceId: this.id, 324 serviceId: this.id,
@@ -282,27 +328,33 @@ export default class Service {
282 } 328 }
283 }); 329 });
284 330
285 this.webview.addEventListener('new-window', (event, url, frameName, options) => { 331 this.webview.addEventListener(
286 debug('new-window', event, url, frameName, options); 332 'new-window',
287 if (!isValidExternalURL(event.url)) { 333 (event, url, frameName, options) => {
288 return; 334 debug('new-window', event, url, frameName, options);
289 } 335 if (!isValidExternalURL(event.url)) {
290 if (event.disposition === 'foreground-tab' || event.disposition === 'background-tab') { 336 return;
291 openWindow({ 337 }
292 event, 338 if (
293 url, 339 event.disposition === 'foreground-tab' ||
294 frameName, 340 event.disposition === 'background-tab'
295 options, 341 ) {
296 }); 342 openWindow({
297 } else { 343 event,
298 ipcRenderer.send('open-browser-window', { 344 url,
299 url: event.url, 345 frameName,
300 serviceId: this.id, 346 options,
301 }); 347 });
302 } 348 } else {
303 }); 349 ipcRenderer.send('open-browser-window', {
350 url: event.url,
351 serviceId: this.id,
352 });
353 }
354 },
355 );
304 356
305 this.webview.addEventListener('did-start-loading', (event) => { 357 this.webview.addEventListener('did-start-loading', event => {
306 debug('Did start load', this.name, event); 358 debug('Did start load', this.name, event);
307 359
308 this.hasCrashed = false; 360 this.hasCrashed = false;
@@ -321,9 +373,13 @@ export default class Service {
321 this.webview.addEventListener('did-frame-finish-load', didLoad.bind(this)); 373 this.webview.addEventListener('did-frame-finish-load', didLoad.bind(this));
322 this.webview.addEventListener('did-navigate', didLoad.bind(this)); 374 this.webview.addEventListener('did-navigate', didLoad.bind(this));
323 375
324 this.webview.addEventListener('did-fail-load', (event) => { 376 this.webview.addEventListener('did-fail-load', event => {
325 debug('Service failed to load', this.name, event); 377 debug('Service failed to load', this.name, event);
326 if (event.isMainFrame && event.errorCode !== -21 && event.errorCode !== -3) { 378 if (
379 event.isMainFrame &&
380 event.errorCode !== -21 &&
381 event.errorCode !== -3
382 ) {
327 this.isError = true; 383 this.isError = true;
328 this.errorMessage = event.errorDescription; 384 this.errorMessage = event.errorDescription;
329 this.isLoading = false; 385 this.isLoading = false;
@@ -365,12 +421,12 @@ export default class Service {
365 421
366 initializeWebViewListener() { 422 initializeWebViewListener() {
367 if (this.webview && this.recipe.events) { 423 if (this.webview && this.recipe.events) {
368 Object.keys(this.recipe.events).forEach((eventName) => { 424 for (const eventName of Object.keys(this.recipe.events)) {
369 const eventHandler = this.recipe[this.recipe.events[eventName]]; 425 const eventHandler = this.recipe[this.recipe.events[eventName]];
370 if (typeof eventHandler === 'function') { 426 if (typeof eventHandler === 'function') {
371 this.webview.addEventListener(eventName, eventHandler); 427 this.webview.addEventListener(eventName, eventHandler);
372 } 428 }
373 }); 429 }
374 } 430 }
375 } 431 }
376 432
diff --git a/src/models/User.ts b/src/models/User.ts
index 54a6838df..a04d46d3c 100644
--- a/src/models/User.ts
+++ b/src/models/User.ts
@@ -43,11 +43,11 @@ export default class User {
43 43
44 constructor(data: IUser) { 44 constructor(data: IUser) {
45 if (!data) { 45 if (!data) {
46 throw Error('User config not valid'); 46 throw new Error('User config not valid');
47 } 47 }
48 48
49 if (!data.id) { 49 if (!data.id) {
50 throw Error('User requires Id'); 50 throw new Error('User requires Id');
51 } 51 }
52 52
53 this.id = data.id; 53 this.id = data.id;
diff --git a/src/models/UserAgent.js b/src/models/UserAgent.js
index 930ae19ef..8ec274aa5 100644
--- a/src/models/UserAgent.js
+++ b/src/models/UserAgent.js
@@ -1,9 +1,4 @@
1import { 1import { action, computed, observe, observable } from 'mobx';
2 action,
3 computed,
4 observe,
5 observable,
6} from 'mobx';
7 2
8import defaultUserAgent from '../helpers/userAgent-helpers'; 3import defaultUserAgent from '../helpers/userAgent-helpers';
9 4
@@ -27,7 +22,7 @@ export default class UserAgent {
27 this.getUserAgent = overrideUserAgent; 22 this.getUserAgent = overrideUserAgent;
28 } 23 }
29 24
30 observe(this, 'webview', (change) => { 25 observe(this, 'webview', change => {
31 const { oldValue, newValue } = change; 26 const { oldValue, newValue } = change;
32 if (oldValue !== null) { 27 if (oldValue !== null) {
33 this._removeWebviewEvents(oldValue); 28 this._removeWebviewEvents(oldValue);
@@ -64,11 +59,13 @@ export default class UserAgent {
64 59
65 @computed get userAgentWithoutChromeVersion() { 60 @computed get userAgentWithoutChromeVersion() {
66 const withChrome = this.userAgentWithChromeVersion; 61 const withChrome = this.userAgentWithChromeVersion;
67 return withChrome.replace(/Chrome\/[0-9.]+/, 'Chrome'); 62 return withChrome.replace(/Chrome\/[\d.]+/, 'Chrome');
68 } 63 }
69 64
70 @computed get userAgent() { 65 @computed get userAgent() {
71 return this.chromelessUserAgent ? this.userAgentWithoutChromeVersion : this.userAgentWithChromeVersion; 66 return this.chromelessUserAgent
67 ? this.userAgentWithoutChromeVersion
68 : this.userAgentWithChromeVersion;
72 } 69 }
73 70
74 @action setWebviewReference(webview) { 71 @action setWebviewReference(webview) {
@@ -95,10 +92,10 @@ export default class UserAgent {
95 _addWebviewEvents(webview) { 92 _addWebviewEvents(webview) {
96 debug('Adding event handlers'); 93 debug('Adding event handlers');
97 94
98 this._willNavigateListener = (event) => this._handleNavigate(event.url, true); 95 this._willNavigateListener = event => this._handleNavigate(event.url, true);
99 webview.addEventListener('will-navigate', this._willNavigateListener); 96 webview.addEventListener('will-navigate', this._willNavigateListener);
100 97
101 this._didNavigateListener = (event) => this._handleNavigate(event.url); 98 this._didNavigateListener = event => this._handleNavigate(event.url);
102 webview.addEventListener('did-navigate', this._didNavigateListener); 99 webview.addEventListener('did-navigate', this._didNavigateListener);
103 } 100 }
104 101