aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar MCMXC <16797721+mcmxcdev@users.noreply.github.com>2023-07-23 20:08:52 -0600
committerLibravatar Vijay Aravamudhan <vraravam@users.noreply.github.com>2023-07-25 07:45:23 +0000
commit8c131073730ec684145c2cc8ee8d6b39bbe9278d (patch)
tree1129d432ae88475909f0e5d38960395b75364902 /src
parent6.4.1-nightly.11 [skip ci] (diff)
downloadferdium-app-8c131073730ec684145c2cc8ee8d6b39bbe9278d.tar.gz
ferdium-app-8c131073730ec684145c2cc8ee8d6b39bbe9278d.tar.zst
ferdium-app-8c131073730ec684145c2cc8ee8d6b39bbe9278d.zip
chore: improve lint setup
- update eslint config - merged eslint rules for JS and TS to avoid duplicates - extended stricter lint ruleset from typescript-eslint - corrected wrong setup for certain eslint rulesets - opt in to reportUnusedDisableDirectives config option - fix or disable a lot of lint issues throughout codebase - remove trailingComma: all from prettier config which is default in prettier v3 - add volta configuration to package.json to autoload correct node and pnpm versions - upgrade all eslint and prettier related dependencies to latest - remove config options from settings.json which are default anyways - remove config options from settings.json which are outdated/unknown - set up prettier as default formatter in settings.json
Diffstat (limited to 'src')
-rw-r--r--src/@types/ferdium.types.ts1
-rw-r--r--src/@types/stores.types.ts1
-rw-r--r--src/actions/lib/actions.ts1
-rw-r--r--src/api/apiBase.ts7
-rw-r--r--src/api/server/ServerApi.ts2
-rw-r--r--src/app.tsx2
-rw-r--r--src/components/AppUpdateInfoBar.tsx1
-rw-r--r--src/components/auth/Login.tsx1
-rw-r--r--src/components/auth/Welcome.tsx4
-rw-r--r--src/components/layout/Sidebar.tsx248
-rw-r--r--src/components/services/tabs/TabBarSortableList.tsx2
-rw-r--r--src/components/services/tabs/TabItem.tsx8
-rw-r--r--src/components/services/tabs/Tabbar.tsx2
-rw-r--r--src/components/settings/navigation/SettingsNavigation.tsx6
-rw-r--r--src/components/settings/supportFerdium/SupportFerdiumDashboard.tsx2
-rw-r--r--src/components/ui/AppLoader/index.tsx23
-rw-r--r--src/components/ui/Link.tsx4
-rw-r--r--src/components/ui/Select.tsx4
-rw-r--r--src/components/ui/Tabs/Tabs.tsx2
-rw-r--r--src/components/ui/WebviewLoader/index.tsx2
-rw-r--r--src/components/ui/colorPickerInput/index.tsx2
-rw-r--r--src/components/ui/headline/index.tsx11
-rw-r--r--src/components/ui/select/index.tsx6
-rw-r--r--src/containers/auth/WelcomeScreen.tsx4
-rw-r--r--src/containers/layout/AppLayoutContainer.tsx1
-rw-r--r--src/containers/settings/EditSettingsScreen.tsx2
-rw-r--r--src/containers/settings/EditUserScreen.tsx2
-rw-r--r--src/electron/macOSPermissions.ts1
-rw-r--r--src/environment.ts2
-rw-r--r--src/features/serviceProxy/index.ts6
-rw-r--r--src/features/workspaces/components/WorkspaceDrawer.tsx5
-rw-r--r--src/features/workspaces/components/WorkspaceDrawerItem.tsx1
-rw-r--r--src/features/workspaces/components/WorkspacesDashboard.tsx1
-rw-r--r--src/features/workspaces/store.ts1
-rw-r--r--src/helpers/recipe-helpers.ts1
-rw-r--r--src/index.ts2
-rw-r--r--src/internal-server/app/Controllers/Http/UserController.js14
-rw-r--r--src/internal-server/public/js/transfer.js1
-rw-r--r--src/lib/Form.ts1
-rw-r--r--src/lib/Menu.ts3
-rw-r--r--src/models/Recipe.ts8
-rw-r--r--src/routes.tsx18
-rw-r--r--src/stores/AppStore.ts2
-rw-r--r--src/stores/GlobalErrorStore.ts12
-rw-r--r--src/stores/RecipesStore.ts1
-rw-r--r--src/stores/ServicesStore.ts2
-rw-r--r--src/stores/SettingsStore.ts21
-rw-r--r--src/stores/UserStore.ts4
-rw-r--r--src/stores/lib/TypedStore.ts2
-rw-r--r--src/webview/contextMenuBuilder.ts7
-rw-r--r--src/webview/lib/Userscript.ts9
-rw-r--r--src/webview/recipe.ts17
52 files changed, 245 insertions, 248 deletions
diff --git a/src/@types/ferdium.types.ts b/src/@types/ferdium.types.ts
index 70306f5fb..f54fb64ae 100644
--- a/src/@types/ferdium.types.ts
+++ b/src/@types/ferdium.types.ts
@@ -3,6 +3,7 @@ declare global {
3 ferdium: any; 3 ferdium: any;
4 } 4 }
5 5
6 // eslint-disable-next-line @typescript-eslint/no-namespace
6 namespace NodeJS { 7 namespace NodeJS {
7 interface ProcessEnv { 8 interface ProcessEnv {
8 GITHUB_AUTH_TOKEN: string; 9 GITHUB_AUTH_TOKEN: string;
diff --git a/src/@types/stores.types.ts b/src/@types/stores.types.ts
index edea41ea9..ff8f127ed 100644
--- a/src/@types/stores.types.ts
+++ b/src/@types/stores.types.ts
@@ -59,6 +59,7 @@ interface Actions {
59interface Api { 59interface Api {
60 app: AppStore; 60 app: AppStore;
61 features: FeaturesStore; 61 features: FeaturesStore;
62 // eslint-disable-next-line @typescript-eslint/ban-types
62 local: {}; 63 local: {};
63 recipePreviews: RecipePreviewsStore; 64 recipePreviews: RecipePreviewsStore;
64 recipes: RecipeStore; 65 recipes: RecipeStore;
diff --git a/src/actions/lib/actions.ts b/src/actions/lib/actions.ts
index faf576fd8..d3fd5f27c 100644
--- a/src/actions/lib/actions.ts
+++ b/src/actions/lib/actions.ts
@@ -8,6 +8,7 @@ export interface Actions {
8 [key: string]: { 8 [key: string]: {
9 [key: string]: { 9 [key: string]: {
10 (...args: any[]): void; 10 (...args: any[]): void;
11 // eslint-disable-next-line @typescript-eslint/ban-types
11 listeners: Function[]; 12 listeners: Function[];
12 notify: (params: any) => void; 13 notify: (params: any) => void;
13 listen: (listener: (params: any) => void) => void; 14 listen: (listener: (params: any) => void) => void;
diff --git a/src/api/apiBase.ts b/src/api/apiBase.ts
index bc2cb3dd1..649895fbc 100644
--- a/src/api/apiBase.ts
+++ b/src/api/apiBase.ts
@@ -14,12 +14,7 @@ import { fixUrl } from '../helpers/url-helpers';
14 14
15// Note: This cannot be used from the internal-server since we are not running within the context of a browser window 15// Note: This cannot be used from the internal-server since we are not running within the context of a browser window
16export default function apiBase(withVersion = true) { 16export default function apiBase(withVersion = true) {
17 if ( 17 if (!(window as any).ferdium?.stores.settings?.all?.app.server) {
18 !(window as any).ferdium ||
19 !(window as any).ferdium.stores.settings ||
20 !(window as any).ferdium.stores.settings.all ||
21 !(window as any).ferdium.stores.settings.all.app.server
22 ) {
23 // Stores have not yet been loaded - return SERVER_NOT_LOADED to force a retry when stores are loaded 18 // Stores have not yet been loaded - return SERVER_NOT_LOADED to force a retry when stores are loaded
24 return SERVER_NOT_LOADED; 19 return SERVER_NOT_LOADED;
25 } 20 }
diff --git a/src/api/server/ServerApi.ts b/src/api/server/ServerApi.ts
index a3d873c65..860b7b76e 100644
--- a/src/api/server/ServerApi.ts
+++ b/src/api/server/ServerApi.ts
@@ -507,7 +507,7 @@ export default class ServerApi {
507 async _mapServiceModels(services: any[]) { 507 async _mapServiceModels(services: any[]) {
508 const recipes = services.map((s: { recipeId: string }) => s.recipeId); 508 const recipes = services.map((s: { recipeId: string }) => s.recipeId);
509 await this._bulkRecipeCheck(recipes); 509 await this._bulkRecipeCheck(recipes);
510 /* eslint-disable no-return-await */ 510
511 return Promise.all( 511 return Promise.all(
512 services.map(async (service: any) => this._prepareServiceModel(service)), 512 services.map(async (service: any) => this._prepareServiceModel(service)),
513 ); 513 );
diff --git a/src/app.tsx b/src/app.tsx
index 4d4100c40..77ec27021 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -24,7 +24,7 @@ window.addEventListener('load', () => {
24 const api = apiFactory(serverApi, new LocalApi()); 24 const api = apiFactory(serverApi, new LocalApi());
25 const history = createHashHistory(); 25 const history = createHashHistory();
26 const router = new RouterStore(history); 26 const router = new RouterStore(history);
27 // @ts-ignore - Need to provide proper typings for actions 27 // @ts-expect-error - Need to provide proper typings for actions
28 const stores = storeFactory(api, actions, router); 28 const stores = storeFactory(api, actions, router);
29 const menu = new MenuFactory(stores, actions); 29 const menu = new MenuFactory(stores, actions);
30 const touchBar = new TouchBarFactory(stores, actions); 30 const touchBar = new TouchBarFactory(stores, actions);
diff --git a/src/components/AppUpdateInfoBar.tsx b/src/components/AppUpdateInfoBar.tsx
index b27578d10..b8e1bb61e 100644
--- a/src/components/AppUpdateInfoBar.tsx
+++ b/src/components/AppUpdateInfoBar.tsx
@@ -38,6 +38,7 @@ const AppUpdateInfoBar = (props: IProps) => {
38 type="primary" 38 type="primary"
39 ctaLabel={intl.formatMessage(messages.buttonInstallUpdate)} 39 ctaLabel={intl.formatMessage(messages.buttonInstallUpdate)}
40 onClick={event => { 40 onClick={event => {
41 // eslint-disable-next-line @typescript-eslint/no-unused-expressions
41 !isWinPortable && onInstallUpdate(event); 42 !isWinPortable && onInstallUpdate(event);
42 }} 43 }}
43 onHide={onHide} 44 onHide={onHide}
diff --git a/src/components/auth/Login.tsx b/src/components/auth/Login.tsx
index 0a95b0565..eaa04256c 100644
--- a/src/components/auth/Login.tsx
+++ b/src/components/auth/Login.tsx
@@ -68,7 +68,6 @@ interface IProps extends WrappedComponentProps {
68 isTokenExpired: boolean; 68 isTokenExpired: boolean;
69 isServerLogout: boolean; 69 isServerLogout: boolean;
70 signupRoute: string; 70 signupRoute: string;
71 // eslint-disable-next-line react/no-unused-prop-types
72 passwordRoute: string; // TODO: Uncomment this line after fixing password recovery in-app 71 passwordRoute: string; // TODO: Uncomment this line after fixing password recovery in-app
73 error: GlobalError; 72 error: GlobalError;
74} 73}
diff --git a/src/components/auth/Welcome.tsx b/src/components/auth/Welcome.tsx
index 1aa8da4d6..047512ea4 100644
--- a/src/components/auth/Welcome.tsx
+++ b/src/components/auth/Welcome.tsx
@@ -44,10 +44,6 @@ interface IProps extends Partial<StoresProps>, WrappedComponentProps {
44@inject('actions') 44@inject('actions')
45@observer 45@observer
46class Welcome extends Component<IProps> { 46class Welcome extends Component<IProps> {
47 constructor(props: IProps) {
48 super(props);
49 }
50
51 useLocalServer(): void { 47 useLocalServer(): void {
52 serverlessLogin(this.props.actions); 48 serverlessLogin(this.props.actions);
53 } 49 }
diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx
index 2b1e87023..ceb9cfff9 100644
--- a/src/components/layout/Sidebar.tsx
+++ b/src/components/layout/Sidebar.tsx
@@ -205,133 +205,131 @@ class Sidebar extends Component<IProps, IState> {
205 hibernateService={this.props.hibernateService} 205 hibernateService={this.props.hibernateService}
206 wakeUpService={this.props.wakeUpService} 206 wakeUpService={this.props.wakeUpService}
207 /> 207 />
208 <> 208 {numberActiveButtons <= 1 || hideCollapseButton ? null : (
209 {numberActiveButtons <= 1 || hideCollapseButton ? null : ( 209 <button
210 <button 210 type="button"
211 type="button" 211 onClick={() => toggleCollapseMenu()}
212 onClick={() => toggleCollapseMenu()} 212 className="sidebar__button sidebar__button--hamburger-menu"
213 className="sidebar__button sidebar__button--hamburger-menu" 213 >
214 > 214 {isMenuCollapsed ? <Icon icon={mdiMenu} size={1.5} /> : null}
215 {isMenuCollapsed ? <Icon icon={mdiMenu} size={1.5} /> : null}
216 215
217 {!isMenuCollapsed && !useHorizontalStyle ? ( 216 {!isMenuCollapsed && !useHorizontalStyle ? (
218 <Icon icon={mdiChevronDown} size={1.5} /> 217 <Icon icon={mdiChevronDown} size={1.5} />
219 ) : null} 218 ) : null}
220 219
221 {!isMenuCollapsed && useHorizontalStyle ? ( 220 {!isMenuCollapsed && useHorizontalStyle ? (
222 <Icon icon={mdiChevronRight} size={1.5} /> 221 <Icon icon={mdiChevronRight} size={1.5} />
223 ) : null} 222 ) : null}
224 </button> 223 </button>
225 )} 224 )}
226 {!hideRecipesButton && !isMenuCollapsed ? ( 225 {!hideRecipesButton && !isMenuCollapsed ? (
227 <button 226 <button
228 type="button" 227 type="button"
229 onClick={() => openSettings({ path: 'recipes' })} 228 onClick={() => openSettings({ path: 'recipes' })}
230 className="sidebar__button sidebar__button--new-service" 229 className="sidebar__button sidebar__button--new-service"
231 data-tooltip-id="tooltip-sidebar-button" 230 data-tooltip-id="tooltip-sidebar-button"
232 data-tooltip-content={`${intl.formatMessage( 231 data-tooltip-content={`${intl.formatMessage(
233 messages.addNewService, 232 messages.addNewService,
234 )} (${addNewServiceShortcutKey(false)})`} 233 )} (${addNewServiceShortcutKey(false)})`}
235 > 234 >
236 <Icon icon={mdiPlusBox} size={1.5} /> 235 <Icon icon={mdiPlusBox} size={1.5} />
237 </button> 236 </button>
238 ) : null} 237 ) : null}
239 {!hideSplitModeButton && !isMenuCollapsed ? ( 238 {!hideSplitModeButton && !isMenuCollapsed ? (
240 <button 239 <button
241 type="button" 240 type="button"
242 onClick={() => { 241 onClick={() => {
243 actions!.settings.update({ 242 actions!.settings.update({
244 type: 'app', 243 type: 'app',
245 data: { 244 data: {
246 splitMode: !splitMode, 245 splitMode: !splitMode,
247 }, 246 },
248 }); 247 });
249 }} 248 }}
250 className="sidebar__button sidebar__button--split-mode-toggle" 249 className="sidebar__button sidebar__button--split-mode-toggle"
251 data-tooltip-id="tooltip-sidebar-button" 250 data-tooltip-id="tooltip-sidebar-button"
252 data-tooltip-content={`${intl.formatMessage( 251 data-tooltip-content={`${intl.formatMessage(
253 messages.splitModeToggle, 252 messages.splitModeToggle,
254 )} (${splitModeToggleShortcutKey(false)})`} 253 )} (${splitModeToggleShortcutKey(false)})`}
255 > 254 >
256 <Icon icon={mdiViewSplitVertical} size={1.5} /> 255 <Icon icon={mdiViewSplitVertical} size={1.5} />
257 </button> 256 </button>
258 ) : null} 257 ) : null}
259 {!hideWorkspacesButton && !isMenuCollapsed ? ( 258 {!hideWorkspacesButton && !isMenuCollapsed ? (
260 <button 259 <button
261 type="button" 260 type="button"
262 onClick={() => { 261 onClick={() => {
263 toggleWorkspaceDrawer(); 262 toggleWorkspaceDrawer();
264 this.updateToolTip(); 263 this.updateToolTip();
265 }} 264 }}
266 className={`sidebar__button sidebar__button--workspaces ${ 265 className={`sidebar__button sidebar__button--workspaces ${
267 isWorkspaceDrawerOpen ? 'is-active' : '' 266 isWorkspaceDrawerOpen ? 'is-active' : ''
268 }`} 267 }`}
269 data-tooltip-id="tooltip-sidebar-button" 268 data-tooltip-id="tooltip-sidebar-button"
270 data-tooltip-content={`${intl.formatMessage( 269 data-tooltip-content={`${intl.formatMessage(
271 workspaceToggleMessage, 270 workspaceToggleMessage,
272 )} (${workspaceToggleShortcutKey(false)})`} 271 )} (${workspaceToggleShortcutKey(false)})`}
273 > 272 >
274 <Icon icon={mdiViewGrid} size={1.5} /> 273 <Icon icon={mdiViewGrid} size={1.5} />
275 </button> 274 </button>
276 ) : null} 275 ) : null}
277 {!hideNotificationsButton && !isMenuCollapsed ? ( 276 {!hideNotificationsButton && !isMenuCollapsed ? (
278 <button 277 <button
279 type="button" 278 type="button"
280 onClick={() => { 279 onClick={() => {
281 toggleMuteApp(); 280 toggleMuteApp();
282 this.updateToolTip(); 281 this.updateToolTip();
283 }} 282 }}
284 className={`sidebar__button sidebar__button--audio ${ 283 className={`sidebar__button sidebar__button--audio ${
285 isAppMuted ? 'is-muted' : '' 284 isAppMuted ? 'is-muted' : ''
286 }`} 285 }`}
287 data-tooltip-id="tooltip-sidebar-button" 286 data-tooltip-id="tooltip-sidebar-button"
288 data-tooltip-content={`${intl.formatMessage( 287 data-tooltip-content={`${intl.formatMessage(
289 isAppMuted ? messages.unmute : messages.mute, 288 isAppMuted ? messages.unmute : messages.mute,
290 )} (${muteFerdiumShortcutKey(false)})`} 289 )} (${muteFerdiumShortcutKey(false)})`}
291 > 290 >
292 <Icon icon={isAppMuted ? mdiBellOff : mdiBell} size={1.5} /> 291 <Icon icon={isAppMuted ? mdiBellOff : mdiBell} size={1.5} />
293 </button> 292 </button>
294 ) : null} 293 ) : null}
295 {todosStore.isFeatureEnabledByUser && !isMenuCollapsed ? ( 294 {todosStore.isFeatureEnabledByUser && !isMenuCollapsed ? (
296 <button 295 <button
297 type="button" 296 type="button"
298 onClick={() => { 297 onClick={() => {
299 todoActions.toggleTodosPanel(); 298 todoActions.toggleTodosPanel();
300 this.updateToolTip(); 299 this.updateToolTip();
301 }} 300 }}
302 disabled={isTodosServiceActive} 301 disabled={isTodosServiceActive}
303 className={`sidebar__button sidebar__button--todos ${ 302 className={`sidebar__button sidebar__button--todos ${
304 todosStore.isTodosPanelVisible ? 'is-active' : '' 303 todosStore.isTodosPanelVisible ? 'is-active' : ''
305 }`} 304 }`}
306 data-tooltip-id="tooltip-sidebar-button" 305 data-tooltip-id="tooltip-sidebar-button"
307 data-tooltip-content={`${intl.formatMessage( 306 data-tooltip-content={`${intl.formatMessage(
308 todosToggleMessage, 307 todosToggleMessage,
309 )} (${todosToggleShortcutKey(false)})`} 308 )} (${todosToggleShortcutKey(false)})`}
310 > 309 >
311 <Icon icon={mdiCheckAll} size={1.5} /> 310 <Icon icon={mdiCheckAll} size={1.5} />
312 </button> 311 </button>
313 ) : null} 312 ) : null}
314 {stores!.settings.all.app.lockingFeatureEnabled ? ( 313 {stores!.settings.all.app.lockingFeatureEnabled ? (
315 <button 314 <button
316 type="button" 315 type="button"
317 className="sidebar__button" 316 className="sidebar__button"
318 onClick={() => { 317 onClick={() => {
319 actions!.settings.update({ 318 actions!.settings.update({
320 type: 'app', 319 type: 'app',
321 data: { 320 data: {
322 locked: true, 321 locked: true,
323 }, 322 },
324 }); 323 });
325 }} 324 }}
326 data-tooltip-id="tooltip-sidebar-button" 325 data-tooltip-id="tooltip-sidebar-button"
327 data-tooltip-content={`${intl.formatMessage( 326 data-tooltip-content={`${intl.formatMessage(
328 messages.lockFerdium, 327 messages.lockFerdium,
329 )} (${lockFerdiumShortcutKey(false)})`} 328 )} (${lockFerdiumShortcutKey(false)})`}
330 > 329 >
331 <Icon icon={mdiLock} size={1.5} /> 330 <Icon icon={mdiLock} size={1.5} />
332 </button> 331 </button>
333 ) : null} 332 ) : null}
334 </>
335 {this.state.tooltipEnabled && ( 333 {this.state.tooltipEnabled && (
336 <ReactTooltip 334 <ReactTooltip
337 id="tooltip-sidebar-button" 335 id="tooltip-sidebar-button"
diff --git a/src/components/services/tabs/TabBarSortableList.tsx b/src/components/services/tabs/TabBarSortableList.tsx
index 5f711c30d..a30587470 100644
--- a/src/components/services/tabs/TabBarSortableList.tsx
+++ b/src/components/services/tabs/TabBarSortableList.tsx
@@ -51,7 +51,7 @@ class TabBarSortableList extends Component<IProps> {
51 {services.map((service, index) => ( 51 {services.map((service, index) => (
52 <TabItem 52 <TabItem
53 key={service.id} 53 key={service.id}
54 // @ts-ignore 54 // @ts-expect-error Fix me
55 clickHandler={() => setActive({ serviceId: service.id })} 55 clickHandler={() => setActive({ serviceId: service.id })}
56 service={service} 56 service={service}
57 index={index} 57 index={index}
diff --git a/src/components/services/tabs/TabItem.tsx b/src/components/services/tabs/TabItem.tsx
index c25af4427..287dedfcb 100644
--- a/src/components/services/tabs/TabItem.tsx
+++ b/src/components/services/tabs/TabItem.tsx
@@ -234,7 +234,7 @@ class TabItem extends Component<IProps, IState> {
234 } = this.props; 234 } = this.props;
235 const { intl } = this.props; 235 const { intl } = this.props;
236 236
237 const menuTemplate: Array<MenuItemConstructorOptions> = [ 237 const menuTemplate: MenuItemConstructorOptions[] = [
238 { 238 {
239 label: service.name || service.recipe.name, 239 label: service.name || service.recipe.name,
240 enabled: false, 240 enabled: false,
@@ -295,7 +295,7 @@ class TabItem extends Component<IProps, IState> {
295 ? messages.wakeUpService 295 ? messages.wakeUpService
296 : messages.hibernateService, 296 : messages.hibernateService,
297 ), 297 ),
298 // eslint-disable-next-line no-confusing-arrow 298
299 click: () => 299 click: () =>
300 service.isHibernating ? wakeUpService() : hibernateService(), 300 service.isHibernating ? wakeUpService() : hibernateService(),
301 enabled: service.isEnabled && service.canHibernate, 301 enabled: service.isEnabled && service.canHibernate,
@@ -311,7 +311,7 @@ class TabItem extends Component<IProps, IState> {
311 { 311 {
312 label: intl.formatMessage(messages.deleteService), 312 label: intl.formatMessage(messages.deleteService),
313 click: () => { 313 click: () => {
314 // @ts-ignore 314 // @ts-expect-error Fix me
315 const selection = dialog.showMessageBoxSync(app.mainWindow, { 315 const selection = dialog.showMessageBoxSync(app.mainWindow, {
316 type: 'question', 316 type: 'question',
317 message: intl.formatMessage(messages.deleteService), 317 message: intl.formatMessage(messages.deleteService),
@@ -417,6 +417,6 @@ class TabItem extends Component<IProps, IState> {
417} 417}
418 418
419export default injectIntl( 419export default injectIntl(
420 // @ts-ignore 420 // @ts-expect-error Fix me
421 SortableElement(injectSheet(styles, { injectTheme: true })(TabItem)), 421 SortableElement(injectSheet(styles, { injectTheme: true })(TabItem)),
422); 422);
diff --git a/src/components/services/tabs/Tabbar.tsx b/src/components/services/tabs/Tabbar.tsx
index f09877b2f..d19a4b8de 100644
--- a/src/components/services/tabs/Tabbar.tsx
+++ b/src/components/services/tabs/Tabbar.tsx
@@ -99,7 +99,7 @@ class TabBar extends Component<IProps> {
99 return ( 99 return (
100 <div> 100 <div>
101 <TabBarSortableList 101 <TabBarSortableList
102 // @ts-ignore 102 // @ts-expect-error Fix me
103 services={services} 103 services={services}
104 setActive={setActive} 104 setActive={setActive}
105 onSortEnd={this.onSortEnd} 105 onSortEnd={this.onSortEnd}
diff --git a/src/components/settings/navigation/SettingsNavigation.tsx b/src/components/settings/navigation/SettingsNavigation.tsx
index 6ffaa411f..66763c6a6 100644
--- a/src/components/settings/navigation/SettingsNavigation.tsx
+++ b/src/components/settings/navigation/SettingsNavigation.tsx
@@ -53,10 +53,6 @@ interface IProps extends Partial<StoresProps>, WrappedComponentProps {
53@inject('stores', 'actions') 53@inject('stores', 'actions')
54@observer 54@observer
55class SettingsNavigation extends Component<IProps> { 55class SettingsNavigation extends Component<IProps> {
56 constructor(props: IProps) {
57 super(props);
58 }
59
60 handleLogout(): void { 56 handleLogout(): void {
61 const isUsingWithoutAccount = 57 const isUsingWithoutAccount =
62 this.props.stores!.settings.app.server === LOCAL_SERVER; 58 this.props.stores!.settings.app.server === LOCAL_SERVER;
@@ -186,7 +182,7 @@ class SettingsNavigation extends Component<IProps> {
186 <span className="settings-navigation__expander" /> 182 <span className="settings-navigation__expander" />
187 <button 183 <button
188 type="button" 184 type="button"
189 // @ts-ignore 185 // @ts-expect-error Fix me
190 to="/auth/logout" // TODO: [TS DEBT] Need to check if button take this prop 186 to="/auth/logout" // TODO: [TS DEBT] Need to check if button take this prop
191 className="settings-navigation__link" 187 className="settings-navigation__link"
192 onClick={this.handleLogout.bind(this)} 188 onClick={this.handleLogout.bind(this)}
diff --git a/src/components/settings/supportFerdium/SupportFerdiumDashboard.tsx b/src/components/settings/supportFerdium/SupportFerdiumDashboard.tsx
index f3b7c718c..065690fb5 100644
--- a/src/components/settings/supportFerdium/SupportFerdiumDashboard.tsx
+++ b/src/components/settings/supportFerdium/SupportFerdiumDashboard.tsx
@@ -50,7 +50,7 @@ const SupportFerdiumDashboard = () => {
50 src="https://img.shields.io/github/stars/ferdium/ferdium-app?style=social" 50 src="https://img.shields.io/github/stars/ferdium/ferdium-app?style=social"
51 /> 51 />
52 </a> 52 </a>
53 <a target="_blank" href={FERDIUM_TRANSLATION}> 53 <a target="_blank" href={FERDIUM_TRANSLATION} rel="noreferrer">
54 <img 54 <img
55 src="https://badges.crowdin.net/ferdium-app/localized.svg" 55 src="https://badges.crowdin.net/ferdium-app/localized.svg"
56 alt="Crowdin" 56 alt="Crowdin"
diff --git a/src/components/ui/AppLoader/index.tsx b/src/components/ui/AppLoader/index.tsx
index f4d9b8e73..64c840aaa 100644
--- a/src/components/ui/AppLoader/index.tsx
+++ b/src/components/ui/AppLoader/index.tsx
@@ -61,18 +61,17 @@ class AppLoader extends Component<IProps, IState> {
61 className={classes.component} 61 className={classes.component}
62 spinnerColor={theme.colorAppLoaderSpinner} 62 spinnerColor={theme.colorAppLoaderSpinner}
63 > 63 >
64 {texts && 64 {texts?.map((text, i) => (
65 texts.map((text, i) => ( 65 <span
66 <span 66 key={text}
67 key={text} 67 className={classnames({
68 className={classnames({ 68 [`${classes.slogan}`]: true,
69 [`${classes.slogan}`]: true, 69 [`${classes.visible}`]: step === i,
70 [`${classes.visible}`]: step === i, 70 })}
71 })} 71 >
72 > 72 {text}
73 {text} 73 </span>
74 </span> 74 ))}
75 ))}
76 </FullscreenLoader> 75 </FullscreenLoader>
77 ); 76 );
78 } 77 }
diff --git a/src/components/ui/Link.tsx b/src/components/ui/Link.tsx
index b5890ebd1..a9a429d3a 100644
--- a/src/components/ui/Link.tsx
+++ b/src/components/ui/Link.tsx
@@ -20,10 +20,6 @@ interface IProps extends Partial<StoresProps> {
20@inject('stores') 20@inject('stores')
21@observer 21@observer
22class Link extends Component<IProps> { 22class Link extends Component<IProps> {
23 constructor(props: IProps) {
24 super(props);
25 }
26
27 onClick(e: MouseEvent<HTMLAnchorElement>): void { 23 onClick(e: MouseEvent<HTMLAnchorElement>): void {
28 const { disabled = false, target = '', to } = this.props; 24 const { disabled = false, target = '', to } = this.props;
29 if (disabled) { 25 if (disabled) {
diff --git a/src/components/ui/Select.tsx b/src/components/ui/Select.tsx
index 8ae2945ce..a2ed4216f 100644
--- a/src/components/ui/Select.tsx
+++ b/src/components/ui/Select.tsx
@@ -24,10 +24,6 @@ class Select extends Component<IProps> {
24 private element: RefObject<HTMLSelectElement> = 24 private element: RefObject<HTMLSelectElement> =
25 createRef<HTMLSelectElement>(); 25 createRef<HTMLSelectElement>();
26 26
27 constructor(props: IProps) {
28 super(props);
29 }
30
31 multipleChange(e: ChangeEvent<HTMLSelectElement>): void { 27 multipleChange(e: ChangeEvent<HTMLSelectElement>): void {
32 e.preventDefault(); 28 e.preventDefault();
33 if (!this.element.current) { 29 if (!this.element.current) {
diff --git a/src/components/ui/Tabs/Tabs.tsx b/src/components/ui/Tabs/Tabs.tsx
index 2c34d7e24..d7f75c8b8 100644
--- a/src/components/ui/Tabs/Tabs.tsx
+++ b/src/components/ui/Tabs/Tabs.tsx
@@ -41,6 +41,7 @@ class Tab extends Component<IProps, IState> {
41 <div className="content-tabs__tabs"> 41 <div className="content-tabs__tabs">
42 {Children.map(children, (child, i) => ( 42 {Children.map(children, (child, i) => (
43 <button 43 <button
44 // eslint-disable-next-line react/no-array-index-key
44 key={i} 45 key={i}
45 className={classnames({ 46 className={classnames({
46 'content-tabs__item': true, 47 'content-tabs__item': true,
@@ -56,6 +57,7 @@ class Tab extends Component<IProps, IState> {
56 <div className="content-tabs__content"> 57 <div className="content-tabs__content">
57 {Children.map(children, (child, i) => ( 58 {Children.map(children, (child, i) => (
58 <div 59 <div
60 // eslint-disable-next-line react/no-array-index-key
59 key={i} 61 key={i}
60 className={classnames({ 62 className={classnames({
61 'content-tabs__item': true, 63 'content-tabs__item': true,
diff --git a/src/components/ui/WebviewLoader/index.tsx b/src/components/ui/WebviewLoader/index.tsx
index 81923b6ca..c4e9c724c 100644
--- a/src/components/ui/WebviewLoader/index.tsx
+++ b/src/components/ui/WebviewLoader/index.tsx
@@ -32,7 +32,7 @@ class WebviewLoader extends Component<IProps> {
32 return ( 32 return (
33 <FullscreenLoader 33 <FullscreenLoader
34 className={classes.component} 34 className={classes.component}
35 title={`${intl.formatMessage(messages.loading, { service: name })}`} 35 title={intl.formatMessage(messages.loading, { service: name })}
36 loaded={loaded} 36 loaded={loaded}
37 /> 37 />
38 ); 38 );
diff --git a/src/components/ui/colorPickerInput/index.tsx b/src/components/ui/colorPickerInput/index.tsx
index 9bab6efec..2367175bd 100644
--- a/src/components/ui/colorPickerInput/index.tsx
+++ b/src/components/ui/colorPickerInput/index.tsx
@@ -25,7 +25,7 @@ class ColorPickerInput extends Component<IProps> {
25 25
26 componentDidMount(): void { 26 componentDidMount(): void {
27 const { focus = false } = this.props; 27 const { focus = false } = this.props;
28 if (focus && this.inputElement && this.inputElement.current) { 28 if (focus && this.inputElement?.current) {
29 this.inputElement.current.focus(); 29 this.inputElement.current.focus();
30 } 30 }
31 } 31 }
diff --git a/src/components/ui/headline/index.tsx b/src/components/ui/headline/index.tsx
index bebd8adcf..424190a6a 100644
--- a/src/components/ui/headline/index.tsx
+++ b/src/components/ui/headline/index.tsx
@@ -67,12 +67,11 @@ class HeadlineComponent extends Component<IProps> {
67} 67}
68 68
69const Headline = injectStyle(styles, { injectTheme: true })(HeadlineComponent); 69const Headline = injectStyle(styles, { injectTheme: true })(HeadlineComponent);
70const createH = (level: number) => (props: Omit<IProps, 'classes'>) => 70const createH = (level: number) => (props: Omit<IProps, 'classes'>) => (
71 ( 71 <Headline level={level} {...props}>
72 <Headline level={level} {...props}> 72 {props.children}
73 {props.children} 73 </Headline>
74 </Headline> 74);
75 );
76 75
77export const H1 = createH(1); 76export const H1 = createH(1);
78export const H2 = createH(2); 77export const H2 = createH(2);
diff --git a/src/components/ui/select/index.tsx b/src/components/ui/select/index.tsx
index 017de5423..902eb7748 100644
--- a/src/components/ui/select/index.tsx
+++ b/src/components/ui/select/index.tsx
@@ -301,11 +301,7 @@ class SelectComponent extends Component<IProps, IState> {
301 this.select(Object.keys(options!)[selected]); 301 this.select(Object.keys(options!)[selected]);
302 } 302 }
303 303
304 if ( 304 if (this.activeOptionRef?.current && this.scrollContainerRef?.current) {
305 this.activeOptionRef?.current &&
306 this.scrollContainerRef &&
307 this.scrollContainerRef.current
308 ) {
309 const containerTopOffset = this.scrollContainerRef.current.offsetTop; 305 const containerTopOffset = this.scrollContainerRef.current.offsetTop;
310 const optionTopOffset = this.activeOptionRef.current.offsetTop; 306 const optionTopOffset = this.activeOptionRef.current.offsetTop;
311 307
diff --git a/src/containers/auth/WelcomeScreen.tsx b/src/containers/auth/WelcomeScreen.tsx
index 561eef236..1f3f50e4a 100644
--- a/src/containers/auth/WelcomeScreen.tsx
+++ b/src/containers/auth/WelcomeScreen.tsx
@@ -8,10 +8,6 @@ interface IProps extends Partial<StoresProps> {}
8@inject('stores', 'actions') 8@inject('stores', 'actions')
9@observer 9@observer
10class WelcomeScreen extends Component<IProps> { 10class WelcomeScreen extends Component<IProps> {
11 constructor(props: IProps) {
12 super(props);
13 }
14
15 render(): ReactElement { 11 render(): ReactElement {
16 const { user, recipePreviews } = this.props.stores!; 12 const { user, recipePreviews } = this.props.stores!;
17 13
diff --git a/src/containers/layout/AppLayoutContainer.tsx b/src/containers/layout/AppLayoutContainer.tsx
index 1929492ff..e30c0e067 100644
--- a/src/containers/layout/AppLayoutContainer.tsx
+++ b/src/containers/layout/AppLayoutContainer.tsx
@@ -74,7 +74,6 @@ class AppLayoutContainer extends Component<IProps> {
74 74
75 const workspacesDrawer = ( 75 const workspacesDrawer = (
76 <WorkspaceDrawer 76 <WorkspaceDrawer
77 // eslint-disable-next-line no-confusing-arrow
78 getServicesForWorkspace={workspace => 77 getServicesForWorkspace={workspace =>
79 workspace 78 workspace
80 ? workspaceStore.getWorkspaceServices(workspace).map(s => s.name) 79 ? workspaceStore.getWorkspaceServices(workspace).map(s => s.name)
diff --git a/src/containers/settings/EditSettingsScreen.tsx b/src/containers/settings/EditSettingsScreen.tsx
index 0f3359bfc..7cdff7fde 100644
--- a/src/containers/settings/EditSettingsScreen.tsx
+++ b/src/containers/settings/EditSettingsScreen.tsx
@@ -1172,8 +1172,6 @@ class EditSettingsScreen extends Component<EditSettingsScreenProps> {
1172 }; 1172 };
1173 } 1173 }
1174 1174
1175 // @ts-ignore: Remove this ignore once mobx-react-form v4 with typescript
1176 // support has been released.
1177 return new Form(config); 1175 return new Form(config);
1178 } 1176 }
1179 1177
diff --git a/src/containers/settings/EditUserScreen.tsx b/src/containers/settings/EditUserScreen.tsx
index 0d6c47da5..10c308524 100644
--- a/src/containers/settings/EditUserScreen.tsx
+++ b/src/containers/settings/EditUserScreen.tsx
@@ -126,8 +126,6 @@ class EditUserScreen extends Component<EditUserScreenProps> {
126 }, 126 },
127 }; 127 };
128 128
129 // @ts-ignore: Remove this ignore once mobx-react-form v4 with typescript
130 // support has been released.
131 return new Form(config); 129 return new Form(config);
132 } 130 }
133 131
diff --git a/src/electron/macOSPermissions.ts b/src/electron/macOSPermissions.ts
index c9f22aecb..88706dd23 100644
--- a/src/electron/macOSPermissions.ts
+++ b/src/electron/macOSPermissions.ts
@@ -2,6 +2,7 @@ import { systemPreferences, BrowserWindow, dialog } from 'electron';
2import { pathExistsSync, mkdirSync, writeFileSync } from 'fs-extra'; 2import { pathExistsSync, mkdirSync, writeFileSync } from 'fs-extra';
3import macosVersion from 'macos-version'; 3import macosVersion from 'macos-version';
4import { dirname } from 'path'; 4import { dirname } from 'path';
5// eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error
5// @ts-ignore 6// @ts-ignore
6import { askForScreenCaptureAccess } from 'node-mac-permissions'; 7import { askForScreenCaptureAccess } from 'node-mac-permissions';
7import { userDataPath } from '../environment-remote'; 8import { userDataPath } from '../environment-remote';
diff --git a/src/environment.ts b/src/environment.ts
index 0ba7774cd..e17be0b7f 100644
--- a/src/environment.ts
+++ b/src/environment.ts
@@ -43,4 +43,4 @@ export const splitModeToggleShortcutKey = (isAccelerator = true) =>
43export const settingsShortcutKey = (isAccelerator = true) => 43export const settingsShortcutKey = (isAccelerator = true) =>
44 `${cmdOrCtrlShortcutKey(isAccelerator)}+${isMac ? ',' : 'P'}`; 44 `${cmdOrCtrlShortcutKey(isAccelerator)}+${isMac ? ',' : 'P'}`;
45export const toggleFullScreenKey = () => 45export const toggleFullScreenKey = () =>
46 isMac ? `CTRL + ${cmdKey} + F` : `F11`; 46 isMac ? `CTRL + ${cmdKey} + F` : 'F11';
diff --git a/src/features/serviceProxy/index.ts b/src/features/serviceProxy/index.ts
index eb3b89ece..c98ae00a7 100644
--- a/src/features/serviceProxy/index.ts
+++ b/src/features/serviceProxy/index.ts
@@ -33,11 +33,7 @@ export default function init(stores: {
33 if (config.isEnabled) { 33 if (config.isEnabled) {
34 const serviceProxyConfig = proxySettings[service.id]; 34 const serviceProxyConfig = proxySettings[service.id];
35 35
36 if ( 36 if (serviceProxyConfig?.isEnabled && serviceProxyConfig.host) {
37 serviceProxyConfig &&
38 serviceProxyConfig.isEnabled &&
39 serviceProxyConfig.host
40 ) {
41 const proxyHost = `${serviceProxyConfig.host}${ 37 const proxyHost = `${serviceProxyConfig.host}${
42 serviceProxyConfig.port ? `:${serviceProxyConfig.port}` : '' 38 serviceProxyConfig.port ? `:${serviceProxyConfig.port}` : ''
43 }`; 39 }`;
diff --git a/src/features/workspaces/components/WorkspaceDrawer.tsx b/src/features/workspaces/components/WorkspaceDrawer.tsx
index 1c827e9dd..3e05cb7de 100644
--- a/src/features/workspaces/components/WorkspaceDrawer.tsx
+++ b/src/features/workspaces/components/WorkspaceDrawer.tsx
@@ -98,6 +98,7 @@ class WorkspaceDrawer extends Component<IProps> {
98 try { 98 try {
99 getUserWorkspacesRequest.execute(); 99 getUserWorkspacesRequest.execute();
100 } catch (error) { 100 } catch (error) {
101 // eslint-disable-next-line no-console
101 console.log(error); 102 console.log(error);
102 } 103 }
103 } 104 }
@@ -121,9 +122,9 @@ class WorkspaceDrawer extends Component<IProps> {
121 workspaceActions.openWorkspaceSettings(); 122 workspaceActions.openWorkspaceSettings();
122 }} 123 }}
123 data-tooltip-id="tooltip-workspaces-drawer" 124 data-tooltip-id="tooltip-workspaces-drawer"
124 data-tooltip-content={`${intl.formatMessage( 125 data-tooltip-content={intl.formatMessage(
125 messages.workspacesSettingsTooltip, 126 messages.workspacesSettingsTooltip,
126 )}`} 127 )}
127 > 128 >
128 <Icon 129 <Icon
129 icon={mdiCog} 130 icon={mdiCog}
diff --git a/src/features/workspaces/components/WorkspaceDrawerItem.tsx b/src/features/workspaces/components/WorkspaceDrawerItem.tsx
index 172b4192c..4fd7662f5 100644
--- a/src/features/workspaces/components/WorkspaceDrawerItem.tsx
+++ b/src/features/workspaces/components/WorkspaceDrawerItem.tsx
@@ -72,6 +72,7 @@ interface IProps extends WithStylesProps<typeof styles>, WrappedComponentProps {
72 name: string; 72 name: string;
73 onClick: MouseEventHandler<HTMLInputElement>; 73 onClick: MouseEventHandler<HTMLInputElement>;
74 services: string[]; 74 services: string[];
75 // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
75 onContextMenuEditClick?: () => void | null; 76 onContextMenuEditClick?: () => void | null;
76 shortcutIndex: number; 77 shortcutIndex: number;
77} 78}
diff --git a/src/features/workspaces/components/WorkspacesDashboard.tsx b/src/features/workspaces/components/WorkspacesDashboard.tsx
index c5f8909c1..a823132c5 100644
--- a/src/features/workspaces/components/WorkspacesDashboard.tsx
+++ b/src/features/workspaces/components/WorkspacesDashboard.tsx
@@ -1,4 +1,3 @@
1/* eslint-disable react/jsx-no-useless-fragment */
2import { Component, ReactElement } from 'react'; 1import { Component, ReactElement } from 'react';
3import { observer } from 'mobx-react'; 2import { observer } from 'mobx-react';
4import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; 3import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
diff --git a/src/features/workspaces/store.ts b/src/features/workspaces/store.ts
index 53e3b62ed..34a4126c8 100644
--- a/src/features/workspaces/store.ts
+++ b/src/features/workspaces/store.ts
@@ -64,6 +64,7 @@ export default class WorkspacesStore extends FeatureStore {
64 return getUserWorkspacesRequest.wasExecuted && this.workspaces.length > 0; 64 return getUserWorkspacesRequest.wasExecuted && this.workspaces.length > 0;
65 } 65 }
66 66
67 // eslint-disable-next-line @typescript-eslint/class-literal-property-style
67 @computed get isUserAllowedToUseFeature() { 68 @computed get isUserAllowedToUseFeature() {
68 return true; 69 return true;
69 } 70 }
diff --git a/src/helpers/recipe-helpers.ts b/src/helpers/recipe-helpers.ts
index 93c107cc5..68a1578e3 100644
--- a/src/helpers/recipe-helpers.ts
+++ b/src/helpers/recipe-helpers.ts
@@ -15,6 +15,7 @@ export function loadRecipeConfig(recipeId: string) {
15 try { 15 try {
16 const configPath = `${recipeId}/package.json`; 16 const configPath = `${recipeId}/package.json`;
17 // Delete module from cache 17 // Delete module from cache
18 // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
18 delete require.cache[require.resolve(configPath)]; 19 delete require.cache[require.resolve(configPath)];
19 20
20 // eslint-disable-next-line import/no-dynamic-require 21 // eslint-disable-next-line import/no-dynamic-require
diff --git a/src/index.ts b/src/index.ts
index 7ef23415b..0487d692c 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -60,6 +60,7 @@ let mainWindow: BrowserWindow | undefined;
60let willQuitApp = false; 60let willQuitApp = false;
61let overrideAppQuitForUpdate = false; 61let overrideAppQuitForUpdate = false;
62 62
63// eslint-disable-next-line unicorn/prefer-event-target
63export const appEvents = new EventEmitter(); 64export const appEvents = new EventEmitter();
64 65
65// Register methods to be called once the window has been loaded. 66// Register methods to be called once the window has been loaded.
@@ -673,6 +674,7 @@ ipcMain.handle('get-desktop-capturer-sources', () =>
673); 674);
674 675
675ipcMain.on('window.toolbar-double-clicked', () => { 676ipcMain.on('window.toolbar-double-clicked', () => {
677 // eslint-disable-next-line @typescript-eslint/no-unused-expressions
676 mainWindow?.isMaximized() ? mainWindow.unmaximize() : mainWindow?.maximize(); 678 mainWindow?.isMaximized() ? mainWindow.unmaximize() : mainWindow?.maximize();
677}); 679});
678 680
diff --git a/src/internal-server/app/Controllers/Http/UserController.js b/src/internal-server/app/Controllers/Http/UserController.js
index 9a9d76636..a9c67a1b2 100644
--- a/src/internal-server/app/Controllers/Http/UserController.js
+++ b/src/internal-server/app/Controllers/Http/UserController.js
@@ -26,6 +26,7 @@ const apiRequest = (url, route, method, auth) =>
26 .then(data => data.json()) 26 .then(data => data.json())
27 .then(json => resolve(json)); 27 .then(json => resolve(json));
28 } catch (error) { 28 } catch (error) {
29 // eslint-disable-next-line no-console
29 console.log(error); 30 console.log(error);
30 reject(); 31 reject();
31 } 32 }
@@ -197,7 +198,7 @@ class UserController {
197 const services = await apiRequest(server, 'me/services', 'GET', token); 198 const services = await apiRequest(server, 'me/services', 'GET', token);
198 199
199 for (const service of services) { 200 for (const service of services) {
200 await this._createAndCacheService(service, serviceIdTranslation); // eslint-disable-line no-await-in-loop 201 await this._createAndCacheService(service, serviceIdTranslation);
201 } 202 }
202 } catch (error) { 203 } catch (error) {
203 const errorMessage = `Could not import your services into our system.\nError: ${error}`; 204 const errorMessage = `Could not import your services into our system.\nError: ${error}`;
@@ -209,7 +210,7 @@ class UserController {
209 const workspaces = await apiRequest(server, 'workspace', 'GET', token); 210 const workspaces = await apiRequest(server, 'workspace', 'GET', token);
210 211
211 for (const workspace of workspaces) { 212 for (const workspace of workspaces) {
212 await this._createWorkspace(workspace, serviceIdTranslation); // eslint-disable-line no-await-in-loop 213 await this._createWorkspace(workspace, serviceIdTranslation);
213 } 214 }
214 } catch (error) { 215 } catch (error) {
215 const errorMessage = `Could not import your workspaces into our system.\nError: ${error}`; 216 const errorMessage = `Could not import your workspaces into our system.\nError: ${error}`;
@@ -257,6 +258,7 @@ class UserController {
257 try { 258 try {
258 file = JSON.parse(request.input('file')); 259 file = JSON.parse(request.input('file'));
259 } catch (error) { 260 } catch (error) {
261 // eslint-disable-next-line no-console
260 console.log(error); 262 console.log(error);
261 return response.send( 263 return response.send(
262 'Could not import: Invalid file, could not read file', 264 'Could not import: Invalid file, could not read file',
@@ -272,7 +274,7 @@ class UserController {
272 // Import services 274 // Import services
273 try { 275 try {
274 for (const service of file.services) { 276 for (const service of file.services) {
275 await this._createAndCacheService(service, serviceIdTranslation); // eslint-disable-line no-await-in-loop 277 await this._createAndCacheService(service, serviceIdTranslation);
276 } 278 }
277 } catch (error) { 279 } catch (error) {
278 const errorMessage = `Could not import your services into our system.\nError: ${error}`; 280 const errorMessage = `Could not import your services into our system.\nError: ${error}`;
@@ -282,7 +284,7 @@ class UserController {
282 // Import workspaces 284 // Import workspaces
283 try { 285 try {
284 for (const workspace of file.workspaces) { 286 for (const workspace of file.workspaces) {
285 await this._createWorkspace(workspace, serviceIdTranslation); // eslint-disable-line no-await-in-loop 287 await this._createWorkspace(workspace, serviceIdTranslation);
286 } 288 }
287 } catch (error) { 289 } catch (error) {
288 const errorMessage = `Could not import your workspaces into our system.\nError: ${error}`; 290 const errorMessage = `Could not import your workspaces into our system.\nError: ${error}`;
@@ -302,6 +304,7 @@ class UserController {
302 ); 304 );
303 305
304 if (workspace.services) { 306 if (workspace.services) {
307 // eslint-disable-next-line no-param-reassign
305 workspace.services = convertToJSON(workspace.services); 308 workspace.services = convertToJSON(workspace.services);
306 } 309 }
307 const services = 310 const services =
@@ -311,6 +314,7 @@ class UserController {
311 ) 314 )
312 : []; 315 : [];
313 if (workspace.data) { 316 if (workspace.data) {
317 // eslint-disable-next-line no-param-reassign
314 workspace.data = convertToJSON(workspace.data); 318 workspace.data = convertToJSON(workspace.data);
315 } 319 }
316 320
@@ -334,9 +338,11 @@ class UserController {
334 ); 338 );
335 339
336 // store the old serviceId as the key for future lookup 340 // store the old serviceId as the key for future lookup
341 // eslint-disable-next-line no-param-reassign
337 serviceIdTranslation[service.serviceId] = newServiceId; 342 serviceIdTranslation[service.serviceId] = newServiceId;
338 343
339 if (service.settings) { 344 if (service.settings) {
345 // eslint-disable-next-line no-param-reassign
340 service.settings = convertToJSON(service.settings); 346 service.settings = convertToJSON(service.settings);
341 } 347 }
342 348
diff --git a/src/internal-server/public/js/transfer.js b/src/internal-server/public/js/transfer.js
index e3b3f92a2..76aa4b938 100644
--- a/src/internal-server/public/js/transfer.js
+++ b/src/internal-server/public/js/transfer.js
@@ -13,5 +13,6 @@ fileInput.addEventListener('change', () => {
13 submitBtn.disabled = false; 13 submitBtn.disabled = false;
14 } 14 }
15 }); 15 });
16 // eslint-disable-next-line unicorn/prefer-blob-reading-methods
16 reader.readAsText(fileInput.files[0]); 17 reader.readAsText(fileInput.files[0]);
17}); 18});
diff --git a/src/lib/Form.ts b/src/lib/Form.ts
index ca96406e7..2b25eb193 100644
--- a/src/lib/Form.ts
+++ b/src/lib/Form.ts
@@ -3,6 +3,7 @@ import vjf from 'mobx-react-form/lib/validators/VJF';
3import { FormFields } from '../@types/mobx-form.types'; 3import { FormFields } from '../@types/mobx-form.types';
4 4
5export default class DefaultForm extends Form { 5export default class DefaultForm extends Form {
6 // eslint-disable-next-line @typescript-eslint/no-useless-constructor
6 constructor(fields: FormFields) { 7 constructor(fields: FormFields) {
7 super(fields); 8 super(fields);
8 } 9 }
diff --git a/src/lib/Menu.ts b/src/lib/Menu.ts
index d611d5f3e..f587f8df9 100644
--- a/src/lib/Menu.ts
+++ b/src/lib/Menu.ts
@@ -700,6 +700,7 @@ class FranzMenu implements StoresProps {
700 700
701 // Don't initialize when window['ferdium'] is undefined 701 // Don't initialize when window['ferdium'] is undefined
702 if (window['ferdium'] === undefined) { 702 if (window['ferdium'] === undefined) {
703 // eslint-disable-next-line no-console
703 console.log('skipping menu init'); 704 console.log('skipping menu init');
704 return; 705 return;
705 } 706 }
@@ -1010,6 +1011,7 @@ class FranzMenu implements StoresProps {
1010 }, 1011 },
1011 ]; 1012 ];
1012 1013
1014 // eslint-disable-next-line unicorn/prefer-at
1013 (tpl[tpl.length - 1].submenu as MenuItemConstructorOptions[]).push( 1015 (tpl[tpl.length - 1].submenu as MenuItemConstructorOptions[]).push(
1014 { 1016 {
1015 type: 'separator', 1017 type: 'separator',
@@ -1027,6 +1029,7 @@ class FranzMenu implements StoresProps {
1027 1029
1028 tpl[5].submenu = this.todosMenu(); 1030 tpl[5].submenu = this.todosMenu();
1029 1031
1032 // eslint-disable-next-line unicorn/prefer-at
1030 (tpl[tpl.length - 1].submenu as MenuItemConstructorOptions[]).push( 1033 (tpl[tpl.length - 1].submenu as MenuItemConstructorOptions[]).push(
1031 { 1034 {
1032 type: 'separator', 1035 type: 'separator',
diff --git a/src/models/Recipe.ts b/src/models/Recipe.ts
index a03d3447f..35e8d4979 100644
--- a/src/models/Recipe.ts
+++ b/src/models/Recipe.ts
@@ -50,11 +50,15 @@ export interface IRecipe {
50 partition: string; 50 partition: string;
51 local: boolean; 51 local: boolean;
52 52
53 // eslint-disable-next-line @typescript-eslint/ban-types
53 readonly overrideUserAgent?: null | Function; 54 readonly overrideUserAgent?: null | Function;
55 // eslint-disable-next-line @typescript-eslint/ban-types
54 readonly buildUrl?: null | Function; 56 readonly buildUrl?: null | Function;
57 // eslint-disable-next-line @typescript-eslint/ban-types
55 readonly modifyRequestHeaders?: null | Function; 58 readonly modifyRequestHeaders?: null | Function;
59 // eslint-disable-next-line @typescript-eslint/ban-types
56 readonly knownCertificateHosts?: null | Function; 60 readonly knownCertificateHosts?: null | Function;
57 readonly events?: null | { (key: string): string }; 61 readonly events?: null | ((key: string) => string);
58 62
59 // TODO: [TS DEBT] Need to check if below properties are needed and where is inherited / implemented from 63 // TODO: [TS DEBT] Need to check if below properties are needed and where is inherited / implemented from
60 author?: string[]; 64 author?: string[];
@@ -132,7 +136,7 @@ export default class Recipe implements IRecipe {
132 this.id = ifUndefined<string>(data.id, this.id); 136 this.id = ifUndefined<string>(data.id, this.id);
133 this.name = ifUndefined<string>(data.name, this.name); 137 this.name = ifUndefined<string>(data.name, this.name);
134 this.version = ifUndefined<string>(data.version, this.version); 138 this.version = ifUndefined<string>(data.version, this.version);
135 this.aliases = ifUndefined<Array<string>>(data.aliases, this.aliases); 139 this.aliases = ifUndefined<string[]>(data.aliases, this.aliases);
136 this.serviceURL = ifUndefined<string>( 140 this.serviceURL = ifUndefined<string>(
137 data.config.serviceURL, 141 data.config.serviceURL,
138 this.serviceURL, 142 this.serviceURL,
diff --git a/src/routes.tsx b/src/routes.tsx
index beada5c96..9f81e46d9 100644
--- a/src/routes.tsx
+++ b/src/routes.tsx
@@ -51,7 +51,7 @@ class FerdiumRoutes extends Component<IProps> {
51 const errorProps = { error: routeProps.stores.globalError.error || {} }; 51 const errorProps = { error: routeProps.stores.globalError.error || {} };
52 52
53 return ( 53 return (
54 // @ts-expect-error 54 // @ts-expect-error Fix me
55 <HistoryRouter history={history}> 55 <HistoryRouter history={history}>
56 <Routes> 56 <Routes>
57 <Route path="/auth" element={<AuthLayoutContainer {...routeProps} />}> 57 <Route path="/auth" element={<AuthLayoutContainer {...routeProps} />}>
@@ -129,7 +129,7 @@ class FerdiumRoutes extends Component<IProps> {
129 /> 129 />
130 <Route 130 <Route
131 path="/settings/services" 131 path="/settings/services"
132 /* @ts-ignore */ 132 // @ts-expect-error Fix me
133 element={<ServicesScreen {...this.props} />} 133 element={<ServicesScreen {...this.props} />}
134 /> 134 />
135 <Route 135 <Route
@@ -138,37 +138,37 @@ class FerdiumRoutes extends Component<IProps> {
138 /> 138 />
139 <Route 139 <Route
140 path={WORKSPACES_ROUTES.ROOT} 140 path={WORKSPACES_ROUTES.ROOT}
141 /* @ts-ignore */ 141 // @ts-expect-error Fix me
142 element={<WorkspacesScreen {...this.props} />} 142 element={<WorkspacesScreen {...this.props} />}
143 /> 143 />
144 <Route 144 <Route
145 path={WORKSPACES_ROUTES.EDIT} 145 path={WORKSPACES_ROUTES.EDIT}
146 /* @ts-ignore */ 146 // @ts-expect-error Fix me
147 element={<EditWorkspaceScreen {...this.props} />} 147 element={<EditWorkspaceScreen {...this.props} />}
148 /> 148 />
149 <Route 149 <Route
150 path="/settings/user" 150 path="/settings/user"
151 /* @ts-ignore */ 151 // @ts-expect-error Fix me
152 element={<AccountScreen {...this.props} />} 152 element={<AccountScreen {...this.props} />}
153 /> 153 />
154 <Route 154 <Route
155 path="/settings/user/edit" 155 path="/settings/user/edit"
156 /* @ts-ignore */ 156 // @ts-expect-error Fix me
157 element={<EditUserScreen {...this.props} />} 157 element={<EditUserScreen {...this.props} />}
158 /> 158 />
159 <Route 159 <Route
160 path="/settings/team" 160 path="/settings/team"
161 /* @ts-ignore */ 161 // @ts-expect-error Fix me
162 element={<TeamScreen {...this.props} />} 162 element={<TeamScreen {...this.props} />}
163 /> 163 />
164 <Route 164 <Route
165 path="/settings/app" 165 path="/settings/app"
166 /* @ts-ignore */ 166 // @ts-expect-error Fix me
167 element={<EditSettingsScreen {...this.props} />} 167 element={<EditSettingsScreen {...this.props} />}
168 /> 168 />
169 <Route 169 <Route
170 path="/settings/invite" 170 path="/settings/invite"
171 /* @ts-ignore */ 171 // @ts-expect-error Fix me
172 element={<InviteSettingsScreen {...this.props} />} 172 element={<InviteSettingsScreen {...this.props} />}
173 /> 173 />
174 <Route 174 <Route
diff --git a/src/stores/AppStore.ts b/src/stores/AppStore.ts
index 82591a2a4..412c52ecf 100644
--- a/src/stores/AppStore.ts
+++ b/src/stores/AppStore.ts
@@ -351,6 +351,7 @@ export default class AppStore extends TypedStore {
351 351
352 // TODO: is there a simple way to use blobs for notifications without storing them on disk? 352 // TODO: is there a simple way to use blobs for notifications without storing them on disk?
353 if (options.icon?.startsWith('blob:')) { 353 if (options.icon?.startsWith('blob:')) {
354 // eslint-disable-next-line no-param-reassign
354 delete options.icon; 355 delete options.icon;
355 } 356 }
356 357
@@ -493,6 +494,7 @@ export default class AppStore extends TypedStore {
493 allOrphanedServiceIds.map(id => removeServicePartitionDirectory(id)), 494 allOrphanedServiceIds.map(id => removeServicePartitionDirectory(id)),
494 ); 495 );
495 } catch (error) { 496 } catch (error) {
497 // eslint-disable-next-line no-console
496 console.log('Error while deleting service partition directory -', error); 498 console.log('Error while deleting service partition directory -', error);
497 } 499 }
498 await Promise.all( 500 await Promise.all(
diff --git a/src/stores/GlobalErrorStore.ts b/src/stores/GlobalErrorStore.ts
index 8547fec72..74a43100b 100644
--- a/src/stores/GlobalErrorStore.ts
+++ b/src/stores/GlobalErrorStore.ts
@@ -27,34 +27,36 @@ export default class GlobalErrorStore extends TypedStore {
27 27
28 @observable response: Response = {} as Response; 28 @observable response: Response = {} as Response;
29 29
30 // TODO: Get rid of the @ts-ignores in this function. 30 // TODO: Get rid of the @ts-expect-errors in this function.
31 constructor(stores: Stores, api: ApiInterface, actions: Actions) { 31 constructor(stores: Stores, api: ApiInterface, actions: Actions) {
32 super(stores, api, actions); 32 super(stores, api, actions);
33 33
34 makeObservable(this); 34 makeObservable(this);
35 35
36 window.addEventListener('error', (...errorArgs: any[]): void => { 36 window.addEventListener('error', (...errorArgs: any[]): void => {
37 // @ts-ignore ts-message: Expected 5 arguments, but got 2. 37 // @ts-expect-error ts-message: Expected 5 arguments, but got 2.
38 this._handleConsoleError.call(this, ['error', ...errorArgs]); 38 this._handleConsoleError.call(this, ['error', ...errorArgs]);
39 }); 39 });
40 40
41 const origConsoleError = console.error; 41 const origConsoleError = console.error;
42 window.console.error = (...errorArgs: any[]) => { 42 window.console.error = (...errorArgs: any[]) => {
43 // @ts-ignore ts-message: Expected 5 arguments, but got 2. 43 // @ts-expect-error ts-message: Expected 5 arguments, but got 2.
44 this._handleConsoleError.call(this, ['error', ...errorArgs]); 44 this._handleConsoleError.call(this, ['error', ...errorArgs]);
45 origConsoleError.apply(this, errorArgs); 45 origConsoleError.apply(this, errorArgs);
46 }; 46 };
47 47
48 // eslint-disable-next-line no-console
48 const origConsoleLog = console.log; 49 const origConsoleLog = console.log;
49 window.console.log = (...logArgs: any[]) => { 50 window.console.log = (...logArgs: any[]) => {
50 // @ts-ignore ts-message: Expected 5 arguments, but got 2. 51 // @ts-expect-error ts-message: Expected 5 arguments, but got 2.
51 this._handleConsoleError.call(this, ['log', ...logArgs]); 52 this._handleConsoleError.call(this, ['log', ...logArgs]);
52 origConsoleLog.apply(this, logArgs); 53 origConsoleLog.apply(this, logArgs);
53 }; 54 };
54 55
56 // eslint-disable-next-line no-console
55 const origConsoleInfo = console.info; 57 const origConsoleInfo = console.info;
56 window.console.info = (...infoArgs: any[]) => { 58 window.console.info = (...infoArgs: any[]) => {
57 // @ts-ignore ts-message: Expected 5 arguments, but got 2. 59 // @ts-expect-error ts-message: Expected 5 arguments, but got 2.
58 this._handleConsoleError.call(this, ['info', ...infoArgs]); 60 this._handleConsoleError.call(this, ['info', ...infoArgs]);
59 origConsoleInfo.apply(this, infoArgs); 61 origConsoleInfo.apply(this, infoArgs);
60 }; 62 };
diff --git a/src/stores/RecipesStore.ts b/src/stores/RecipesStore.ts
index 07f1343f8..b645a5989 100644
--- a/src/stores/RecipesStore.ts
+++ b/src/stores/RecipesStore.ts
@@ -36,6 +36,7 @@ export default class RecipesStore extends TypedStore {
36 36
37 async setup(): Promise<void> { 37 async setup(): Promise<void> {
38 // Initially load all recipes 38 // Initially load all recipes
39 // eslint-disable-next-line @typescript-eslint/no-unused-expressions
39 this.all; 40 this.all;
40 } 41 }
41 42
diff --git a/src/stores/ServicesStore.ts b/src/stores/ServicesStore.ts
index 44f8b277c..7f4693cad 100644
--- a/src/stores/ServicesStore.ts
+++ b/src/stores/ServicesStore.ts
@@ -435,7 +435,7 @@ export default class ServicesStore extends TypedStore {
435 435
436 // TODO: This can actually return undefined as well 436 // TODO: This can actually return undefined as well
437 one(id: string): Service { 437 one(id: string): Service {
438 return this.all.find(service => service.id === id) as Service; 438 return this.all.find(service => service.id === id)!;
439 } 439 }
440 440
441 async _showAddServiceInterface({ recipeId }) { 441 async _showAddServiceInterface({ recipeId }) {
diff --git a/src/stores/SettingsStore.ts b/src/stores/SettingsStore.ts
index 5ca499160..90cd82690 100644
--- a/src/stores/SettingsStore.ts
+++ b/src/stores/SettingsStore.ts
@@ -70,14 +70,17 @@ export default class SettingsStore extends TypedStore {
70 this.all.app.lockingFeatureEnabled && 70 this.all.app.lockingFeatureEnabled &&
71 this.all.app.inactivityLock !== 0 71 this.all.app.inactivityLock !== 0
72 ) { 72 ) {
73 inactivityTimer = setTimeout(() => { 73 inactivityTimer = setTimeout(
74 this.actions.settings.update({ 74 () => {
75 type: 'app', 75 this.actions.settings.update({
76 data: { 76 type: 'app',
77 locked: true, 77 data: {
78 }, 78 locked: true,
79 }); 79 },
80 }, this.all.app.inactivityLock * 1000 * 60); 80 });
81 },
82 this.all.app.inactivityLock * 1000 * 60,
83 );
81 } 84 }
82 }); 85 });
83 getCurrentWindow().on('focus', () => { 86 getCurrentWindow().on('focus', () => {
@@ -176,6 +179,7 @@ export default class SettingsStore extends TypedStore {
176 179
177 const appSettings = this.all[type]; 180 const appSettings = this.all[type];
178 if (Object.hasOwnProperty.call(appSettings, key)) { 181 if (Object.hasOwnProperty.call(appSettings, key)) {
182 // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
179 delete appSettings[key]; 183 delete appSettings[key];
180 184
181 this.actions.settings.update({ 185 this.actions.settings.update({
@@ -185,6 +189,7 @@ export default class SettingsStore extends TypedStore {
185 } 189 }
186 } 190 }
187 191
192 // eslint-disable-next-line @typescript-eslint/ban-types
188 _ensureMigrationAndMarkDone(migrationName: string, callback: Function): void { 193 _ensureMigrationAndMarkDone(migrationName: string, callback: Function): void {
189 if (!this.all.migration[migrationName]) { 194 if (!this.all.migration[migrationName]) {
190 callback(); 195 callback();
diff --git a/src/stores/UserStore.ts b/src/stores/UserStore.ts
index 7ba8f4222..0616acdad 100644
--- a/src/stores/UserStore.ts
+++ b/src/stores/UserStore.ts
@@ -210,7 +210,7 @@ export default class UserStore extends TypedStore {
210 currency, 210 currency,
211 }): Promise<void> { 211 }): Promise<void> {
212 // TODO: [TS DEBT] Need to find a way proper to implement promise's then and catch in request class 212 // TODO: [TS DEBT] Need to find a way proper to implement promise's then and catch in request class
213 // @ts-ignore 213 // @ts-expect-error Fix me
214 const authToken = await this.signupRequest.execute({ 214 const authToken = await this.signupRequest.execute({
215 firstname, 215 firstname,
216 lastname, 216 lastname,
@@ -400,7 +400,7 @@ export default class UserStore extends TypedStore {
400 const params = new URLSearchParams(parsedUrl.search.slice(1)); 400 const params = new URLSearchParams(parsedUrl.search.slice(1));
401 401
402 // TODO: Remove the neccesity for `as string` 402 // TODO: Remove the neccesity for `as string`
403 params.append('authToken', this.authToken as string); 403 params.append('authToken', this.authToken!);
404 404
405 return `${parsedUrl.origin}${parsedUrl.pathname}?${params.toString()}`; 405 return `${parsedUrl.origin}${parsedUrl.pathname}?${params.toString()}`;
406 } 406 }
diff --git a/src/stores/lib/TypedStore.ts b/src/stores/lib/TypedStore.ts
index 0a669e669..8bae529ba 100644
--- a/src/stores/lib/TypedStore.ts
+++ b/src/stores/lib/TypedStore.ts
@@ -41,7 +41,7 @@ export default abstract class TypedStore {
41 this.actions = actions; 41 this.actions = actions;
42 } 42 }
43 43
44 registerReactions(reactions: { (r: IReactionPublic): void }[]): void { 44 registerReactions(reactions: ((r: IReactionPublic) => void)[]): void {
45 for (const reaction of reactions) { 45 for (const reaction of reactions) {
46 this._reactions.push(new Reaction(reaction)); 46 this._reactions.push(new Reaction(reaction));
47 } 47 }
diff --git a/src/webview/contextMenuBuilder.ts b/src/webview/contextMenuBuilder.ts
index 6d904eee3..d18bc56f9 100644
--- a/src/webview/contextMenuBuilder.ts
+++ b/src/webview/contextMenuBuilder.ts
@@ -52,8 +52,8 @@ function translatePopup(res, isError: boolean = false) {
52 z-index: 999999; 52 z-index: 999999;
53 ${ 53 ${
54 isError 54 isError
55 ? `background: rgb(255 37 37);` 55 ? 'background: rgb(255 37 37);'
56 : `background: rgb(131 131 131);` 56 : 'background: rgb(131 131 131);'
57 } 57 }
58 border-radius: 8px; 58 border-radius: 8px;
59 top: 5%; 59 top: 5%;
@@ -148,7 +148,7 @@ const contextMenuStringTable: ContextMenuStringTable = {
148 paste: () => 'Paste', 148 paste: () => 'Paste',
149 pasteAndMatchStyle: () => 'Paste and match style', 149 pasteAndMatchStyle: () => 'Paste and match style',
150 searchWith: ({ searchEngine }) => `Search with ${searchEngine}`, 150 searchWith: ({ searchEngine }) => `Search with ${searchEngine}`,
151 translate: () => `Translate to ...`, 151 translate: () => 'Translate to ...',
152 quickTranslate: ({ translatorLanguage }) => 152 quickTranslate: ({ translatorLanguage }) =>
153 `Translate to ${translatorLanguage}`, 153 `Translate to ${translatorLanguage}`,
154 translateLanguage: ({ translatorLanguage }) => `${translatorLanguage}`, 154 translateLanguage: ({ translatorLanguage }) => `${translatorLanguage}`,
@@ -798,6 +798,7 @@ export class ContextMenuBuilder {
798 callback: { 798 callback: {
799 (dataURL: any): void; 799 (dataURL: any): void;
800 (dataURL: any): void; 800 (dataURL: any): void;
801 // eslint-disable-next-line @typescript-eslint/unified-signatures
801 (arg0: string): void; 802 (arg0: string): void;
802 }, 803 },
803 outputFormat: string = 'image/png', 804 outputFormat: string = 'image/png',
diff --git a/src/webview/lib/Userscript.ts b/src/webview/lib/Userscript.ts
index b0e4fb805..5adc1ac3a 100644
--- a/src/webview/lib/Userscript.ts
+++ b/src/webview/lib/Userscript.ts
@@ -32,7 +32,7 @@ export default class Userscript {
32 * 32 *
33 * @param {*} settings 33 * @param {*} settings
34 */ 34 */
35 // eslint-disable-next-line camelcase 35
36 internal_setSettings(settings: any) { 36 internal_setSettings(settings: any) {
37 // This is needed to get a clean JS object from the settings itself to provide better accessibility 37 // This is needed to get a clean JS object from the settings itself to provide better accessibility
38 // Otherwise this will be a mobX instance 38 // Otherwise this will be a mobX instance
@@ -45,7 +45,7 @@ export default class Userscript {
45 * @param {number} indirect Indirect messages 45 * @param {number} indirect Indirect messages
46 */ 46 */
47 setBadge(direct: number = 0, indirect: number = 0) { 47 setBadge(direct: number = 0, indirect: number = 0) {
48 if (this.recipe && this.recipe.setBadge) { 48 if (this.recipe?.setBadge) {
49 this.recipe.setBadge(direct, indirect); 49 this.recipe.setBadge(direct, indirect);
50 } 50 }
51 } 51 }
@@ -55,7 +55,7 @@ export default class Userscript {
55 * @param {*} title Dialog title 55 * @param {*} title Dialog title
56 */ 56 */
57 setDialogTitle(title: string) { 57 setDialogTitle(title: string) {
58 if (this.recipe && this.recipe.setDialogTitle) { 58 if (this.recipe?.setDialogTitle) {
59 this.recipe.setDialogTitle(title); 59 this.recipe.setDialogTitle(title);
60 } 60 }
61 } 61 }
@@ -66,7 +66,7 @@ export default class Userscript {
66 * @param {...string} files 66 * @param {...string} files
67 */ 67 */
68 injectCSSFiles(...files: string[]) { 68 injectCSSFiles(...files: string[]) {
69 if (this.recipe && this.recipe.injectCSS) { 69 if (this.recipe?.injectCSS) {
70 // @ts-expect-error A spread argument must either have a tuple type or be passed to a rest parameter. 70 // @ts-expect-error A spread argument must either have a tuple type or be passed to a rest parameter.
71 this.recipe.injectCSS(...files); 71 this.recipe.injectCSS(...files);
72 } 72 }
@@ -99,6 +99,7 @@ export default class Userscript {
99 * @param {string} key 99 * @param {string} key
100 * @return Value of the key 100 * @return Value of the key
101 */ 101 */
102 // eslint-disable-next-line consistent-return
102 get(key: string) { 103 get(key: string) {
103 const ferdiumUserKey = window.localStorage.getItem(`ferdium-user-${key}`); 104 const ferdiumUserKey = window.localStorage.getItem(`ferdium-user-${key}`);
104 105
diff --git a/src/webview/recipe.ts b/src/webview/recipe.ts
index 0d18e4347..76615d234 100644
--- a/src/webview/recipe.ts
+++ b/src/webview/recipe.ts
@@ -1,6 +1,6 @@
1/* eslint-disable global-require */ 1/* eslint-disable global-require */
2/* eslint-disable import/no-dynamic-require */ 2/* eslint-disable import/no-dynamic-require */
3/* eslint-disable import/first */ 3
4import { noop, debounce } from 'lodash'; 4import { noop, debounce } from 'lodash';
5import { contextBridge, ipcRenderer } from 'electron'; 5import { contextBridge, ipcRenderer } from 'electron';
6import { join } from 'path'; 6import { join } from 'path';
@@ -52,7 +52,7 @@ import Service from '../models/Service';
52// This will cause the service to fail loading 52// This will cause the service to fail loading
53// As the message API is not actually needed, we'll add this shim sendMessage 53// As the message API is not actually needed, we'll add this shim sendMessage
54// function in order for darkreader to continue working 54// function in order for darkreader to continue working
55// @ts-ignore 55// @ts-expect-error Fix this
56window.chrome.runtime.sendMessage = noop; 56window.chrome.runtime.sendMessage = noop;
57 57
58const debug = require('../preload-safe-debug')('Ferdium:Plugin'); 58const debug = require('../preload-safe-debug')('Ferdium:Plugin');
@@ -143,9 +143,9 @@ class RecipeController {
143 service: Service; 143 service: Service;
144 } = { 144 } = {
145 overrideSpellcheckerLanguage: false, 145 overrideSpellcheckerLanguage: false,
146 // @ts-ignore 146 // @ts-expect-error Fix this
147 app: DEFAULT_APP_SETTINGS, 147 app: DEFAULT_APP_SETTINGS,
148 // @ts-ignore 148 // @ts-expect-error Fix this
149 service: { 149 service: {
150 isDarkModeEnabled: false, 150 isDarkModeEnabled: false,
151 spellcheckerLanguage: '', 151 spellcheckerLanguage: '',
@@ -233,6 +233,7 @@ class RecipeController {
233 const modulePath = join(recipe.path, 'webview.js'); 233 const modulePath = join(recipe.path, 'webview.js');
234 debug('module path', modulePath); 234 debug('module path', modulePath);
235 // Delete module from cache 235 // Delete module from cache
236 // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
236 delete require.cache[require.resolve(modulePath)]; 237 delete require.cache[require.resolve(modulePath)];
237 try { 238 try {
238 this.recipe = new RecipeWebview( 239 this.recipe = new RecipeWebview(
@@ -311,7 +312,7 @@ class RecipeController {
311 debug('translatorEngine', this.settings.app.translatorEngine); 312 debug('translatorEngine', this.settings.app.translatorEngine);
312 debug('translatorLanguage', this.settings.app.translatorLanguage); 313 debug('translatorLanguage', this.settings.app.translatorLanguage);
313 314
314 if (this.userscript && this.userscript.internal_setSettings) { 315 if (this.userscript?.internal_setSettings) {
315 this.userscript.internal_setSettings(this.settings); 316 this.userscript.internal_setSettings(this.settings);
316 } 317 }
317 318
@@ -339,7 +340,7 @@ class RecipeController {
339 'Darkmode enabled?', 340 'Darkmode enabled?',
340 this.settings.service.isDarkModeEnabled, 341 this.settings.service.isDarkModeEnabled,
341 'Dark theme active?', 342 'Dark theme active?',
342 // @ts-ignore 343 // @ts-expect-error Fix this
343 this.settings.app.isDarkThemeActive, 344 this.settings.app.isDarkThemeActive,
344 ); 345 );
345 346
@@ -356,7 +357,7 @@ class RecipeController {
356 debug('Enable dark mode'); 357 debug('Enable dark mode');
357 358
358 // Check if recipe has a custom dark mode handler 359 // Check if recipe has a custom dark mode handler
359 if (this.recipe && this.recipe.darkModeHandler) { 360 if (this.recipe?.darkModeHandler) {
360 debug('Using custom dark mode handler'); 361 debug('Using custom dark mode handler');
361 362
362 // Remove other dark mode styles if they were already loaded 363 // Remove other dark mode styles if they were already loaded
@@ -399,7 +400,7 @@ class RecipeController {
399 debug('Remove dark mode'); 400 debug('Remove dark mode');
400 debug('DarkMode disabled - removing remaining styles'); 401 debug('DarkMode disabled - removing remaining styles');
401 402
402 if (this.recipe && this.recipe.darkModeHandler) { 403 if (this.recipe?.darkModeHandler) {
403 // Remove other dark mode styles if they were already loaded 404 // Remove other dark mode styles if they were already loaded
404 if (this.hasUpdatedBeforeRecipeLoaded) { 405 if (this.hasUpdatedBeforeRecipeLoaded) {
405 this.hasUpdatedBeforeRecipeLoaded = false; 406 this.hasUpdatedBeforeRecipeLoaded = false;