diff options
-rw-r--r-- | src/@types/stores.types.ts | 4 | ||||
-rw-r--r-- | src/config.ts | 1 | ||||
-rw-r--r-- | src/webview/find.ts | 4 | ||||
-rw-r--r-- | src/webview/lib/RecipeWebview.ts | 2 | ||||
-rw-r--r-- | src/webview/recipe.ts (renamed from src/webview/recipe.js) | 72 |
5 files changed, 45 insertions, 38 deletions
diff --git a/src/@types/stores.types.ts b/src/@types/stores.types.ts index bf2dc8bd2..bbb37cff9 100644 --- a/src/@types/stores.types.ts +++ b/src/@types/stores.types.ts | |||
@@ -78,7 +78,7 @@ interface TypedStore { | |||
78 | resetStatus: () => void; | 78 | resetStatus: () => void; |
79 | } | 79 | } |
80 | 80 | ||
81 | interface AppStore extends TypedStore { | 81 | export interface AppStore extends TypedStore { |
82 | accentColor: string; | 82 | accentColor: string; |
83 | adaptableDarkMode: boolean; | 83 | adaptableDarkMode: boolean; |
84 | progressbarAccentColor: string; | 84 | progressbarAccentColor: string; |
@@ -102,7 +102,7 @@ interface AppStore extends TypedStore { | |||
102 | isOnline: boolean; | 102 | isOnline: boolean; |
103 | isSystemDarkModeEnabled: () => void; | 103 | isSystemDarkModeEnabled: () => void; |
104 | isSystemMuteOverridden: () => void; | 104 | isSystemMuteOverridden: () => void; |
105 | locale: () => void; | 105 | locale: string; |
106 | lockedPassword: string; | 106 | lockedPassword: string; |
107 | reloadAfterResume: boolean; | 107 | reloadAfterResume: boolean; |
108 | reloadAfterResumeTime: number; | 108 | reloadAfterResumeTime: number; |
diff --git a/src/config.ts b/src/config.ts index 4bd1ca155..e4baf27c5 100644 --- a/src/config.ts +++ b/src/config.ts | |||
@@ -456,4 +456,5 @@ export const DEFAULT_SERVICE_SETTINGS = { | |||
456 | hasHostedOption: false, | 456 | hasHostedOption: false, |
457 | allowFavoritesDelineationInUnreadCount: false, | 457 | allowFavoritesDelineationInUnreadCount: false, |
458 | disablewebsecurity: false, | 458 | disablewebsecurity: false, |
459 | spellcheckerLanguage: false, | ||
459 | }; | 460 | }; |
diff --git a/src/webview/find.ts b/src/webview/find.ts index 0665d9670..ead818b07 100644 --- a/src/webview/find.ts +++ b/src/webview/find.ts | |||
@@ -24,4 +24,8 @@ export default class FindInPage extends ElectronFindInPage { | |||
24 | constructor(options = {}) { | 24 | constructor(options = {}) { |
25 | super(webContentsShim, options); | 25 | super(webContentsShim, options); |
26 | } | 26 | } |
27 | |||
28 | openFindWindow() { | ||
29 | super.openFindWindow(); | ||
30 | } | ||
27 | } | 31 | } |
diff --git a/src/webview/lib/RecipeWebview.ts b/src/webview/lib/RecipeWebview.ts index a896f1b6e..20be3f866 100644 --- a/src/webview/lib/RecipeWebview.ts +++ b/src/webview/lib/RecipeWebview.ts | |||
@@ -39,7 +39,7 @@ class RecipeWebview { | |||
39 | 39 | ||
40 | loopFunc = () => null; | 40 | loopFunc = () => null; |
41 | 41 | ||
42 | darkModeHandler = false; | 42 | darkModeHandler: ((darkMode: boolean, config: any) => void) | null = null; |
43 | 43 | ||
44 | // TODO Remove this once we implement a proper wrapper. | 44 | // TODO Remove this once we implement a proper wrapper. |
45 | get ipcRenderer() { | 45 | get ipcRenderer() { |
diff --git a/src/webview/recipe.js b/src/webview/recipe.ts index acf4f9f31..887d9c367 100644 --- a/src/webview/recipe.js +++ b/src/webview/recipe.ts | |||
@@ -1,19 +1,14 @@ | |||
1 | /* eslint-disable global-require */ | 1 | /* eslint-disable global-require */ |
2 | /* eslint-disable import/no-dynamic-require */ | ||
2 | /* eslint-disable import/first */ | 3 | /* eslint-disable import/first */ |
3 | import { contextBridge, ipcRenderer } from 'electron'; | 4 | import { contextBridge, ipcRenderer } from 'electron'; |
4 | import { join } from 'path'; | 5 | import { join } from 'path'; |
5 | import { autorun, computed, makeObservable, observable } from 'mobx'; | 6 | import { autorun, computed, makeObservable, observable } from 'mobx'; |
6 | import { pathExistsSync, readFileSync } from 'fs-extra'; | 7 | import { pathExistsSync, readFileSync } from 'fs-extra'; |
7 | import { debounce } from 'lodash'; | 8 | import { debounce } from 'lodash'; |
8 | |||
9 | // For some services darkreader tries to use the chrome extension message API | ||
10 | // This will cause the service to fail loading | ||
11 | // As the message API is not actually needed, we'll add this shim sendMessage | ||
12 | // function in order for darkreader to continue working | ||
13 | window.chrome.runtime.sendMessage = () => {}; | ||
14 | import { | 9 | import { |
15 | enable as enableDarkMode, | ||
16 | disable as disableDarkMode, | 10 | disable as disableDarkMode, |
11 | enable as enableDarkMode, | ||
17 | } from 'darkreader'; | 12 | } from 'darkreader'; |
18 | 13 | ||
19 | import { existsSync } from 'fs'; | 14 | import { existsSync } from 'fs'; |
@@ -35,8 +30,8 @@ import { | |||
35 | } from './darkmode'; | 30 | } from './darkmode'; |
36 | import FindInPage from './find'; | 31 | import FindInPage from './find'; |
37 | import { | 32 | import { |
38 | NotificationsHandler, | ||
39 | notificationsClassDefinition, | 33 | notificationsClassDefinition, |
34 | NotificationsHandler, | ||
40 | } from './notifications'; | 35 | } from './notifications'; |
41 | import { | 36 | import { |
42 | getDisplayMediaSelector, | 37 | getDisplayMediaSelector, |
@@ -44,12 +39,20 @@ import { | |||
44 | screenShareJs, | 39 | screenShareJs, |
45 | } from './screenshare'; | 40 | } from './screenshare'; |
46 | import { | 41 | import { |
47 | switchDict, | ||
48 | getSpellcheckerLocaleByFuzzyIdentifier, | 42 | getSpellcheckerLocaleByFuzzyIdentifier, |
43 | switchDict, | ||
49 | } from './spellchecker'; | 44 | } from './spellchecker'; |
50 | 45 | ||
51 | import { DEFAULT_APP_SETTINGS } from '../config'; | ||
52 | import { ifUndefinedString } from '../jsUtils'; | 46 | import { ifUndefinedString } from '../jsUtils'; |
47 | import { AppStore } from '../@types/stores.types'; | ||
48 | import Service from '../models/Service'; | ||
49 | |||
50 | // For some services darkreader tries to use the chrome extension message API | ||
51 | // This will cause the service to fail loading | ||
52 | // As the message API is not actually needed, we'll add this shim sendMessage | ||
53 | // function in order for darkreader to continue working | ||
54 | // @ts-ignore | ||
55 | window.chrome.runtime.sendMessage = () => {}; | ||
53 | 56 | ||
54 | const debug = require('../preload-safe-debug')('Ferdium:Plugin'); | 57 | const debug = require('../preload-safe-debug')('Ferdium:Plugin'); |
55 | 58 | ||
@@ -64,7 +67,7 @@ const notificationsHandler = new NotificationsHandler(); | |||
64 | // Patching window.open | 67 | // Patching window.open |
65 | const originalWindowOpen = window.open; | 68 | const originalWindowOpen = window.open; |
66 | 69 | ||
67 | window.open = (url, frameName, features) => { | 70 | window.open = (url, frameName, features): WindowProxy | null => { |
68 | debug('window.open', url, frameName, features); | 71 | debug('window.open', url, frameName, features); |
69 | if (!url) { | 72 | if (!url) { |
70 | // The service hasn't yet supplied a URL (as used in Skype). | 73 | // The service hasn't yet supplied a URL (as used in Skype). |
@@ -93,17 +96,19 @@ window.open = (url, frameName, features) => { | |||
93 | clearInterval(checkInterval); | 96 | clearInterval(checkInterval); |
94 | }, 1000); | 97 | }, 1000); |
95 | 98 | ||
96 | return newWindow; | 99 | return newWindow as Window; |
97 | } | 100 | } |
98 | 101 | ||
99 | // We need to differentiate if the link should be opened in a popup or in the systems default browser | 102 | // We need to differentiate if the link should be opened in a popup or in the systems default browser |
100 | if (!frameName && !features && typeof features !== 'string') { | 103 | if (!frameName && !features && typeof features !== 'string') { |
101 | return ipcRenderer.sendToHost('new-window', url); | 104 | ipcRenderer.sendToHost('new-window', url); |
105 | return null; | ||
102 | } | 106 | } |
103 | 107 | ||
104 | if (url) { | 108 | if (url) { |
105 | return originalWindowOpen(url, frameName, features); | 109 | return originalWindowOpen(url, frameName, features); |
106 | } | 110 | } |
111 | return null; | ||
107 | }; | 112 | }; |
108 | 113 | ||
109 | // We can't override APIs here, so we first expose functions via 'window.ferdium', | 114 | // We can't override APIs here, so we first expose functions via 'window.ferdium', |
@@ -126,17 +131,15 @@ ipcRenderer.sendToHost( | |||
126 | ); | 131 | ); |
127 | 132 | ||
128 | class RecipeController { | 133 | class RecipeController { |
129 | @observable settings = { | 134 | // @ts-ignore |
135 | @observable settings: { | ||
136 | overrideSpellcheckerLanguage: boolean; | ||
137 | app: AppStore; | ||
138 | service: Service; | ||
139 | } = { | ||
130 | overrideSpellcheckerLanguage: false, | 140 | overrideSpellcheckerLanguage: false, |
131 | app: DEFAULT_APP_SETTINGS, | ||
132 | service: { | ||
133 | isDarkModeEnabled: false, | ||
134 | spellcheckerLanguage: '', | ||
135 | }, | ||
136 | }; | 141 | }; |
137 | 142 | ||
138 | spellcheckProvider = null; | ||
139 | |||
140 | ipcEvents = { | 143 | ipcEvents = { |
141 | 'initialize-recipe': 'loadRecipeModule', | 144 | 'initialize-recipe': 'loadRecipeModule', |
142 | 'settings-update': 'updateAppSettings', | 145 | 'settings-update': 'updateAppSettings', |
@@ -147,9 +150,9 @@ class RecipeController { | |||
147 | 150 | ||
148 | universalDarkModeInjected = false; | 151 | universalDarkModeInjected = false; |
149 | 152 | ||
150 | recipe = null; | 153 | recipe: RecipeWebview | null = null; |
151 | 154 | ||
152 | userscript = null; | 155 | userscript: Userscript | null = null; |
153 | 156 | ||
154 | hasUpdatedBeforeRecipeLoaded = false; | 157 | hasUpdatedBeforeRecipeLoaded = false; |
155 | 158 | ||
@@ -166,9 +169,7 @@ class RecipeController { | |||
166 | ); | 169 | ); |
167 | } | 170 | } |
168 | 171 | ||
169 | cldIdentifier = null; | 172 | findInPage: FindInPage | null = null; |
170 | |||
171 | findInPage = null; | ||
172 | 173 | ||
173 | async initialize() { | 174 | async initialize() { |
174 | for (const channel of Object.keys(this.ipcEvents)) { | 175 | for (const channel of Object.keys(this.ipcEvents)) { |
@@ -181,7 +182,6 @@ class RecipeController { | |||
181 | debug('Send "hello" to host'); | 182 | debug('Send "hello" to host'); |
182 | setTimeout(() => ipcRenderer.sendToHost('hello'), 100); | 183 | setTimeout(() => ipcRenderer.sendToHost('hello'), 100); |
183 | 184 | ||
184 | this.spellcheckingProvider = null; | ||
185 | contextMenu( | 185 | contextMenu( |
186 | () => this.settings.app.enableSpellchecking, | 186 | () => this.settings.app.enableSpellchecking, |
187 | () => this.settings.app.spellcheckerLanguage, | 187 | () => this.settings.app.spellcheckerLanguage, |
@@ -216,7 +216,7 @@ class RecipeController { | |||
216 | }); | 216 | }); |
217 | } | 217 | } |
218 | 218 | ||
219 | loadRecipeModule(event, config, recipe) { | 219 | loadRecipeModule(_event, config, recipe) { |
220 | debug('loadRecipeModule'); | 220 | debug('loadRecipeModule'); |
221 | const modulePath = join(recipe.path, 'webview.js'); | 221 | const modulePath = join(recipe.path, 'webview.js'); |
222 | debug('module path', modulePath); | 222 | debug('module path', modulePath); |
@@ -230,7 +230,6 @@ class RecipeController { | |||
230 | sessionHandler, | 230 | sessionHandler, |
231 | ); | 231 | ); |
232 | if (existsSync(modulePath)) { | 232 | if (existsSync(modulePath)) { |
233 | // eslint-disable-next-line import/no-dynamic-require | ||
234 | require(modulePath)(this.recipe, { ...config, recipe }); | 233 | require(modulePath)(this.recipe, { ...config, recipe }); |
235 | debug('Initialize Recipe', config, recipe); | 234 | debug('Initialize Recipe', config, recipe); |
236 | } | 235 | } |
@@ -255,12 +254,11 @@ class RecipeController { | |||
255 | const data = readFileSync(userCss); | 254 | const data = readFileSync(userCss); |
256 | styles.innerHTML += data.toString(); | 255 | styles.innerHTML += data.toString(); |
257 | } | 256 | } |
258 | document.querySelector('head').append(styles); | 257 | document.querySelector('head')?.append(styles); |
259 | 258 | ||
260 | const userJs = join(recipe.path, 'user.js'); | 259 | const userJs = join(recipe.path, 'user.js'); |
261 | if (pathExistsSync(userJs)) { | 260 | if (pathExistsSync(userJs)) { |
262 | const loadUserJs = () => { | 261 | const loadUserJs = () => { |
263 | // eslint-disable-next-line import/no-dynamic-require | ||
264 | const userJsModule = require(userJs); | 262 | const userJsModule = require(userJs); |
265 | 263 | ||
266 | if (typeof userJsModule === 'function') { | 264 | if (typeof userJsModule === 'function') { |
@@ -280,7 +278,7 @@ class RecipeController { | |||
280 | } | 278 | } |
281 | 279 | ||
282 | openFindInPage() { | 280 | openFindInPage() { |
283 | this.findInPage.openFindWindow(); | 281 | this.findInPage?.openFindWindow(); |
284 | } | 282 | } |
285 | 283 | ||
286 | update() { | 284 | update() { |
@@ -328,6 +326,7 @@ class RecipeController { | |||
328 | 'Darkmode enabled?', | 326 | 'Darkmode enabled?', |
329 | this.settings.service.isDarkModeEnabled, | 327 | this.settings.service.isDarkModeEnabled, |
330 | 'Dark theme active?', | 328 | 'Dark theme active?', |
329 | // @ts-ignore | ||
331 | this.settings.app.isDarkThemeActive, | 330 | this.settings.app.isDarkThemeActive, |
332 | ); | 331 | ); |
333 | 332 | ||
@@ -375,6 +374,10 @@ class RecipeController { | |||
375 | { brightness, contrast, sepia }, | 374 | { brightness, contrast, sepia }, |
376 | { | 375 | { |
377 | css: customDarkModeCss[window.location.host] || '', | 376 | css: customDarkModeCss[window.location.host] || '', |
377 | invert: [], | ||
378 | ignoreImageAnalysis: [], | ||
379 | ignoreInlineStyle: [], | ||
380 | disableStyleSheetsProxy: false, | ||
378 | }, | 381 | }, |
379 | ); | 382 | ); |
380 | this.universalDarkModeInjected = true; | 383 | this.universalDarkModeInjected = true; |
@@ -415,11 +418,11 @@ class RecipeController { | |||
415 | } | 418 | } |
416 | } | 419 | } |
417 | 420 | ||
418 | updateAppSettings(event, data) { | 421 | updateAppSettings(_event, data) { |
419 | this.settings.app = Object.assign(this.settings.app, data); | 422 | this.settings.app = Object.assign(this.settings.app, data); |
420 | } | 423 | } |
421 | 424 | ||
422 | updateServiceSettings(event, data) { | 425 | updateServiceSettings(_event, data) { |
423 | this.settings.service = Object.assign(this.settings.service, data); | 426 | this.settings.service = Object.assign(this.settings.service, data); |
424 | } | 427 | } |
425 | 428 | ||
@@ -470,4 +473,3 @@ class RecipeController { | |||
470 | 473 | ||
471 | /* eslint-disable no-new */ | 474 | /* eslint-disable no-new */ |
472 | new RecipeController(); | 475 | new RecipeController(); |
473 | /* eslint-enable no-new */ | ||