aboutsummaryrefslogtreecommitdiffstats
path: root/src/models
diff options
context:
space:
mode:
authorLibravatar Ricardo Cino <ricardo@cino.io>2022-06-23 18:10:39 +0200
committerLibravatar GitHub <noreply@github.com>2022-06-23 16:10:39 +0000
commit6b2c2b8dfb86245a1747bf7977159f5129461863 (patch)
tree28944f62a962d8a658262ea902f8554d4419fa9e /src/models
parentchore: featureStore and GlobalErrorStore JS => TS (diff)
downloadferdium-app-6b2c2b8dfb86245a1747bf7977159f5129461863.tar.gz
ferdium-app-6b2c2b8dfb86245a1747bf7977159f5129461863.tar.zst
ferdium-app-6b2c2b8dfb86245a1747bf7977159f5129461863.zip
chore: servicesStore + models into typescript (#344)
Diffstat (limited to 'src/models')
-rw-r--r--src/models/Recipe.ts56
-rw-r--r--src/models/Service.ts (renamed from src/models/Service.js)188
-rw-r--r--src/models/UserAgent.ts (renamed from src/models/UserAgent.js)41
3 files changed, 157 insertions, 128 deletions
diff --git a/src/models/Recipe.ts b/src/models/Recipe.ts
index be889d22c..eb8b0b1ff 100644
--- a/src/models/Recipe.ts
+++ b/src/models/Recipe.ts
@@ -2,7 +2,7 @@ import semver from 'semver';
2import { pathExistsSync } from 'fs-extra'; 2import { pathExistsSync } from 'fs-extra';
3import { join } from 'path'; 3import { join } from 'path';
4import { DEFAULT_SERVICE_SETTINGS } from '../config'; 4import { DEFAULT_SERVICE_SETTINGS } from '../config';
5import { ifUndefinedString, ifUndefinedBoolean } from '../jsUtils'; 5import { ifUndefined } from '../jsUtils';
6 6
7interface IRecipe { 7interface IRecipe {
8 id: string; 8 id: string;
@@ -34,7 +34,7 @@ export default class Recipe {
34 34
35 name: string = ''; 35 name: string = '';
36 36
37 description = ''; 37 description: string = '';
38 38
39 version: string = ''; 39 version: string = '';
40 40
@@ -75,6 +75,19 @@ export default class Recipe {
75 // TODO: Is this being used? 75 // TODO: Is this being used?
76 local: boolean = false; 76 local: boolean = false;
77 77
78 // TODO Add types for this once we know if they are neccesary to pass
79 // on to the initialize-recipe ipc event.
80 overrideUserAgent: any;
81
82 buildUrl: any;
83
84 modifyRequestHeaders: any;
85
86 knownCertificateHosts: any;
87
88 events: any;
89 // End todo.
90
78 // TODO: Need to reconcile which of these are optional/mandatory 91 // TODO: Need to reconcile which of these are optional/mandatory
79 constructor(data: IRecipe) { 92 constructor(data: IRecipe) {
80 if (!data) { 93 if (!data) {
@@ -93,61 +106,64 @@ export default class Recipe {
93 } 106 }
94 107
95 // from the recipe 108 // from the recipe
96 this.id = ifUndefinedString(data.id, this.id); 109 this.id = ifUndefined<string>(data.id, this.id);
97 this.name = ifUndefinedString(data.name, this.name); 110 this.name = ifUndefined<string>(data.name, this.name);
98 this.version = ifUndefinedString(data.version, this.version); 111 this.version = ifUndefined<string>(data.version, this.version);
99 this.aliases = data.aliases || this.aliases; 112 this.aliases = data.aliases || this.aliases;
100 this.serviceURL = ifUndefinedString( 113 this.serviceURL = ifUndefined<string>(
101 data.config.serviceURL, 114 data.config.serviceURL,
102 this.serviceURL, 115 this.serviceURL,
103 ); 116 );
104 this.hasDirectMessages = ifUndefinedBoolean( 117 this.hasDirectMessages = ifUndefined<boolean>(
105 data.config.hasDirectMessages, 118 data.config.hasDirectMessages,
106 this.hasDirectMessages, 119 this.hasDirectMessages,
107 ); 120 );
108 this.hasIndirectMessages = ifUndefinedBoolean( 121 this.hasIndirectMessages = ifUndefined<boolean>(
109 data.config.hasIndirectMessages, 122 data.config.hasIndirectMessages,
110 this.hasIndirectMessages, 123 this.hasIndirectMessages,
111 ); 124 );
112 this.hasNotificationSound = ifUndefinedBoolean( 125 this.hasNotificationSound = ifUndefined<boolean>(
113 data.config.hasNotificationSound, 126 data.config.hasNotificationSound,
114 this.hasNotificationSound, 127 this.hasNotificationSound,
115 ); 128 );
116 this.hasTeamId = ifUndefinedBoolean(data.config.hasTeamId, this.hasTeamId); 129 this.hasTeamId = ifUndefined<boolean>(
117 this.hasCustomUrl = ifUndefinedBoolean( 130 data.config.hasTeamId,
131 this.hasTeamId,
132 );
133 this.hasCustomUrl = ifUndefined<boolean>(
118 data.config.hasCustomUrl, 134 data.config.hasCustomUrl,
119 this.hasCustomUrl, 135 this.hasCustomUrl,
120 ); 136 );
121 this.hasHostedOption = ifUndefinedBoolean( 137 this.hasHostedOption = ifUndefined<boolean>(
122 data.config.hasHostedOption, 138 data.config.hasHostedOption,
123 this.hasHostedOption, 139 this.hasHostedOption,
124 ); 140 );
125 this.urlInputPrefix = ifUndefinedString( 141 this.urlInputPrefix = ifUndefined<string>(
126 data.config.urlInputPrefix, 142 data.config.urlInputPrefix,
127 this.urlInputPrefix, 143 this.urlInputPrefix,
128 ); 144 );
129 this.urlInputSuffix = ifUndefinedString( 145 this.urlInputSuffix = ifUndefined<string>(
130 data.config.urlInputSuffix, 146 data.config.urlInputSuffix,
131 this.urlInputSuffix, 147 this.urlInputSuffix,
132 ); 148 );
133 this.disablewebsecurity = ifUndefinedBoolean( 149 this.disablewebsecurity = ifUndefined<boolean>(
134 data.config.disablewebsecurity, 150 data.config.disablewebsecurity,
135 this.disablewebsecurity, 151 this.disablewebsecurity,
136 ); 152 );
137 this.autoHibernate = ifUndefinedBoolean( 153 this.autoHibernate = ifUndefined<boolean>(
138 data.config.autoHibernate, 154 data.config.autoHibernate,
139 this.autoHibernate, 155 this.autoHibernate,
140 ); 156 );
141 this.local = ifUndefinedBoolean(data.config.local, this.local); 157 this.local = ifUndefined<boolean>(data.config.local, this.local);
142 this.message = ifUndefinedString(data.config.message, this.message); 158 this.message = ifUndefined<string>(data.config.message, this.message);
143 this.allowFavoritesDelineationInUnreadCount = ifUndefinedBoolean( 159 this.allowFavoritesDelineationInUnreadCount = ifUndefined<boolean>(
144 data.config.allowFavoritesDelineationInUnreadCount, 160 data.config.allowFavoritesDelineationInUnreadCount,
145 this.allowFavoritesDelineationInUnreadCount, 161 this.allowFavoritesDelineationInUnreadCount,
146 ); 162 );
147 163
148 // computed 164 // computed
149 this.path = data.path; 165 this.path = data.path;
150 this.partition = ifUndefinedString(data.config.partition, this.partition); 166 this.partition = ifUndefined<string>(data.config.partition, this.partition);
151 } 167 }
152 168
153 // TODO: Need to remove this if its not used anywhere 169 // TODO: Need to remove this if its not used anywhere
diff --git a/src/models/Service.js b/src/models/Service.ts
index 53285e440..c4165e59a 100644
--- a/src/models/Service.js
+++ b/src/models/Service.ts
@@ -3,114 +3,121 @@ import { ipcRenderer } from 'electron';
3import { webContents } from '@electron/remote'; 3import { webContents } from '@electron/remote';
4import normalizeUrl from 'normalize-url'; 4import normalizeUrl from 'normalize-url';
5import { join } from 'path'; 5import { join } from 'path';
6import ElectronWebView from 'react-electron-web-view';
6 7
7import { todosStore } from '../features/todos'; 8import { todosStore } from '../features/todos';
8import { isValidExternalURL } from '../helpers/url-helpers'; 9import { isValidExternalURL } from '../helpers/url-helpers';
9import UserAgent from './UserAgent'; 10import UserAgent from './UserAgent';
10import { DEFAULT_SERVICE_ORDER } from '../config'; 11import { DEFAULT_SERVICE_ORDER } from '../config';
11import { 12import { ifUndefined } from '../jsUtils';
12 ifUndefinedString, 13import Recipe from './Recipe';
13 ifUndefinedBoolean,
14 ifUndefinedNumber,
15} from '../jsUtils';
16 14
17const debug = require('../preload-safe-debug')('Ferdium:Service'); 15const debug = require('../preload-safe-debug')('Ferdium:Service');
18 16
19// TODO: Shouldn't most of these values default to what's defined in DEFAULT_SERVICE_SETTINGS? 17// TODO: Shouldn't most of these values default to what's defined in DEFAULT_SERVICE_SETTINGS?
20export default class Service { 18export default class Service {
21 id = ''; 19 id: string = '';
22 20
23 recipe = null; 21 recipe: Recipe;
24 22
25 _webview = null; 23 _webview: ElectronWebView | null = null;
26 24
27 timer = null; 25 timer: NodeJS.Timeout | null = null;
28 26
29 events = {}; 27 events = {};
30 28
31 @observable isAttached = false; 29 @observable isAttached: boolean = false;
32 30
33 @observable isActive = false; // Is current webview active 31 @observable isActive: boolean = false; // Is current webview active
34 32
35 @observable name = ''; 33 @observable name: string = '';
36 34
37 @observable unreadDirectMessageCount = 0; 35 @observable unreadDirectMessageCount: number = 0;
38 36
39 @observable unreadIndirectMessageCount = 0; 37 @observable unreadIndirectMessageCount: number = 0;
40 38
41 @observable dialogTitle = ''; 39 @observable dialogTitle: string = '';
42 40
43 @observable order = DEFAULT_SERVICE_ORDER; 41 @observable order: number = DEFAULT_SERVICE_ORDER;
44 42
45 @observable isEnabled = true; 43 @observable isEnabled: boolean = true;
46 44
47 @observable isMuted = false; 45 @observable isMuted: boolean = false;
48 46
49 @observable team = ''; 47 @observable team: string = '';
50 48
51 @observable customUrl = ''; 49 @observable customUrl: string = '';
52 50
53 @observable isNotificationEnabled = true; 51 @observable isNotificationEnabled: boolean = true;
54 52
55 @observable isBadgeEnabled = true; 53 @observable isBadgeEnabled: boolean = true;
56 54
57 @observable trapLinkClicks = false; 55 @observable trapLinkClicks: boolean = false;
58 56
59 @observable isIndirectMessageBadgeEnabled = true; 57 @observable isIndirectMessageBadgeEnabled: boolean = true;
60 58
61 @observable iconUrl = ''; 59 @observable iconUrl: string = '';
62 60
63 @observable hasCustomUploadedIcon = false; 61 @observable customIconUrl: string = '';
64 62
65 @observable hasCrashed = false; 63 @observable hasCustomUploadedIcon: boolean = false;
66 64
67 @observable isDarkModeEnabled = false; 65 @observable hasCrashed: boolean = false;
68 66
69 @observable isProgressbarEnabled = true; 67 @observable isDarkModeEnabled: boolean = false;
70 68
71 @observable darkReaderSettings = { brightness: 100, contrast: 90, sepia: 10 }; 69 @observable isProgressbarEnabled: boolean = true;
72 70
73 @observable spellcheckerLanguage = null; 71 @observable darkReaderSettings: object = {
72 brightness: 100,
73 contrast: 90,
74 sepia: 10,
75 };
74 76
75 @observable isFirstLoad = true; 77 @observable spellcheckerLanguage: string | null = null;
76 78
77 @observable isLoading = true; 79 @observable isFirstLoad: boolean = true;
78 80
79 @observable isLoadingPage = true; 81 @observable isLoading: boolean = true;
80 82
81 @observable isError = false; 83 @observable isLoadingPage: boolean = true;
82 84
83 @observable errorMessage = ''; 85 @observable isError: boolean = false;
84 86
85 @observable isUsingCustomUrl = false; 87 @observable errorMessage: string = '';
86 88
87 @observable isServiceAccessRestricted = false; 89 @observable isUsingCustomUrl: boolean = false;
88 90
91 @observable isServiceAccessRestricted: boolean = false;
92
93 // todo is this used?
89 @observable restrictionType = null; 94 @observable restrictionType = null;
90 95
91 @observable isHibernationEnabled = false; 96 @observable isHibernationEnabled: boolean = false;
97
98 @observable isWakeUpEnabled: boolean = true;
92 99
93 @observable isWakeUpEnabled = true; 100 @observable isHibernationRequested: boolean = false;
94 101
95 @observable isHibernationRequested = false; 102 @observable onlyShowFavoritesInUnreadCount: boolean = false;
96 103
97 @observable onlyShowFavoritesInUnreadCount = false; 104 @observable lastUsed: number = Date.now(); // timestamp
98 105
99 @observable lastUsed = Date.now(); // timestamp 106 @observable lastHibernated: number | null = null; // timestamp
100 107
101 @observable lastHibernated = null; // timestamp 108 @observable lastPoll: number = Date.now();
102 109
103 @observable lastPoll = Date.now(); 110 @observable lastPollAnswer: number = Date.now();
104 111
105 @observable lastPollAnswer = Date.now(); 112 @observable lostRecipeConnection: boolean = false;
106 113
107 @observable lostRecipeConnection = false; 114 @observable lostRecipeReloadAttempt: number = 0;
108 115
109 @observable lostRecipeReloadAttempt = 0; 116 @observable userAgentModel: UserAgent;
110 117
111 @observable userAgentModel = null; 118 @observable proxy: string | null = null;
112 119
113 constructor(data, recipe) { 120 constructor(data, recipe: Recipe) {
114 if (!data) { 121 if (!data) {
115 throw new Error('Service config not valid'); 122 throw new Error('Service config not valid');
116 } 123 }
@@ -123,64 +130,64 @@ export default class Service {
123 130
124 this.userAgentModel = new UserAgent(recipe.overrideUserAgent); 131 this.userAgentModel = new UserAgent(recipe.overrideUserAgent);
125 132
126 this.id = ifUndefinedString(data.id, this.id); 133 this.id = ifUndefined<string>(data.id, this.id);
127 this.name = ifUndefinedString(data.name, this.name); 134 this.name = ifUndefined<string>(data.name, this.name);
128 this.team = ifUndefinedString(data.team, this.team); 135 this.team = ifUndefined<string>(data.team, this.team);
129 this.customUrl = ifUndefinedString(data.customUrl, this.customUrl); 136 this.customUrl = ifUndefined<string>(data.customUrl, this.customUrl);
130 this.iconUrl = ifUndefinedString(data.iconUrl, this.iconUrl); 137 this.iconUrl = ifUndefined<string>(data.iconUrl, this.iconUrl);
131 this.order = ifUndefinedNumber(data.order, this.order); 138 this.order = ifUndefined<number>(data.order, this.order);
132 this.isEnabled = ifUndefinedBoolean(data.isEnabled, this.isEnabled); 139 this.isEnabled = ifUndefined<boolean>(data.isEnabled, this.isEnabled);
133 this.isNotificationEnabled = ifUndefinedBoolean( 140 this.isNotificationEnabled = ifUndefined<boolean>(
134 data.isNotificationEnabled, 141 data.isNotificationEnabled,
135 this.isNotificationEnabled, 142 this.isNotificationEnabled,
136 ); 143 );
137 this.isBadgeEnabled = ifUndefinedBoolean( 144 this.isBadgeEnabled = ifUndefined<boolean>(
138 data.isBadgeEnabled, 145 data.isBadgeEnabled,
139 this.isBadgeEnabled, 146 this.isBadgeEnabled,
140 ); 147 );
141 this.trapLinkClicks = ifUndefinedBoolean( 148 this.trapLinkClicks = ifUndefined<boolean>(
142 data.trapLinkClicks, 149 data.trapLinkClicks,
143 this.trapLinkClicks, 150 this.trapLinkClicks,
144 ); 151 );
145 this.isIndirectMessageBadgeEnabled = ifUndefinedBoolean( 152 this.isIndirectMessageBadgeEnabled = ifUndefined<boolean>(
146 data.isIndirectMessageBadgeEnabled, 153 data.isIndirectMessageBadgeEnabled,
147 this.isIndirectMessageBadgeEnabled, 154 this.isIndirectMessageBadgeEnabled,
148 ); 155 );
149 this.isMuted = ifUndefinedBoolean(data.isMuted, this.isMuted); 156 this.isMuted = ifUndefined<boolean>(data.isMuted, this.isMuted);
150 this.isDarkModeEnabled = ifUndefinedBoolean( 157 this.isDarkModeEnabled = ifUndefined<boolean>(
151 data.isDarkModeEnabled, 158 data.isDarkModeEnabled,
152 this.isDarkModeEnabled, 159 this.isDarkModeEnabled,
153 ); 160 );
154 this.darkReaderSettings = ifUndefinedString( 161 this.darkReaderSettings = ifUndefined<object>(
155 data.darkReaderSettings, 162 data.darkReaderSettings,
156 this.darkReaderSettings, 163 this.darkReaderSettings,
157 ); 164 );
158 this.isProgressbarEnabled = ifUndefinedBoolean( 165 this.isProgressbarEnabled = ifUndefined<boolean>(
159 data.isProgressbarEnabled, 166 data.isProgressbarEnabled,
160 this.isProgressbarEnabled, 167 this.isProgressbarEnabled,
161 ); 168 );
162 this.hasCustomUploadedIcon = ifUndefinedBoolean( 169 this.hasCustomUploadedIcon = ifUndefined<boolean>(
163 data.iconId?.length > 0, 170 data.iconId?.length > 0,
164 this.hasCustomUploadedIcon, 171 this.hasCustomUploadedIcon,
165 ); 172 );
166 this.onlyShowFavoritesInUnreadCount = ifUndefinedBoolean( 173 this.onlyShowFavoritesInUnreadCount = ifUndefined<boolean>(
167 data.onlyShowFavoritesInUnreadCount, 174 data.onlyShowFavoritesInUnreadCount,
168 this.onlyShowFavoritesInUnreadCount, 175 this.onlyShowFavoritesInUnreadCount,
169 ); 176 );
170 this.proxy = ifUndefinedString(data.proxy, this.proxy); 177 this.proxy = ifUndefined<string | null>(data.proxy, this.proxy);
171 this.spellcheckerLanguage = ifUndefinedString( 178 this.spellcheckerLanguage = ifUndefined<string | null>(
172 data.spellcheckerLanguage, 179 data.spellcheckerLanguage,
173 this.spellcheckerLanguage, 180 this.spellcheckerLanguage,
174 ); 181 );
175 this.userAgentPref = ifUndefinedString( 182 this.userAgentPref = ifUndefined<string | null>(
176 data.userAgentPref, 183 data.userAgentPref,
177 this.userAgentPref, 184 this.userAgentPref,
178 ); 185 );
179 this.isHibernationEnabled = ifUndefinedBoolean( 186 this.isHibernationEnabled = ifUndefined<boolean>(
180 data.isHibernationEnabled, 187 data.isHibernationEnabled,
181 this.isHibernationEnabled, 188 this.isHibernationEnabled,
182 ); 189 );
183 this.isWakeUpEnabled = ifUndefinedBoolean( 190 this.isWakeUpEnabled = ifUndefined<boolean>(
184 data.isWakeUpEnabled, 191 data.isWakeUpEnabled,
185 this.isWakeUpEnabled, 192 this.isWakeUpEnabled,
186 ); 193 );
@@ -195,7 +202,7 @@ export default class Service {
195 this.isHibernationRequested = true; 202 this.isHibernationRequested = true;
196 } 203 }
197 204
198 autorun(() => { 205 autorun((): void => {
199 if (!this.isEnabled) { 206 if (!this.isEnabled) {
200 this.webview = null; 207 this.webview = null;
201 this.isAttached = false; 208 this.isAttached = false;
@@ -209,7 +216,7 @@ export default class Service {
209 }); 216 });
210 } 217 }
211 218
212 @computed get shareWithWebview() { 219 @computed get shareWithWebview(): object {
213 return { 220 return {
214 id: this.id, 221 id: this.id,
215 spellcheckerLanguage: this.spellcheckerLanguage, 222 spellcheckerLanguage: this.spellcheckerLanguage,
@@ -224,19 +231,19 @@ export default class Service {
224 }; 231 };
225 } 232 }
226 233
227 @computed get isTodosService() { 234 @computed get isTodosService(): boolean {
228 return this.recipe.id === todosStore.todoRecipeId; 235 return this.recipe.id === todosStore.todoRecipeId;
229 } 236 }
230 237
231 @computed get canHibernate() { 238 @computed get canHibernate(): boolean {
232 return this.isHibernationEnabled; 239 return this.isHibernationEnabled;
233 } 240 }
234 241
235 @computed get isHibernating() { 242 @computed get isHibernating(): boolean {
236 return this.canHibernate && this.isHibernationRequested; 243 return this.canHibernate && this.isHibernationRequested;
237 } 244 }
238 245
239 get webview() { 246 get webview(): ElectronWebView | null {
240 if (this.isTodosService) { 247 if (this.isTodosService) {
241 return todosStore.webview; 248 return todosStore.webview;
242 } 249 }
@@ -248,9 +255,9 @@ export default class Service {
248 this._webview = webview; 255 this._webview = webview;
249 } 256 }
250 257
251 @computed get url() { 258 @computed get url(): string {
252 if (this.recipe.hasCustomUrl && this.customUrl) { 259 if (this.recipe.hasCustomUrl && this.customUrl) {
253 let url; 260 let url: string = '';
254 try { 261 try {
255 url = normalizeUrl(this.customUrl, { 262 url = normalizeUrl(this.customUrl, {
256 stripAuthentication: false, 263 stripAuthentication: false,
@@ -277,7 +284,7 @@ export default class Service {
277 return this.recipe.serviceURL; 284 return this.recipe.serviceURL;
278 } 285 }
279 286
280 @computed get icon() { 287 @computed get icon(): string {
281 if (this.iconUrl) { 288 if (this.iconUrl) {
282 return this.iconUrl; 289 return this.iconUrl;
283 } 290 }
@@ -285,15 +292,15 @@ export default class Service {
285 return join(this.recipe.path, 'icon.svg'); 292 return join(this.recipe.path, 'icon.svg');
286 } 293 }
287 294
288 @computed get hasCustomIcon() { 295 @computed get hasCustomIcon(): boolean {
289 return Boolean(this.iconUrl); 296 return Boolean(this.iconUrl);
290 } 297 }
291 298
292 @computed get userAgent() { 299 @computed get userAgent(): string {
293 return this.userAgentModel.userAgent; 300 return this.userAgentModel.userAgent;
294 } 301 }
295 302
296 @computed get userAgentPref() { 303 @computed get userAgentPref(): string | null {
297 return this.userAgentModel.userAgentPref; 304 return this.userAgentModel.userAgentPref;
298 } 305 }
299 306
@@ -301,15 +308,15 @@ export default class Service {
301 this.userAgentModel.userAgentPref = pref; 308 this.userAgentModel.userAgentPref = pref;
302 } 309 }
303 310
304 @computed get defaultUserAgent() { 311 @computed get defaultUserAgent(): String {
305 return this.userAgentModel.defaultUserAgent; 312 return this.userAgentModel.defaultUserAgent;
306 } 313 }
307 314
308 @computed get partition() { 315 @computed get partition(): string {
309 return this.recipe.partition || `persist:service-${this.id}`; 316 return this.recipe.partition || `persist:service-${this.id}`;
310 } 317 }
311 318
312 initializeWebViewEvents({ handleIPCMessage, openWindow, stores }) { 319 initializeWebViewEvents({ handleIPCMessage, openWindow, stores }): void {
313 const webviewWebContents = webContents.fromId( 320 const webviewWebContents = webContents.fromId(
314 this.webview.getWebContentsId(), 321 this.webview.getWebContentsId(),
315 ); 322 );
@@ -401,6 +408,7 @@ export default class Service {
401 this.isLoadingPage = false; 408 this.isLoadingPage = false;
402 }); 409 });
403 410
411 // eslint-disable-next-line unicorn/consistent-function-scoping
404 const didLoad = () => { 412 const didLoad = () => {
405 this.isLoading = false; 413 this.isLoading = false;
406 this.isLoadingPage = false; 414 this.isLoadingPage = false;
@@ -437,7 +445,7 @@ export default class Service {
437 this.webview.send('found-in-page', result); 445 this.webview.send('found-in-page', result);
438 }); 446 });
439 447
440 webviewWebContents.on('login', (event, request, authInfo, callback) => { 448 webviewWebContents.on('login', (event, _, authInfo, callback) => {
441 // const authCallback = callback; 449 // const authCallback = callback;
442 debug('browser login event', authInfo); 450 debug('browser login event', authInfo);
443 event.preventDefault(); 451 event.preventDefault();
@@ -460,7 +468,7 @@ export default class Service {
460 }); 468 });
461 } 469 }
462 470
463 initializeWebViewListener() { 471 initializeWebViewListener(): void {
464 if (this.webview && this.recipe.events) { 472 if (this.webview && this.recipe.events) {
465 for (const eventName of Object.keys(this.recipe.events)) { 473 for (const eventName of Object.keys(this.recipe.events)) {
466 const eventHandler = this.recipe[this.recipe.events[eventName]]; 474 const eventHandler = this.recipe[this.recipe.events[eventName]];
@@ -471,7 +479,7 @@ export default class Service {
471 } 479 }
472 } 480 }
473 481
474 resetMessageCount() { 482 resetMessageCount(): void {
475 this.unreadDirectMessageCount = 0; 483 this.unreadDirectMessageCount = 0;
476 this.unreadIndirectMessageCount = 0; 484 this.unreadIndirectMessageCount = 0;
477 } 485 }
diff --git a/src/models/UserAgent.js b/src/models/UserAgent.ts
index 3e1394b45..1d06d72b0 100644
--- a/src/models/UserAgent.js
+++ b/src/models/UserAgent.ts
@@ -1,25 +1,28 @@
1import { action, computed, observe, observable } from 'mobx'; 1import { action, computed, observe, observable } from 'mobx';
2 2
3import ElectronWebView from 'react-electron-web-view';
3import defaultUserAgent from '../helpers/userAgent-helpers'; 4import defaultUserAgent from '../helpers/userAgent-helpers';
4 5
5const debug = require('../preload-safe-debug')('Ferdium:UserAgent'); 6const debug = require('../preload-safe-debug')('Ferdium:UserAgent');
6 7
7export default class UserAgent { 8export default class UserAgent {
8 _willNavigateListener = null; 9 // eslint-disable-next-line @typescript-eslint/no-unused-vars
10 _willNavigateListener = (_event: any): void => {};
9 11
10 _didNavigateListener = null; 12 // eslint-disable-next-line @typescript-eslint/no-unused-vars
13 _didNavigateListener = (_event: any): void => {};
11 14
12 @observable.ref webview = null; 15 @observable.ref webview: ElectronWebView = null;
13 16
14 @observable chromelessUserAgent = false; 17 @observable chromelessUserAgent: boolean = false;
15 18
16 @observable userAgentPref = null; 19 @observable userAgentPref: string | null = null;
17 20
18 @observable getUserAgent = null; 21 @observable overrideUserAgent = (): string => '';
19 22
20 constructor(overrideUserAgent = null) { 23 constructor(overrideUserAgent: any = null) {
21 if (typeof overrideUserAgent === 'function') { 24 if (typeof overrideUserAgent === 'function') {
22 this.getUserAgent = overrideUserAgent; 25 this.overrideUserAgent = overrideUserAgent;
23 } 26 }
24 27
25 observe(this, 'webview', change => { 28 observe(this, 'webview', change => {
@@ -33,10 +36,12 @@ export default class UserAgent {
33 }); 36 });
34 } 37 }
35 38
36 @computed get defaultUserAgent() { 39 @computed get defaultUserAgent(): string {
37 if (typeof this.getUserAgent === 'function') { 40 const replacedUserAgent = this.overrideUserAgent();
38 return this.getUserAgent(); 41 if (replacedUserAgent.length > 0) {
42 return replacedUserAgent;
39 } 43 }
44
40 const globalPref = window['ferdium'].stores.settings.all.app.userAgentPref; 45 const globalPref = window['ferdium'].stores.settings.all.app.userAgentPref;
41 if (typeof globalPref === 'string') { 46 if (typeof globalPref === 'string') {
42 const trimmed = globalPref.trim(); 47 const trimmed = globalPref.trim();
@@ -47,7 +52,7 @@ export default class UserAgent {
47 return defaultUserAgent(); 52 return defaultUserAgent();
48 } 53 }
49 54
50 @computed get serviceUserAgentPref() { 55 @computed get serviceUserAgentPref(): string | null {
51 if (typeof this.userAgentPref === 'string') { 56 if (typeof this.userAgentPref === 'string') {
52 const trimmed = this.userAgentPref.trim(); 57 const trimmed = this.userAgentPref.trim();
53 if (trimmed !== '') { 58 if (trimmed !== '') {
@@ -57,12 +62,12 @@ export default class UserAgent {
57 return null; 62 return null;
58 } 63 }
59 64
60 @computed get userAgentWithoutChromeVersion() { 65 @computed get userAgentWithoutChromeVersion(): string {
61 const withChrome = this.defaultUserAgent; 66 const withChrome = this.defaultUserAgent;
62 return withChrome.replace(/Chrome\/[\d.]+/, 'Chrome'); 67 return withChrome.replace(/Chrome\/[\d.]+/, 'Chrome');
63 } 68 }
64 69
65 @computed get userAgent() { 70 @computed get userAgent(): string {
66 return ( 71 return (
67 this.serviceUserAgentPref || 72 this.serviceUserAgentPref ||
68 (this.chromelessUserAgent 73 (this.chromelessUserAgent
@@ -71,11 +76,11 @@ export default class UserAgent {
71 ); 76 );
72 } 77 }
73 78
74 @action setWebviewReference(webview) { 79 @action setWebviewReference(webview: ElectronWebView): void {
75 this.webview = webview; 80 this.webview = webview;
76 } 81 }
77 82
78 @action _handleNavigate(url, forwardingHack = false) { 83 @action _handleNavigate(url: string, forwardingHack: boolean = false): void {
79 if (url.startsWith('https://accounts.google.com')) { 84 if (url.startsWith('https://accounts.google.com')) {
80 if (!this.chromelessUserAgent) { 85 if (!this.chromelessUserAgent) {
81 debug('Setting user agent to chromeless for url', url); 86 debug('Setting user agent to chromeless for url', url);
@@ -92,7 +97,7 @@ export default class UserAgent {
92 } 97 }
93 } 98 }
94 99
95 _addWebviewEvents(webview) { 100 _addWebviewEvents(webview: ElectronWebView): void {
96 debug('Adding event handlers'); 101 debug('Adding event handlers');
97 102
98 this._willNavigateListener = event => this._handleNavigate(event.url, true); 103 this._willNavigateListener = event => this._handleNavigate(event.url, true);
@@ -102,7 +107,7 @@ export default class UserAgent {
102 webview.addEventListener('did-navigate', this._didNavigateListener); 107 webview.addEventListener('did-navigate', this._didNavigateListener);
103 } 108 }
104 109
105 _removeWebviewEvents(webview) { 110 _removeWebviewEvents(webview: ElectronWebView): void {
106 debug('Removing event handlers'); 111 debug('Removing event handlers');
107 112
108 webview.removeEventListener('will-navigate', this._willNavigateListener); 113 webview.removeEventListener('will-navigate', this._willNavigateListener);