aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar MCMXC <16797721+mcmxcdev@users.noreply.github.com>2024-04-18 08:18:36 -0600
committerLibravatar GitHub <noreply@github.com>2024-04-18 08:18:36 -0600
commitc49723056acec489765acb54bae3889ac07f25af (patch)
tree58bea705d61a728b060e615ce514b8d4a7936c9e
parentfeat: hide all services workspace (#1713) (diff)
downloadferdium-app-c49723056acec489765acb54bae3889ac07f25af.tar.gz
ferdium-app-c49723056acec489765acb54bae3889ac07f25af.tar.zst
ferdium-app-c49723056acec489765acb54bae3889ac07f25af.zip
refactor: bring down eslint warnings to zero (#1714)
- install `@eslint-react/eslint-plugin` dependency - configure `@eslint-react/eslint-plugin` in eslint config - modernize `lint` command in `package.json` - disable or fix various reported lint issues - fix `div` being nested in `p` for settings - replace deprecated `event.keyCode` with `event.key` - update isEscKeyPress method and unit tests which used deprecated `event.keyCode` - allow `eslint` v8 as peer dependency for `@eslint-react/eslint-plugin`
-rw-r--r--.eslintignore1
-rw-r--r--.eslintrc.js13
-rw-r--r--package.json4
-rw-r--r--pnpm-lock.yaml280
-rw-r--r--scripts/link-readme.ts2
-rw-r--r--src/I18n.tsx4
-rw-r--r--src/api/utils/auth.ts1
-rw-r--r--src/components/auth/AuthLayout.tsx1
-rw-r--r--src/components/downloadManager/DownloadManagerDashboard.tsx1
-rw-r--r--src/components/downloadManager/DownloadManagerLayout.tsx4
-rw-r--r--src/components/settings/SettingsLayout.tsx2
-rw-r--r--src/components/settings/releaseNotes/ReleaseNotesDashboard.tsx1
-rw-r--r--src/components/settings/releaseNotes/ReleaseNotesLayout.tsx4
-rw-r--r--src/components/settings/settings/EditSettingsForm.tsx56
-rw-r--r--src/components/settings/supportFerdium/SupportFerdiumDashboard.tsx14
-rw-r--r--src/components/ui/FAB.tsx1
-rw-r--r--src/components/ui/SearchInput.tsx1
-rw-r--r--src/components/ui/Tabs/Tabs.tsx7
-rw-r--r--src/components/ui/button/index.tsx2
-rw-r--r--src/components/ui/imageUpload/index.tsx2
-rw-r--r--src/components/ui/input/index.tsx2
-rw-r--r--src/components/ui/select/index.tsx2
-rw-r--r--src/components/ui/textarea/index.tsx7
-rw-r--r--src/containers/auth/AuthReleaseNotesScreen.tsx1
-rw-r--r--src/containers/download-manager/DownloadManagerScreen.tsx17
-rw-r--r--src/containers/settings/EditServiceScreen.tsx4
-rw-r--r--src/containers/settings/ReleaseNotesScreen.tsx18
-rw-r--r--src/containers/settings/SupportScreen.tsx18
-rw-r--r--src/electron/ipc-api/autoUpdate.ts1
-rw-r--r--src/electron/ipc-api/index.ts1
-rw-r--r--src/electron/macOSPermissions.ts2
-rw-r--r--src/features/appearance/index.ts1
-rw-r--r--src/features/basicAuth/Component.tsx2
-rw-r--r--src/features/communityRecipes/store.ts1
-rw-r--r--src/features/quickSwitch/Component.tsx2
-rw-r--r--src/features/todos/actions.ts1
-rw-r--r--src/features/todos/components/TodosWebview.tsx3
-rw-r--r--src/features/todos/index.ts1
-rw-r--r--src/features/webControls/containers/WebControlsScreen.tsx2
-rw-r--r--src/features/workspaces/components/CreateWorkspaceForm.tsx2
-rw-r--r--src/features/workspaces/components/EditWorkspaceForm.tsx7
-rw-r--r--src/features/workspaces/components/WorkspaceDrawer.tsx2
-rw-r--r--src/features/workspaces/components/WorkspaceDrawerItem.tsx1
-rw-r--r--src/features/workspaces/components/WorkspaceServiceListItem.tsx1
-rw-r--r--src/features/workspaces/components/WorkspacesDashboard.tsx50
-rw-r--r--src/features/workspaces/index.ts1
-rw-r--r--src/index.ts1
-rw-r--r--src/internal-server/app/Controllers/Http/ImageController.js1
-rw-r--r--src/internal-server/start/migrate.js1
-rw-r--r--src/internal-server/test.ts2
-rw-r--r--src/jsUtils.ts2
-rw-r--r--src/routes.tsx3
-rw-r--r--src/stores/AppStore.ts2
-rw-r--r--src/stores/ServicesStore.ts9
-rw-r--r--src/stores/lib/Request.ts2
-rw-r--r--src/styles/settings.scss1
-rw-r--r--src/themes/default/index.ts1
-rw-r--r--src/webview/lib/RecipeWebview.ts1
-rw-r--r--test/jsUtils.test.ts8
59 files changed, 450 insertions, 135 deletions
diff --git a/.eslintignore b/.eslintignore
index f1867f427..30357b9c4 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -10,6 +10,7 @@ pids
10# Coverage directory used by tools like istanbul 10# Coverage directory used by tools like istanbul
11coverage 11coverage
12.eslintcache 12.eslintcache
13.eslintrc.js
13 14
14# Dependency directory 15# Dependency directory
15# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 16# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
diff --git a/.eslintrc.js b/.eslintrc.js
index ed473c21b..f95bbbd9f 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -17,8 +17,9 @@ module.exports = {
17 'plugin:unicorn/recommended', 17 'plugin:unicorn/recommended',
18 'plugin:sonar/recommended', 18 'plugin:sonar/recommended',
19 'plugin:prettier/recommended', 19 'plugin:prettier/recommended',
20 'plugin:@eslint-react/recommended-legacy',
20 ], 21 ],
21 plugins: ['jest'], 22 plugins: ['@eslint-react', 'jest'],
22 settings: { 23 settings: {
23 react: { 24 react: {
24 pragma: 'React', // Pragma to use, default to "React" 25 pragma: 'React', // Pragma to use, default to "React"
@@ -45,6 +46,7 @@ module.exports = {
45 // TODO: Opt-in to a stricter ruleset in the future 46 // TODO: Opt-in to a stricter ruleset in the future
46 // 'plugin:@typescript-eslint/strict-type-checked', 47 // 'plugin:@typescript-eslint/strict-type-checked',
47 'plugin:@typescript-eslint/stylistic-type-checked', 48 'plugin:@typescript-eslint/stylistic-type-checked',
49 'plugin:@eslint-react/recommended-type-checked-legacy',
48 ], 50 ],
49 parser: '@typescript-eslint/parser', 51 parser: '@typescript-eslint/parser',
50 plugins: [], 52 plugins: [],
@@ -71,6 +73,12 @@ module.exports = {
71 // eslint-plugin-import 73 // eslint-plugin-import
72 'import/no-extraneous-dependencies': 0, 74 'import/no-extraneous-dependencies': 0,
73 75
76 // @eslint-react
77 '@eslint-react/no-class-component': 0,
78 '@eslint-react/no-complicated-conditional-rendering': 0,
79 '@eslint-react/no-leaked-conditional-rendering': 0,
80 '@eslint-react/hooks-extra/ensure-custom-hooks-using-other-hooks': 0,
81
74 // sonar 82 // sonar
75 'sonar/no-try-promise': 0, 83 'sonar/no-try-promise': 0,
76 }, 84 },
@@ -105,7 +113,7 @@ module.exports = {
105 'react/jsx-filename-extension': 1, 113 'react/jsx-filename-extension': 1,
106 'react/jsx-no-bind': 1, 114 'react/jsx-no-bind': 1,
107 'react/jsx-props-no-spreading': 0, 115 'react/jsx-props-no-spreading': 0,
108 'react/prefer-stateless-function': 1, 116 'react/prefer-stateless-function': 0,
109 'react/static-property-placement': 0, 117 'react/static-property-placement': 0,
110 'react/state-in-constructor': 1, 118 'react/state-in-constructor': 1,
111 'react/sort-comp': 0, 119 'react/sort-comp': 0,
@@ -137,6 +145,7 @@ module.exports = {
137 'unicorn/import-style': 0, 145 'unicorn/import-style': 0,
138 'unicorn/consistent-destructuring': 0, 146 'unicorn/consistent-destructuring': 0,
139 'unicorn/no-anonymous-default-export': 0, 147 'unicorn/no-anonymous-default-export': 0,
148 'unicorn/no-array-for-each': 0,
140 // eslint-plugin-sonar 149 // eslint-plugin-sonar
141 'sonar/function-name': 0, 150 'sonar/function-name': 0,
142 }, 151 },
diff --git a/package.json b/package.json
index 988791a98..f49c636ae 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
32 "test": "jest", 32 "test": "jest",
33 "test:watch": "jest --watch", 33 "test:watch": "jest --watch",
34 "typecheck": "tsc --noEmit", 34 "typecheck": "tsc --noEmit",
35 "lint": "eslint \"{src,test,scripts}/**/*.{js,jsx,mjs,ts,tsx}\" --quiet", 35 "lint": "eslint . --max-warnings 0",
36 "lint:fix": "pnpm lint --cache --fix", 36 "lint:fix": "pnpm lint --cache --fix",
37 "biome:check": "pnpm biome check .", 37 "biome:check": "pnpm biome check .",
38 "biome:check:fix": "pnpm biome:check --apply-unsafe", 38 "biome:check:fix": "pnpm biome:check --apply-unsafe",
@@ -136,6 +136,7 @@
136 "@commitlint/cli": "19.2.1", 136 "@commitlint/cli": "19.2.1",
137 "@commitlint/config-conventional": "19.1.0", 137 "@commitlint/config-conventional": "19.1.0",
138 "@electron/notarize": "2.3.0", 138 "@electron/notarize": "2.3.0",
139 "@eslint-react/eslint-plugin": "1.5.8",
139 "@formatjs/cli": "6.2.9", 140 "@formatjs/cli": "6.2.9",
140 "@jest/types": "29.6.3", 141 "@jest/types": "29.6.3",
141 "@types/auto-launch": "5.0.5", 142 "@types/auto-launch": "5.0.5",
@@ -201,6 +202,7 @@
201 "allowedVersions": { 202 "allowedVersions": {
202 "@typescript-eslint/parser": "^7.0.0", 203 "@typescript-eslint/parser": "^7.0.0",
203 "esbuild-sass-plugin>esbuild": "^0.16.7", 204 "esbuild-sass-plugin>esbuild": "^0.16.7",
205 "eslint": "^8.0.0",
204 "react-electron-web-view>react": "^18.0.0", 206 "react-electron-web-view>react": "^18.0.0",
205 "react-electron-web-view>react-dom": "^18.0.0", 207 "react-electron-web-view>react-dom": "^18.0.0",
206 "react-sortable-hoc>react": "^18.0.0", 208 "react-sortable-hoc>react": "^18.0.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e88ccd691..1b8261174 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -270,6 +270,9 @@ devDependencies:
270 '@electron/notarize': 270 '@electron/notarize':
271 specifier: 2.3.0 271 specifier: 2.3.0
272 version: 2.3.0 272 version: 2.3.0
273 '@eslint-react/eslint-plugin':
274 specifier: 1.5.8
275 version: 1.5.8(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5)
273 '@formatjs/cli': 276 '@formatjs/cli':
274 specifier: 6.2.9 277 specifier: 6.2.9
275 version: 6.2.9 278 version: 6.2.9
@@ -1853,7 +1856,7 @@ packages:
1853 resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} 1856 resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
1854 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1857 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
1855 peerDependencies: 1858 peerDependencies:
1856 eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 1859 eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 || ^8.0.0
1857 dependencies: 1860 dependencies:
1858 eslint: 8.57.0 1861 eslint: 8.57.0
1859 eslint-visitor-keys: 3.4.3 1862 eslint-visitor-keys: 3.4.3
@@ -1864,6 +1867,128 @@ packages:
1864 engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 1867 engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
1865 dev: true 1868 dev: true
1866 1869
1870 /@eslint-react/ast@1.5.8(eslint@8.57.0)(typescript@5.4.5):
1871 resolution: {integrity: sha512-bfhjJYByn/oql2H3xqlUwqsCrCsu7ItYTuSl7vU2VWuUaGTNm2DVLljje5prUq7z26mQ/96YzW16OFoSmGovjw==}
1872 dependencies:
1873 '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
1874 '@eslint-react/tools': 1.5.8
1875 '@eslint-react/types': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1876 '@typescript-eslint/scope-manager': 7.6.0
1877 '@typescript-eslint/types': 7.6.0
1878 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
1879 string-ts: 2.1.0
1880 transitivePeerDependencies:
1881 - eslint
1882 - supports-color
1883 - typescript
1884 dev: true
1885
1886 /@eslint-react/core@1.5.8(eslint@8.57.0)(typescript@5.4.5):
1887 resolution: {integrity: sha512-iJoWoD5+dPS0sZvyVhkeQi2K5tI/fviRavsXFAR4GDhiviI8tZvKQg8mj/OlHDPUlvA+Bz8P0d0dxEXM3nyolQ==}
1888 dependencies:
1889 '@eslint-react/ast': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1890 '@eslint-react/jsx': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1891 '@eslint-react/shared': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1892 '@eslint-react/tools': 1.5.8
1893 '@eslint-react/types': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1894 '@typescript-eslint/scope-manager': 7.6.0
1895 '@typescript-eslint/type-utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
1896 '@typescript-eslint/types': 7.6.0
1897 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
1898 short-unique-id: 5.0.3
1899 transitivePeerDependencies:
1900 - eslint
1901 - supports-color
1902 - typescript
1903 dev: true
1904
1905 /@eslint-react/eslint-plugin@1.5.8(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5):
1906 resolution: {integrity: sha512-SQgGcd5DKK0zjOn6O1QztTolzRzw+VHP9qMWwlRkonoxau4T9U5RwsbBzl2Aojk9v3CtPOHtr1AQ8ZOUEi6d4A==}
1907 engines: {bun: '>=1.0.15', node: '>=18.18.0'}
1908 peerDependencies:
1909 '@typescript-eslint/parser': '>=7.5.0 || ^7.0.0'
1910 eslint: '>=9.0.0 || ^8.0.0'
1911 typescript: '>=5.3.3'
1912 dependencies:
1913 '@eslint-react/shared': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1914 '@eslint-react/tools': 1.5.8
1915 '@eslint-react/types': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1916 '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
1917 '@typescript-eslint/scope-manager': 7.6.0
1918 '@typescript-eslint/type-utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
1919 '@typescript-eslint/types': 7.6.0
1920 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
1921 eslint: 8.57.0
1922 eslint-plugin-react-core: 1.5.8(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5)
1923 eslint-plugin-react-dom: 1.5.8(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5)
1924 eslint-plugin-react-hooks-extra: 1.5.8(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5)
1925 eslint-plugin-react-naming-convention: 1.5.8(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5)
1926 typescript: 5.4.5
1927 transitivePeerDependencies:
1928 - supports-color
1929 dev: true
1930
1931 /@eslint-react/jsx@1.5.8(eslint@8.57.0)(typescript@5.4.5):
1932 resolution: {integrity: sha512-zQd239hspAJ9I9ejxKh7MuSW27HNVsXWiRHzit3azXRX95jwGZeeMRQeh9tS9290ANr8n2vBbSTePbl1FkuPKg==}
1933 dependencies:
1934 '@eslint-react/ast': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1935 '@eslint-react/shared': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1936 '@eslint-react/tools': 1.5.8
1937 '@eslint-react/types': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1938 '@eslint-react/var': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1939 '@typescript-eslint/scope-manager': 7.6.0
1940 '@typescript-eslint/types': 7.6.0
1941 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
1942 micro-memoize: 4.1.2
1943 transitivePeerDependencies:
1944 - eslint
1945 - supports-color
1946 - typescript
1947 dev: true
1948
1949 /@eslint-react/shared@1.5.8(eslint@8.57.0)(typescript@5.4.5):
1950 resolution: {integrity: sha512-XE6tp39NACI9pFD1x5LRXE2NfcQoRDVsOEqzYfS1XQczTHann2ySzrPgTPJE4KlKT156uRxg8DqPkcpsioQIEw==}
1951 dependencies:
1952 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
1953 deepmerge-ts: 5.1.0
1954 transitivePeerDependencies:
1955 - eslint
1956 - supports-color
1957 - typescript
1958 dev: true
1959
1960 /@eslint-react/tools@1.5.8:
1961 resolution: {integrity: sha512-Ye4HqrB6l8JomMRE7A8DUZsNNK5P28dDBXE69kR9UjWQqXU1xA2E5Pw7g9dn7CSNkPSi6IIm/1cFAPzPgMUqrQ==}
1962 dev: true
1963
1964 /@eslint-react/types@1.5.8(eslint@8.57.0)(typescript@5.4.5):
1965 resolution: {integrity: sha512-u1Y1G8+IRiNNZ+REMMkVvHAp+I3ruJoKRybHsM1DCoyT3xZZ85wNPwB5R+oBurEXG7vRi3A9CsUGKU7v+PCbfw==}
1966 dependencies:
1967 '@eslint-react/tools': 1.5.8
1968 '@typescript-eslint/types': 7.6.0
1969 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
1970 transitivePeerDependencies:
1971 - eslint
1972 - supports-color
1973 - typescript
1974 dev: true
1975
1976 /@eslint-react/var@1.5.8(eslint@8.57.0)(typescript@5.4.5):
1977 resolution: {integrity: sha512-RhQfA2oTGTX7d8aauU8pIqq+tAxv5bSl/8LxtvNx6UXQxQAuk/2Oss7ICdgm6GBMUGpbaBATTgIo3wOytLwqCw==}
1978 dependencies:
1979 '@eslint-react/ast': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1980 '@eslint-react/tools': 1.5.8
1981 '@eslint-react/types': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
1982 '@typescript-eslint/scope-manager': 7.6.0
1983 '@typescript-eslint/types': 7.6.0
1984 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
1985 string-ts: 2.1.0
1986 transitivePeerDependencies:
1987 - eslint
1988 - supports-color
1989 - typescript
1990 dev: true
1991
1867 /@eslint/eslintrc@2.1.4: 1992 /@eslint/eslintrc@2.1.4:
1868 resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} 1993 resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
1869 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1994 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -3219,7 +3344,7 @@ packages:
3219 engines: {node: ^18.18.0 || >=20.0.0} 3344 engines: {node: ^18.18.0 || >=20.0.0}
3220 peerDependencies: 3345 peerDependencies:
3221 '@typescript-eslint/parser': ^7.0.0 3346 '@typescript-eslint/parser': ^7.0.0
3222 eslint: ^8.56.0 3347 eslint: ^8.56.0 || ^8.0.0
3223 typescript: '*' 3348 typescript: '*'
3224 peerDependenciesMeta: 3349 peerDependenciesMeta:
3225 typescript: 3350 typescript:
@@ -3247,7 +3372,7 @@ packages:
3247 resolution: {integrity: sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==} 3372 resolution: {integrity: sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==}
3248 engines: {node: ^18.18.0 || >=20.0.0} 3373 engines: {node: ^18.18.0 || >=20.0.0}
3249 peerDependencies: 3374 peerDependencies:
3250 eslint: ^8.56.0 3375 eslint: ^8.56.0 || ^8.0.0
3251 typescript: '*' 3376 typescript: '*'
3252 peerDependenciesMeta: 3377 peerDependenciesMeta:
3253 typescript: 3378 typescript:
@@ -3312,7 +3437,7 @@ packages:
3312 resolution: {integrity: sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==} 3437 resolution: {integrity: sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==}
3313 engines: {node: ^18.18.0 || >=20.0.0} 3438 engines: {node: ^18.18.0 || >=20.0.0}
3314 peerDependencies: 3439 peerDependencies:
3315 eslint: ^8.56.0 3440 eslint: ^8.56.0 || ^8.0.0
3316 typescript: '*' 3441 typescript: '*'
3317 peerDependenciesMeta: 3442 peerDependenciesMeta:
3318 typescript: 3443 typescript:
@@ -3451,7 +3576,7 @@ packages:
3451 resolution: {integrity: sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==} 3576 resolution: {integrity: sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==}
3452 engines: {node: ^18.18.0 || >=20.0.0} 3577 engines: {node: ^18.18.0 || >=20.0.0}
3453 peerDependencies: 3578 peerDependencies:
3454 eslint: ^8.56.0 3579 eslint: ^8.56.0 || ^8.0.0
3455 dependencies: 3580 dependencies:
3456 '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) 3581 '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
3457 '@types/json-schema': 7.0.15 3582 '@types/json-schema': 7.0.15
@@ -5663,6 +5788,11 @@ packages:
5663 resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 5788 resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
5664 dev: true 5789 dev: true
5665 5790
5791 /deepmerge-ts@5.1.0:
5792 resolution: {integrity: sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==}
5793 engines: {node: '>=16.0.0'}
5794 dev: true
5795
5666 /deepmerge@4.3.0: 5796 /deepmerge@4.3.0:
5667 resolution: {integrity: sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==} 5797 resolution: {integrity: sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==}
5668 engines: {node: '>=0.10.0'} 5798 engines: {node: '>=0.10.0'}
@@ -6477,7 +6607,7 @@ packages:
6477 resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} 6607 resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==}
6478 engines: {node: ^10.12.0 || >=12.0.0} 6608 engines: {node: ^10.12.0 || >=12.0.0}
6479 peerDependencies: 6609 peerDependencies:
6480 eslint: ^7.32.0 || ^8.2.0 6610 eslint: ^7.32.0 || ^8.2.0 || ^8.0.0
6481 eslint-plugin-import: ^2.25.2 6611 eslint-plugin-import: ^2.25.2
6482 dependencies: 6612 dependencies:
6483 confusing-browser-globals: 1.0.11 6613 confusing-browser-globals: 1.0.11
@@ -6493,7 +6623,7 @@ packages:
6493 peerDependencies: 6623 peerDependencies:
6494 '@typescript-eslint/eslint-plugin': ^7.0.0 6624 '@typescript-eslint/eslint-plugin': ^7.0.0
6495 '@typescript-eslint/parser': ^7.0.0 6625 '@typescript-eslint/parser': ^7.0.0
6496 eslint: ^8.56.0 6626 eslint: ^8.56.0 || ^8.0.0
6497 dependencies: 6627 dependencies:
6498 '@typescript-eslint/eslint-plugin': 7.6.0(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5) 6628 '@typescript-eslint/eslint-plugin': 7.6.0(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5)
6499 '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.5) 6629 '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
@@ -6507,7 +6637,7 @@ packages:
6507 resolution: {integrity: sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==} 6637 resolution: {integrity: sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==}
6508 engines: {node: ^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0} 6638 engines: {node: ^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0}
6509 peerDependencies: 6639 peerDependencies:
6510 eslint: ^7.32.0 || ^8.2.0 6640 eslint: ^7.32.0 || ^8.2.0 || ^8.0.0
6511 eslint-plugin-import: ^2.25.3 6641 eslint-plugin-import: ^2.25.3
6512 eslint-plugin-jsx-a11y: ^6.5.1 6642 eslint-plugin-jsx-a11y: ^6.5.1
6513 eslint-plugin-react: ^7.28.0 6643 eslint-plugin-react: ^7.28.0
@@ -6527,7 +6657,7 @@ packages:
6527 resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} 6657 resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
6528 hasBin: true 6658 hasBin: true
6529 peerDependencies: 6659 peerDependencies:
6530 eslint: '>=7.0.0' 6660 eslint: '>=7.0.0 || ^8.0.0'
6531 dependencies: 6661 dependencies:
6532 eslint: 8.57.0 6662 eslint: 8.57.0
6533 dev: true 6663 dev: true
@@ -6576,7 +6706,7 @@ packages:
6576 engines: {node: '>=4'} 6706 engines: {node: '>=4'}
6577 peerDependencies: 6707 peerDependencies:
6578 '@typescript-eslint/parser': '*' 6708 '@typescript-eslint/parser': '*'
6579 eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 6709 eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^8.0.0
6580 peerDependenciesMeta: 6710 peerDependenciesMeta:
6581 '@typescript-eslint/parser': 6711 '@typescript-eslint/parser':
6582 optional: true 6712 optional: true
@@ -6632,7 +6762,7 @@ packages:
6632 resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} 6762 resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==}
6633 engines: {node: '>=4.0'} 6763 engines: {node: '>=4.0'}
6634 peerDependencies: 6764 peerDependencies:
6635 eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 6765 eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^8.0.0
6636 dependencies: 6766 dependencies:
6637 '@babel/runtime': 7.23.5 6767 '@babel/runtime': 7.23.5
6638 aria-query: 5.3.0 6768 aria-query: 5.3.0
@@ -6658,7 +6788,7 @@ packages:
6658 engines: {node: ^14.18.0 || >=16.0.0} 6788 engines: {node: ^14.18.0 || >=16.0.0}
6659 peerDependencies: 6789 peerDependencies:
6660 '@types/eslint': '>=8.0.0' 6790 '@types/eslint': '>=8.0.0'
6661 eslint: '>=8.0.0' 6791 eslint: '>=8.0.0 || ^8.0.0'
6662 eslint-config-prettier: '*' 6792 eslint-config-prettier: '*'
6663 prettier: '>=3.0.0' 6793 prettier: '>=3.0.0'
6664 peerDependenciesMeta: 6794 peerDependenciesMeta:
@@ -6674,20 +6804,127 @@ packages:
6674 synckit: 0.8.6 6804 synckit: 0.8.6
6675 dev: true 6805 dev: true
6676 6806
6807 /eslint-plugin-react-core@1.5.8(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5):
6808 resolution: {integrity: sha512-AWF0N07w3Tpkq2VKiZdvf1ItdQuYw/nJFmcs1ZZZOKq6eNSYpsSzKDpurwjAyMl4+WE+xL2b6lrUuVawfNpkMQ==}
6809 engines: {bun: '>=1.0.15', node: '>=18.18.0'}
6810 peerDependencies:
6811 '@typescript-eslint/parser': '>=7.5.0 || ^7.0.0'
6812 eslint: '>=9.0.0 || ^8.0.0'
6813 typescript: '>=5.3.3'
6814 dependencies:
6815 '@eslint-react/ast': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6816 '@eslint-react/core': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6817 '@eslint-react/jsx': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6818 '@eslint-react/shared': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6819 '@eslint-react/tools': 1.5.8
6820 '@eslint-react/types': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6821 '@eslint-react/var': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6822 '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6823 '@typescript-eslint/scope-manager': 7.6.0
6824 '@typescript-eslint/type-utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6825 '@typescript-eslint/types': 7.6.0
6826 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6827 eslint: 8.57.0
6828 string-ts: 2.1.0
6829 ts-api-utils: 1.3.0(typescript@5.4.5)
6830 typescript: 5.4.5
6831 transitivePeerDependencies:
6832 - supports-color
6833 dev: true
6834
6835 /eslint-plugin-react-dom@1.5.8(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5):
6836 resolution: {integrity: sha512-xPCfuSvdccCnzyMHeBWCepi+SniXf5IszcQB0951Chvb4pSkwyemuN0xy4ux4cu0i5wyHzQZJk3jBqM1b49+YQ==}
6837 engines: {bun: '>=1.0.15', node: '>=18.18.0'}
6838 peerDependencies:
6839 '@typescript-eslint/parser': '>=7.5.0 || ^7.0.0'
6840 eslint: '>=9.0.0 || ^8.0.0'
6841 typescript: '>=5.3.3'
6842 dependencies:
6843 '@eslint-react/ast': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6844 '@eslint-react/core': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6845 '@eslint-react/jsx': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6846 '@eslint-react/shared': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6847 '@eslint-react/tools': 1.5.8
6848 '@eslint-react/types': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6849 '@eslint-react/var': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6850 '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6851 '@typescript-eslint/scope-manager': 7.6.0
6852 '@typescript-eslint/types': 7.6.0
6853 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6854 eslint: 8.57.0
6855 string-ts: 2.1.0
6856 typescript: 5.4.5
6857 transitivePeerDependencies:
6858 - supports-color
6859 dev: true
6860
6861 /eslint-plugin-react-hooks-extra@1.5.8(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5):
6862 resolution: {integrity: sha512-GDitayVrF51bDH+ASs9QCvw6YZOn5A99iQMH9wKCGlaGA+mUD0vFt8EHW4kALjmBNSjA/y5ZZ3/435mGwrIv8Q==}
6863 engines: {bun: '>=1.0.15', node: '>=18.18.0'}
6864 peerDependencies:
6865 '@typescript-eslint/parser': '>=7.5.0 || ^7.0.0'
6866 eslint: '>=9.0.0 || ^8.0.0'
6867 typescript: '>=5.3.3'
6868 dependencies:
6869 '@eslint-react/ast': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6870 '@eslint-react/core': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6871 '@eslint-react/jsx': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6872 '@eslint-react/shared': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6873 '@eslint-react/tools': 1.5.8
6874 '@eslint-react/types': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6875 '@eslint-react/var': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6876 '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6877 '@typescript-eslint/scope-manager': 7.6.0
6878 '@typescript-eslint/type-utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6879 '@typescript-eslint/types': 7.6.0
6880 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6881 eslint: 8.57.0
6882 string-ts: 2.1.0
6883 typescript: 5.4.5
6884 transitivePeerDependencies:
6885 - supports-color
6886 dev: true
6887
6677 /eslint-plugin-react-hooks@4.6.0(eslint@8.57.0): 6888 /eslint-plugin-react-hooks@4.6.0(eslint@8.57.0):
6678 resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} 6889 resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
6679 engines: {node: '>=10'} 6890 engines: {node: '>=10'}
6680 peerDependencies: 6891 peerDependencies:
6681 eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 6892 eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^8.0.0
6682 dependencies: 6893 dependencies:
6683 eslint: 8.57.0 6894 eslint: 8.57.0
6684 dev: true 6895 dev: true
6685 6896
6897 /eslint-plugin-react-naming-convention@1.5.8(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.5):
6898 resolution: {integrity: sha512-1pZNudmoiaB4ZnfGauMoi9at4pSmzb0EMidfDXybmev09fEuO7mBUfpks/Fjs1PGDGogEhe0a9KQIVTPe4Ui2w==}
6899 engines: {bun: '>=1.0.15', node: '>=18.18.0'}
6900 peerDependencies:
6901 '@typescript-eslint/parser': '>=7.5.0 || ^7.0.0'
6902 eslint: '>=9.0.0 || ^8.0.0'
6903 typescript: '>=5.3.3'
6904 dependencies:
6905 '@eslint-react/ast': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6906 '@eslint-react/core': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6907 '@eslint-react/jsx': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6908 '@eslint-react/shared': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6909 '@eslint-react/tools': 1.5.8
6910 '@eslint-react/types': 1.5.8(eslint@8.57.0)(typescript@5.4.5)
6911 '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6912 '@typescript-eslint/scope-manager': 7.6.0
6913 '@typescript-eslint/type-utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6914 '@typescript-eslint/types': 7.6.0
6915 '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.5)
6916 eslint: 8.57.0
6917 string-ts: 2.1.0
6918 typescript: 5.4.5
6919 transitivePeerDependencies:
6920 - supports-color
6921 dev: true
6922
6686 /eslint-plugin-react@7.34.1(eslint@8.57.0): 6923 /eslint-plugin-react@7.34.1(eslint@8.57.0):
6687 resolution: {integrity: sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==} 6924 resolution: {integrity: sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==}
6688 engines: {node: '>=4'} 6925 engines: {node: '>=4'}
6689 peerDependencies: 6926 peerDependencies:
6690 eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 6927 eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^8.0.0
6691 dependencies: 6928 dependencies:
6692 array-includes: 3.1.7 6929 array-includes: 3.1.7
6693 array.prototype.findlast: 1.2.5 6930 array.prototype.findlast: 1.2.5
@@ -6754,7 +6991,7 @@ packages:
6754 resolution: {integrity: sha512-1Yzm7/m+0R4djH0tjDjfVei/ju2w3AzUGjG6q8JnuNIL5xIwsflyCooW5sfBvQp2pMYQFSWWCFONsjCax1EHng==} 6991 resolution: {integrity: sha512-1Yzm7/m+0R4djH0tjDjfVei/ju2w3AzUGjG6q8JnuNIL5xIwsflyCooW5sfBvQp2pMYQFSWWCFONsjCax1EHng==}
6755 engines: {node: '>=16'} 6992 engines: {node: '>=16'}
6756 peerDependencies: 6993 peerDependencies:
6757 eslint: '>=8.56.0' 6994 eslint: '>=8.56.0 || ^8.0.0'
6758 dependencies: 6995 dependencies:
6759 '@babel/helper-validator-identifier': 7.22.20 6996 '@babel/helper-validator-identifier': 7.22.20
6760 '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) 6997 '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
@@ -10105,6 +10342,10 @@ packages:
10105 engines: {node: '>= 8'} 10342 engines: {node: '>= 8'}
10106 dev: true 10343 dev: true
10107 10344
10345 /micro-memoize@4.1.2:
10346 resolution: {integrity: sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g==}
10347 dev: true
10348
10108 /micromatch@3.1.10: 10349 /micromatch@3.1.10:
10109 resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} 10350 resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==}
10110 engines: {node: '>=0.10.0'} 10351 engines: {node: '>=0.10.0'}
@@ -12591,6 +12832,11 @@ packages:
12591 resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} 12832 resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
12592 dev: true 12833 dev: true
12593 12834
12835 /short-unique-id@5.0.3:
12836 resolution: {integrity: sha512-yhniEILouC0s4lpH0h7rJsfylZdca10W9mDJRAFh3EpcSUanCHGb0R7kcFOIUCZYSAPo0PUD5ZxWQdW0T4xaug==}
12837 hasBin: true
12838 dev: true
12839
12594 /side-channel@1.0.4: 12840 /side-channel@1.0.4:
12595 resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} 12841 resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
12596 dependencies: 12842 dependencies:
@@ -12965,6 +13211,10 @@ packages:
12965 resolution: {integrity: sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==} 13211 resolution: {integrity: sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==}
12966 dev: true 13212 dev: true
12967 13213
13214 /string-ts@2.1.0:
13215 resolution: {integrity: sha512-YpGEBxS3Qw1De+RO3Gdrsx2gwYU9b7WmPtKhRLTTKc3oKzbOxqGDYLRGkNeIXLL4BGVZMXY49hPpzP3RAwUFAA==}
13216 dev: true
13217
12968 /string-width@2.1.1: 13218 /string-width@2.1.1:
12969 resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} 13219 resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==}
12970 engines: {node: '>=4'} 13220 engines: {node: '>=4'}
diff --git a/scripts/link-readme.ts b/scripts/link-readme.ts
index 147ae22f7..d323d83f6 100644
--- a/scripts/link-readme.ts
+++ b/scripts/link-readme.ts
@@ -9,6 +9,7 @@
9import path from 'node:path'; 9import path from 'node:path';
10import fs from 'fs-extra'; 10import fs from 'fs-extra';
11 11
12// eslint-disable-next-line no-console
12console.log('Linking issues and PRs in README.md'); 13console.log('Linking issues and PRs in README.md');
13 14
14const readmepath = path.join(__dirname, '..', 'README.md'); 15const readmepath = path.join(__dirname, '..', 'README.md');
@@ -60,4 +61,5 @@ readme = readme.replaceAll(/(?<!\[)@\w+(?!])/gi, match => {
60// Write to file 61// Write to file
61fs.writeFileSync(readmepath, readme); 62fs.writeFileSync(readmepath, readme);
62 63
64// eslint-disable-next-line no-console
63console.log(`Added ${replacements} strings`); 65console.log(`Added ${replacements} strings`);
diff --git a/src/I18n.tsx b/src/I18n.tsx
index 2085f3e98..dc9c7d6b9 100644
--- a/src/I18n.tsx
+++ b/src/I18n.tsx
@@ -27,7 +27,9 @@ class I18N extends Component<Props> {
27 27
28 return ( 28 return (
29 <IntlProvider 29 <IntlProvider
30 {...{ locale, key: locale, messages: translations[locale] }} 30 locale={locale}
31 key={locale}
32 messages={translations[locale]}
31 ref={intlProvider => { 33 ref={intlProvider => {
32 window['ferdium'].intl = intlProvider 34 window['ferdium'].intl = intlProvider
33 ? intlProvider.state.intl 35 ? intlProvider.state.intl
diff --git a/src/api/utils/auth.ts b/src/api/utils/auth.ts
index ce30e0132..0188675fc 100644
--- a/src/api/utils/auth.ts
+++ b/src/api/utils/auth.ts
@@ -39,6 +39,7 @@ export const prepareLocalToken = async (requestData: {
39 await when(() => !needsToken() || !!localServerToken(), { timeout: 2000 }); 39 await when(() => !needsToken() || !!localServerToken(), { timeout: 2000 });
40 const token = localServerToken(); 40 const token = localServerToken();
41 if (token) { 41 if (token) {
42 // eslint-disable-next-line no-param-reassign
42 requestData.headers['X-Ferdium-Local-Token'] = token; 43 requestData.headers['X-Ferdium-Local-Token'] = token;
43 } 44 }
44}; 45};
diff --git a/src/components/auth/AuthLayout.tsx b/src/components/auth/AuthLayout.tsx
index 67e898318..3952045b2 100644
--- a/src/components/auth/AuthLayout.tsx
+++ b/src/components/auth/AuthLayout.tsx
@@ -106,6 +106,7 @@ class AuthLayout extends Component<IProps, IState> {
106 )} 106 )}
107 <div className="auth__layout"> 107 <div className="auth__layout">
108 {/* Inject globalError into children */} 108 {/* Inject globalError into children */}
109 {/* eslint-disable-next-line @eslint-react/no-clone-element */}
109 {cloneElement(children, { error })} 110 {cloneElement(children, { error })}
110 </div> 111 </div>
111 {/* </div> */} 112 {/* </div> */}
diff --git a/src/components/downloadManager/DownloadManagerDashboard.tsx b/src/components/downloadManager/DownloadManagerDashboard.tsx
index 490be269d..aeaa94634 100644
--- a/src/components/downloadManager/DownloadManagerDashboard.tsx
+++ b/src/components/downloadManager/DownloadManagerDashboard.tsx
@@ -47,7 +47,6 @@ interface IState {
47 data: string; 47 data: string;
48} 48}
49 49
50// eslint-disable-next-line react/prefer-stateless-function
51class DownloadManagerDashboard extends Component<IProps, IState> { 50class DownloadManagerDashboard extends Component<IProps, IState> {
52 render() { 51 render() {
53 const { intl, stores, actions } = this.props; 52 const { intl, stores, actions } = this.props;
diff --git a/src/components/downloadManager/DownloadManagerLayout.tsx b/src/components/downloadManager/DownloadManagerLayout.tsx
index 08c0ace1e..43670355c 100644
--- a/src/components/downloadManager/DownloadManagerLayout.tsx
+++ b/src/components/downloadManager/DownloadManagerLayout.tsx
@@ -44,8 +44,8 @@ class DownloadManagerLayout extends Component<IProps> {
44 ); 44 );
45 } 45 }
46 46
47 handleKeyDown(e) { 47 handleKeyDown(e: KeyboardEvent) {
48 if (isEscKeyPress(e.keyCode)) { 48 if (isEscKeyPress(e.key)) {
49 this.props.actions!.ui.closeSettings(); 49 this.props.actions!.ui.closeSettings();
50 } 50 }
51 } 51 }
diff --git a/src/components/settings/SettingsLayout.tsx b/src/components/settings/SettingsLayout.tsx
index 17f8c3e33..a5fa13d71 100644
--- a/src/components/settings/SettingsLayout.tsx
+++ b/src/components/settings/SettingsLayout.tsx
@@ -41,7 +41,7 @@ class SettingsLayout extends Component<PropsWithChildren<IProps>> {
41 } 41 }
42 42
43 handleKeyDown(e: KeyboardEvent): void { 43 handleKeyDown(e: KeyboardEvent): void {
44 if (isEscKeyPress(e.keyCode)) { 44 if (isEscKeyPress(e.key)) {
45 this.props.closeSettings(); 45 this.props.closeSettings();
46 } 46 }
47 } 47 }
diff --git a/src/components/settings/releaseNotes/ReleaseNotesDashboard.tsx b/src/components/settings/releaseNotes/ReleaseNotesDashboard.tsx
index e874b4469..e2867ab8e 100644
--- a/src/components/settings/releaseNotes/ReleaseNotesDashboard.tsx
+++ b/src/components/settings/releaseNotes/ReleaseNotesDashboard.tsx
@@ -49,6 +49,7 @@ class ReleaseNotesDashboard extends Component<IProps, IState> {
49 intl, 49 intl,
50 ); 50 );
51 51
52 // eslint-disable-next-line @eslint-react/no-set-state-in-component-did-mount
52 this.setState({ 53 this.setState({
53 data, 54 data,
54 }); 55 });
diff --git a/src/components/settings/releaseNotes/ReleaseNotesLayout.tsx b/src/components/settings/releaseNotes/ReleaseNotesLayout.tsx
index 23db7141e..4fb31d053 100644
--- a/src/components/settings/releaseNotes/ReleaseNotesLayout.tsx
+++ b/src/components/settings/releaseNotes/ReleaseNotesLayout.tsx
@@ -43,8 +43,8 @@ class ReleaseNotesLayout extends Component<IProps> {
43 ); 43 );
44 } 44 }
45 45
46 handleKeyDown(e) { 46 handleKeyDown(e: KeyboardEvent) {
47 if (isEscKeyPress(e.keyCode)) { 47 if (isEscKeyPress(e.key)) {
48 this.props.actions!.ui.closeSettings(); 48 this.props.actions!.ui.closeSettings();
49 } 49 }
50 } 50 }
diff --git a/src/components/settings/settings/EditSettingsForm.tsx b/src/components/settings/settings/EditSettingsForm.tsx
index 84057091d..c3e8d46a0 100644
--- a/src/components/settings/settings/EditSettingsForm.tsx
+++ b/src/components/settings/settings/EditSettingsForm.tsx
@@ -1087,34 +1087,34 @@ class EditSettingsForm extends Component<IProps, IState> {
1087 <H3> 1087 <H3>
1088 {intl.formatMessage(messages.subheadlineFerdiumProfile)} 1088 {intl.formatMessage(messages.subheadlineFerdiumProfile)}
1089 </H3> 1089 </H3>
1090 <p> 1090
1091 <div className="settings__open-settings-file-container"> 1091 <div className="settings__open-settings-file-container">
1092 <Button 1092 <Button
1093 buttonType="secondary" 1093 buttonType="secondary"
1094 label={intl.formatMessage( 1094 label={intl.formatMessage(
1095 messages.buttonOpenFerdiumProfileFolder, 1095 messages.buttonOpenFerdiumProfileFolder,
1096 )} 1096 )}
1097 className="settings__open-settings-file-button" 1097 className="settings__open-settings-file-button"
1098 onClick={() => openPath(profileFolder)} 1098 onClick={() => openPath(profileFolder)}
1099 /> 1099 />
1100 <Button 1100 <Button
1101 buttonType="secondary" 1101 buttonType="secondary"
1102 label={intl.formatMessage( 1102 label={intl.formatMessage(
1103 messages.buttonOpenFerdiumServiceRecipesFolder, 1103 messages.buttonOpenFerdiumServiceRecipesFolder,
1104 )} 1104 )}
1105 className="settings__open-settings-file-button" 1105 className="settings__open-settings-file-button"
1106 onClick={() => openPath(recipeFolder)} 1106 onClick={() => openPath(recipeFolder)}
1107 /> 1107 />
1108 <Button 1108 <Button
1109 buttonType="secondary" 1109 buttonType="secondary"
1110 label={intl.formatMessage( 1110 label={intl.formatMessage(
1111 messages.buttonOpenImportExport, 1111 messages.buttonOpenImportExport,
1112 )} 1112 )}
1113 className="settings__open-settings-file-button" 1113 className="settings__open-settings-file-button"
1114 onClick={() => openExternalUrl(serverURL, true)} 1114 onClick={() => openExternalUrl(serverURL, true)}
1115 /> 1115 />
1116 </div> 1116 </div>
1117 </p> 1117
1118 <p className="settings__help"> 1118 <p className="settings__help">
1119 {intl.formatMessage(messages.serverHelp, { 1119 {intl.formatMessage(messages.serverHelp, {
1120 serverURL, 1120 serverURL,
diff --git a/src/components/settings/supportFerdium/SupportFerdiumDashboard.tsx b/src/components/settings/supportFerdium/SupportFerdiumDashboard.tsx
index 065690fb5..3a4592666 100644
--- a/src/components/settings/supportFerdium/SupportFerdiumDashboard.tsx
+++ b/src/components/settings/supportFerdium/SupportFerdiumDashboard.tsx
@@ -33,7 +33,7 @@ const SupportFerdiumDashboard = () => {
33 <a 33 <a
34 href="https://twitter.com/ferdiumteam/" 34 href="https://twitter.com/ferdiumteam/"
35 target="_blank" 35 target="_blank"
36 rel="noreferrer" 36 rel="noreferrer noopener"
37 > 37 >
38 <img 38 <img
39 alt="Twitter Follow" 39 alt="Twitter Follow"
@@ -43,14 +43,18 @@ const SupportFerdiumDashboard = () => {
43 <a 43 <a
44 href="https://github.com/ferdium/ferdium-app" 44 href="https://github.com/ferdium/ferdium-app"
45 target="_blank" 45 target="_blank"
46 rel="noreferrer" 46 rel="noreferrer noopener"
47 > 47 >
48 <img 48 <img
49 alt="GitHub Stars" 49 alt="GitHub Stars"
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} rel="noreferrer"> 53 <a
54 target="_blank"
55 href={FERDIUM_TRANSLATION}
56 rel="noreferrer noopener"
57 >
54 <img 58 <img
55 src="https://badges.crowdin.net/ferdium-app/localized.svg" 59 src="https://badges.crowdin.net/ferdium-app/localized.svg"
56 alt="Crowdin" 60 alt="Crowdin"
@@ -59,7 +63,7 @@ const SupportFerdiumDashboard = () => {
59 <a 63 <a
60 href="https://opencollective.com/ferdium#section-contributors" 64 href="https://opencollective.com/ferdium#section-contributors"
61 target="_blank" 65 target="_blank"
62 rel="noreferrer" 66 rel="noreferrer noopener"
63 > 67 >
64 <img 68 <img
65 alt="Open Collective backers" 69 alt="Open Collective backers"
@@ -72,7 +76,7 @@ const SupportFerdiumDashboard = () => {
72 <a 76 <a
73 href="https://github.com/ferdium/ferdium-app#contributors-" 77 href="https://github.com/ferdium/ferdium-app#contributors-"
74 target="_blank" 78 target="_blank"
75 rel="noreferrer" 79 rel="noreferrer noopener"
76 > 80 >
77 <img 81 <img
78 alt="GitHub contributors (non-exhaustive)" 82 alt="GitHub contributors (non-exhaustive)"
diff --git a/src/components/ui/FAB.tsx b/src/components/ui/FAB.tsx
index b4eeace8b..1e9ff9022 100644
--- a/src/components/ui/FAB.tsx
+++ b/src/components/ui/FAB.tsx
@@ -36,6 +36,7 @@ class Button extends Component<IProps> {
36 }; 36 };
37 37
38 return ( 38 return (
39 // eslint-disable-next-line @eslint-react/dom/no-missing-button-type
39 <button {...buttonProps} type="button"> 40 <button {...buttonProps} type="button">
40 {children} 41 {children}
41 </button> 42 </button>
diff --git a/src/components/ui/SearchInput.tsx b/src/components/ui/SearchInput.tsx
index 2e70d1b35..d31463010 100644
--- a/src/components/ui/SearchInput.tsx
+++ b/src/components/ui/SearchInput.tsx
@@ -98,6 +98,7 @@ class SearchInput extends Component<IProps, IState> {
98 /> 98 />
99 </label> 99 </label>
100 {value.length > 0 && ( 100 {value.length > 0 && (
101 // eslint-disable-next-line jsx-a11y/no-static-element-interactions
101 <span onClick={() => this.reset()} onKeyDown={noop}> 102 <span onClick={() => this.reset()} onKeyDown={noop}>
102 <Icon icon={mdiCloseCircleOutline} /> 103 <Icon icon={mdiCloseCircleOutline} />
103 </span> 104 </span>
diff --git a/src/components/ui/Tabs/Tabs.tsx b/src/components/ui/Tabs/Tabs.tsx
index a5ec148aa..d1e397122 100644
--- a/src/components/ui/Tabs/Tabs.tsx
+++ b/src/components/ui/Tabs/Tabs.tsx
@@ -35,6 +35,7 @@ class Tab extends Component<IProps, IState> {
35 35
36 render(): ReactElement { 36 render(): ReactElement {
37 const { children: childElements } = this.props; 37 const { children: childElements } = this.props;
38 // eslint-disable-next-line @eslint-react/no-children-to-array
38 const children = Children.toArray(childElements); // removes all null values 39 const children = Children.toArray(childElements); // removes all null values
39 40
40 if (children.length === 1) { 41 if (children.length === 1) {
@@ -44,9 +45,10 @@ class Tab extends Component<IProps, IState> {
44 return ( 45 return (
45 <div className="content-tabs"> 46 <div className="content-tabs">
46 <div className="content-tabs__tabs"> 47 <div className="content-tabs__tabs">
48 {/* eslint-disable-next-line @eslint-react/no-children-map */}
47 {Children.map(children, (child, i) => ( 49 {Children.map(children, (child, i) => (
48 <button 50 <button
49 // eslint-disable-next-line react/no-array-index-key 51 // eslint-disable-next-line react/no-array-index-key, @eslint-react/no-array-index-key
50 key={i} 52 key={i}
51 className={classnames({ 53 className={classnames({
52 'content-tabs__item': true, 54 'content-tabs__item': true,
@@ -60,9 +62,10 @@ class Tab extends Component<IProps, IState> {
60 ))} 62 ))}
61 </div> 63 </div>
62 <div className="content-tabs__content"> 64 <div className="content-tabs__content">
65 {/* eslint-disable-next-line @eslint-react/no-children-map */}
63 {Children.map(children, (child, i) => ( 66 {Children.map(children, (child, i) => (
64 <div 67 <div
65 // eslint-disable-next-line react/no-array-index-key 68 // eslint-disable-next-line react/no-array-index-key, @eslint-react/no-array-index-key
66 key={i} 69 key={i}
67 className={classnames({ 70 className={classnames({
68 'content-tabs__item': true, 71 'content-tabs__item': true,
diff --git a/src/components/ui/button/index.tsx b/src/components/ui/button/index.tsx
index 5c606f274..ba4353dae 100644
--- a/src/components/ui/button/index.tsx
+++ b/src/components/ui/button/index.tsx
@@ -223,7 +223,7 @@ class ButtonComponent extends Component<IProps, IState> {
223 ) : ( 223 ) : (
224 <button 224 <button
225 id={id} 225 id={id}
226 // eslint-disable-next-line react/button-has-type 226 // eslint-disable-next-line react/button-has-type, @eslint-react/dom/no-missing-button-type
227 type={type} 227 type={type}
228 onClick={onClick} 228 onClick={onClick}
229 className={classnames({ 229 className={classnames({
diff --git a/src/components/ui/imageUpload/index.tsx b/src/components/ui/imageUpload/index.tsx
index 876572484..092271ab0 100644
--- a/src/components/ui/imageUpload/index.tsx
+++ b/src/components/ui/imageUpload/index.tsx
@@ -129,7 +129,9 @@ class ImageUpload extends Component<IProps, IState> {
129 </> 129 </>
130 ) : ( 130 ) : (
131 <Dropzone 131 <Dropzone
132 // eslint-disable-next-line react/jsx-no-bind
132 onDropAccepted={this.onDropAccepted.bind(this)} 133 onDropAccepted={this.onDropAccepted.bind(this)}
134 // eslint-disable-next-line react/jsx-no-bind
133 onDropRejected={this.onDropRejected.bind(this)} 135 onDropRejected={this.onDropRejected.bind(this)}
134 multiple={multiple} 136 multiple={multiple}
135 accept={{ 137 accept={{
diff --git a/src/components/ui/input/index.tsx b/src/components/ui/input/index.tsx
index c61efe570..225517ba8 100644
--- a/src/components/ui/input/index.tsx
+++ b/src/components/ui/input/index.tsx
@@ -172,7 +172,7 @@ class Input extends Component<IProps, IState> {
172 onFocus={onFocus} 172 onFocus={onFocus}
173 onBlur={onBlur} 173 onBlur={onBlur}
174 disabled={disabled} 174 disabled={disabled}
175 onKeyPress={this.onInputKeyPress.bind(this)} 175 onKeyUp={this.onInputKeyPress.bind(this)}
176 min={min} 176 min={min}
177 max={max} 177 max={max}
178 step={step} 178 step={step}
diff --git a/src/components/ui/select/index.tsx b/src/components/ui/select/index.tsx
index 2716ebc2d..397fd97ed 100644
--- a/src/components/ui/select/index.tsx
+++ b/src/components/ui/select/index.tsx
@@ -197,6 +197,7 @@ class SelectComponent extends Component<IProps, IState> {
197 this.arrowKeysHandler = this.arrowKeysHandler.bind(this); 197 this.arrowKeysHandler = this.arrowKeysHandler.bind(this);
198 } 198 }
199 199
200 // eslint-disable-next-line @eslint-react/no-unsafe-component-will-mount
200 UNSAFE_componentWillMount(): void { 201 UNSAFE_componentWillMount(): void {
201 const { value } = this.props; 202 const { value } = this.props;
202 203
@@ -417,6 +418,7 @@ class SelectComponent extends Component<IProps, IState> {
417 ref={this.scrollContainerRef} 418 ref={this.scrollContainerRef}
418 > 419 >
419 {Object.keys(options!).map((key, i) => ( 420 {Object.keys(options!).map((key, i) => (
421 // eslint-disable-next-line jsx-a11y/no-static-element-interactions
420 <div 422 <div
421 key={key} 423 key={key}
422 onClick={() => this.select(key)} 424 onClick={() => this.select(key)}
diff --git a/src/components/ui/textarea/index.tsx b/src/components/ui/textarea/index.tsx
index 4a0e77afe..e332f7a47 100644
--- a/src/components/ui/textarea/index.tsx
+++ b/src/components/ui/textarea/index.tsx
@@ -40,10 +40,9 @@ class TextareaComponent extends Component<IProps> {
40 const { data } = this.props; 40 const { data } = this.props;
41 41
42 if (this.textareaRef?.current && data) { 42 if (this.textareaRef?.current && data) {
43 Object.keys(data).map( 43 Object.keys(data).forEach(key => {
44 // biome-ignore lint/suspicious/noAssignInExpressions: <explanation> 44 this.textareaRef.current!.dataset[key] = data[key];
45 key => (this.textareaRef.current!.dataset[key] = data[key]), 45 });
46 );
47 } 46 }
48 } 47 }
49 48
diff --git a/src/containers/auth/AuthReleaseNotesScreen.tsx b/src/containers/auth/AuthReleaseNotesScreen.tsx
index 3191ba139..eac537ad6 100644
--- a/src/containers/auth/AuthReleaseNotesScreen.tsx
+++ b/src/containers/auth/AuthReleaseNotesScreen.tsx
@@ -43,6 +43,7 @@ class AuthReleaseNotesScreen extends Component<IProps, IState> {
43 intl, 43 intl,
44 ); 44 );
45 45
46 // eslint-disable-next-line @eslint-react/no-set-state-in-component-did-mount
46 this.setState({ 47 this.setState({
47 data, 48 data,
48 }); 49 });
diff --git a/src/containers/download-manager/DownloadManagerScreen.tsx b/src/containers/download-manager/DownloadManagerScreen.tsx
index cd9686f4d..3413be37a 100644
--- a/src/containers/download-manager/DownloadManagerScreen.tsx
+++ b/src/containers/download-manager/DownloadManagerScreen.tsx
@@ -1,15 +1,12 @@
1import { Component, type ReactElement } from 'react';
2import DownloadManager from '../../components/downloadManager/DownloadManagerDashboard'; 1import DownloadManager from '../../components/downloadManager/DownloadManagerDashboard';
3import ErrorBoundary from '../../components/util/ErrorBoundary'; 2import ErrorBoundary from '../../components/util/ErrorBoundary';
4 3
5class DownloadManagerScreen extends Component { 4const DownloadManagerScreen = ({ ...props }) => {
6 render(): ReactElement { 5 return (
7 return ( 6 <ErrorBoundary>
8 <ErrorBoundary> 7 <DownloadManager {...props} />
9 <DownloadManager {...this.props} /> 8 </ErrorBoundary>
10 </ErrorBoundary> 9 );
11 ); 10};
12 }
13}
14 11
15export default DownloadManagerScreen; 12export default DownloadManagerScreen;
diff --git a/src/containers/settings/EditServiceScreen.tsx b/src/containers/settings/EditServiceScreen.tsx
index dde69ef2d..f3b9b0857 100644
--- a/src/containers/settings/EditServiceScreen.tsx
+++ b/src/containers/settings/EditServiceScreen.tsx
@@ -141,13 +141,17 @@ class EditServiceScreen extends Component<IProps> {
141 const { action } = this.props.params; 141 const { action } = this.props.params;
142 const { recipes, services } = this.props.stores; 142 const { recipes, services } = this.props.stores;
143 const { createService, updateService } = this.props.actions.service; 143 const { createService, updateService } = this.props.actions.service;
144 // eslint-disable-next-line no-param-reassign
144 data.darkReaderSettings = { 145 data.darkReaderSettings = {
145 brightness: data.darkReaderBrightness, 146 brightness: data.darkReaderBrightness,
146 contrast: data.darkReaderContrast, 147 contrast: data.darkReaderContrast,
147 sepia: data.darkReaderSepia, 148 sepia: data.darkReaderSepia,
148 }; 149 };
150 // eslint-disable-next-line no-param-reassign
149 delete data.darkReaderContrast; 151 delete data.darkReaderContrast;
152 // eslint-disable-next-line no-param-reassign
150 delete data.darkReaderBrightness; 153 delete data.darkReaderBrightness;
154 // eslint-disable-next-line no-param-reassign
151 delete data.darkReaderSepia; 155 delete data.darkReaderSepia;
152 156
153 const serviceData = data; 157 const serviceData = data;
diff --git a/src/containers/settings/ReleaseNotesScreen.tsx b/src/containers/settings/ReleaseNotesScreen.tsx
index 482364817..3a7b8d0e9 100644
--- a/src/containers/settings/ReleaseNotesScreen.tsx
+++ b/src/containers/settings/ReleaseNotesScreen.tsx
@@ -1,16 +1,12 @@
1import { Component, type ReactElement } from 'react';
2
3import ReleaseNotes from '../../components/settings/releaseNotes/ReleaseNotesDashboard'; 1import ReleaseNotes from '../../components/settings/releaseNotes/ReleaseNotesDashboard';
4import ErrorBoundary from '../../components/util/ErrorBoundary'; 2import ErrorBoundary from '../../components/util/ErrorBoundary';
5 3
6class ReleaseNotesScreen extends Component { 4const ReleaseNotesScreen = () => {
7 render(): ReactElement { 5 return (
8 return ( 6 <ErrorBoundary>
9 <ErrorBoundary> 7 <ReleaseNotes />
10 <ReleaseNotes /> 8 </ErrorBoundary>
11 </ErrorBoundary> 9 );
12 ); 10};
13 }
14}
15 11
16export default ReleaseNotesScreen; 12export default ReleaseNotesScreen;
diff --git a/src/containers/settings/SupportScreen.tsx b/src/containers/settings/SupportScreen.tsx
index 4c50869bb..3fdb0b4df 100644
--- a/src/containers/settings/SupportScreen.tsx
+++ b/src/containers/settings/SupportScreen.tsx
@@ -1,16 +1,12 @@
1import { Component, type ReactElement } from 'react';
2
3import SupportFerdium from '../../components/settings/supportFerdium/SupportFerdiumDashboard'; 1import SupportFerdium from '../../components/settings/supportFerdium/SupportFerdiumDashboard';
4import ErrorBoundary from '../../components/util/ErrorBoundary'; 2import ErrorBoundary from '../../components/util/ErrorBoundary';
5 3
6class SupportScreen extends Component { 4const SupportScreen = () => {
7 render(): ReactElement { 5 return (
8 return ( 6 <ErrorBoundary>
9 <ErrorBoundary> 7 <SupportFerdium />
10 <SupportFerdium /> 8 </ErrorBoundary>
11 </ErrorBoundary> 9 );
12 ); 10};
13 }
14}
15 11
16export default SupportScreen; 12export default SupportScreen;
diff --git a/src/electron/ipc-api/autoUpdate.ts b/src/electron/ipc-api/autoUpdate.ts
index 775daf602..44e2a1b19 100644
--- a/src/electron/ipc-api/autoUpdate.ts
+++ b/src/electron/ipc-api/autoUpdate.ts
@@ -1,5 +1,6 @@
1import { BrowserWindow, ipcMain } from 'electron'; 1import { BrowserWindow, ipcMain } from 'electron';
2import { autoUpdater } from 'electron-updater'; 2import { autoUpdater } from 'electron-updater';
3// eslint-disable-next-line import/no-cycle
3import { appEvents } from '../..'; 4import { appEvents } from '../..';
4 5
5const debug = require('../../preload-safe-debug')('Ferdium:ipcApi:autoUpdate'); 6const debug = require('../../preload-safe-debug')('Ferdium:ipcApi:autoUpdate');
diff --git a/src/electron/ipc-api/index.ts b/src/electron/ipc-api/index.ts
index 48c6d142c..83cc5eae2 100644
--- a/src/electron/ipc-api/index.ts
+++ b/src/electron/ipc-api/index.ts
@@ -1,6 +1,7 @@
1import type { BrowserWindow } from 'electron'; 1import type { BrowserWindow } from 'electron';
2import type TrayIcon from '../../lib/Tray'; 2import type TrayIcon from '../../lib/Tray';
3import appIndicator from './appIndicator'; 3import appIndicator from './appIndicator';
4// eslint-disable-next-line import/no-cycle
4import autoUpdate from './autoUpdate'; 5import autoUpdate from './autoUpdate';
5import dnd from './dnd'; 6import dnd from './dnd';
6import download from './download'; 7import download from './download';
diff --git a/src/electron/macOSPermissions.ts b/src/electron/macOSPermissions.ts
index 90f0f4028..a3bbbbe19 100644
--- a/src/electron/macOSPermissions.ts
+++ b/src/electron/macOSPermissions.ts
@@ -2,7 +2,7 @@ import { dirname } from 'node:path';
2import { type BrowserWindow, dialog, systemPreferences } from 'electron'; 2import { type BrowserWindow, dialog, systemPreferences } from 'electron';
3import { mkdirSync, pathExistsSync, writeFileSync } from 'fs-extra'; 3import { mkdirSync, pathExistsSync, writeFileSync } from 'fs-extra';
4import macosVersion from 'macos-version'; 4import macosVersion from 'macos-version';
5// eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error 5// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
6// @ts-ignore 6// @ts-ignore
7import { askForScreenCaptureAccess } from 'node-mac-permissions'; 7import { askForScreenCaptureAccess } from 'node-mac-permissions';
8import { userDataPath } from '../environment-remote'; 8import { userDataPath } from '../environment-remote';
diff --git a/src/features/appearance/index.ts b/src/features/appearance/index.ts
index 049080505..9b7715a23 100644
--- a/src/features/appearance/index.ts
+++ b/src/features/appearance/index.ts
@@ -46,6 +46,7 @@ function generateAccentStyle(accentColorStr) {
46 try { 46 try {
47 accentColor = color(accentColorStr); 47 accentColor = color(accentColorStr);
48 } catch { 48 } catch {
49 // eslint-disable-next-line no-param-reassign
49 accentColorStr = DEFAULT_APP_SETTINGS.accentColor; 50 accentColorStr = DEFAULT_APP_SETTINGS.accentColor;
50 accentColor = color(accentColorStr); 51 accentColor = color(accentColorStr);
51 } 52 }
diff --git a/src/features/basicAuth/Component.tsx b/src/features/basicAuth/Component.tsx
index 7c901344d..bae38443a 100644
--- a/src/features/basicAuth/Component.tsx
+++ b/src/features/basicAuth/Component.tsx
@@ -61,6 +61,7 @@ class BasicAuthModal extends Component<IProps> {
61 <Modal 61 <Modal
62 isOpen={isModalVisible} 62 isOpen={isModalVisible}
63 className={classes.modal} 63 className={classes.modal}
64 // eslint-disable-next-line react/jsx-no-bind
64 close={this.cancel.bind(this)} 65 close={this.cancel.bind(this)}
65 showClose={false} 66 showClose={false}
66 > 67 >
@@ -86,6 +87,7 @@ class BasicAuthModal extends Component<IProps> {
86 type="button" 87 type="button"
87 label={intl.formatMessage(globalMessages.cancel)} 88 label={intl.formatMessage(globalMessages.cancel)}
88 buttonType="secondary" 89 buttonType="secondary"
90 // eslint-disable-next-line react/jsx-no-bind
89 onClick={this.cancel.bind(this)} 91 onClick={this.cancel.bind(this)}
90 /> 92 />
91 <Button 93 <Button
diff --git a/src/features/communityRecipes/store.ts b/src/features/communityRecipes/store.ts
index 1c21908e2..548867528 100644
--- a/src/features/communityRecipes/store.ts
+++ b/src/features/communityRecipes/store.ts
@@ -27,6 +27,7 @@ export class CommunityRecipesStore extends FeatureStore {
27 return this.stores.recipePreviews.dev.map( 27 return this.stores.recipePreviews.dev.map(
28 (recipePreview: { isDevRecipe: boolean; author: any[] }) => { 28 (recipePreview: { isDevRecipe: boolean; author: any[] }) => {
29 // TODO: Need to figure out if this is even necessary/used 29 // TODO: Need to figure out if this is even necessary/used
30 // eslint-disable-next-line no-param-reassign
30 recipePreview.isDevRecipe = !!recipePreview.author.some( 31 recipePreview.isDevRecipe = !!recipePreview.author.some(
31 (author: { email: string }) => 32 (author: { email: string }) =>
32 author.email === this.stores.user.data.email, 33 author.email === this.stores.user.data.email,
diff --git a/src/features/quickSwitch/Component.tsx b/src/features/quickSwitch/Component.tsx
index 4a48b1e6c..3a7477f62 100644
--- a/src/features/quickSwitch/Component.tsx
+++ b/src/features/quickSwitch/Component.tsx
@@ -302,6 +302,7 @@ class QuickSwitchModal extends Component<IProps, IState> {
302 isOpen={isModalVisible} 302 isOpen={isModalVisible}
303 className={`${classes.modal} quick-switch`} 303 className={`${classes.modal} quick-switch`}
304 shouldCloseOnOverlayClick 304 shouldCloseOnOverlayClick
305 // eslint-disable-next-line react/jsx-no-bind
305 close={this.close.bind(this)} 306 close={this.close.bind(this)}
306 > 307 >
307 <H1 className={classes.headline}> 308 <H1 className={classes.headline}>
@@ -318,6 +319,7 @@ class QuickSwitchModal extends Component<IProps, IState> {
318 319
319 <div className={classes.services}> 320 <div className={classes.services}>
320 {services.map((service, index) => ( 321 {services.map((service, index) => (
322 // eslint-disable-next-line jsx-a11y/no-static-element-interactions
321 <div 323 <div
322 className={`${classes.service} ${ 324 className={`${classes.service} ${
323 this.state.selected === index 325 this.state.selected === index
diff --git a/src/features/todos/actions.ts b/src/features/todos/actions.ts
index c2000752f..27c7e489b 100644
--- a/src/features/todos/actions.ts
+++ b/src/features/todos/actions.ts
@@ -36,6 +36,7 @@ export const todoActions = createActionsFromDefinitions<TodoActionsType>(
36 channel: PropTypes.string.isRequired, 36 channel: PropTypes.string.isRequired,
37 message: PropTypes.shape({ 37 message: PropTypes.shape({
38 action: PropTypes.string.isRequired, 38 action: PropTypes.string.isRequired,
39 // eslint-disable-next-line react/forbid-prop-types
39 data: PropTypes.object, 40 data: PropTypes.object,
40 }), 41 }),
41 }, 42 },
diff --git a/src/features/todos/components/TodosWebview.tsx b/src/features/todos/components/TodosWebview.tsx
index f9493d519..544768bbf 100644
--- a/src/features/todos/components/TodosWebview.tsx
+++ b/src/features/todos/components/TodosWebview.tsx
@@ -92,6 +92,7 @@ class TodosWebview extends Component<IProps, IState> {
92 } 92 }
93 93
94 componentDidMount() { 94 componentDidMount() {
95 // eslint-disable-next-line @eslint-react/no-set-state-in-component-did-mount
95 this.setState({ 96 this.setState({
96 width: this.props.width, 97 width: this.props.width,
97 }); 98 });
@@ -173,6 +174,7 @@ class TodosWebview extends Component<IProps, IState> {
173 } 174 }
174 175
175 return ( 176 return (
177 // eslint-disable-next-line jsx-a11y/no-static-element-interactions
176 <div 178 <div
177 className={classnames({ 179 className={classnames({
178 [classes.root]: true, 180 [classes.root]: true,
@@ -185,6 +187,7 @@ class TodosWebview extends Component<IProps, IState> {
185 ref={this.node} 187 ref={this.node}
186 id="todos-panel" 188 id="todos-panel"
187 > 189 >
190 {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
188 <div 191 <div
189 className={classes.resizeHandler} 192 className={classes.resizeHandler}
190 style={{ 193 style={{
diff --git a/src/features/todos/index.ts b/src/features/todos/index.ts
index 2fa8c3130..5465ed48a 100644
--- a/src/features/todos/index.ts
+++ b/src/features/todos/index.ts
@@ -3,6 +3,7 @@ import TodoStore from './store';
3export const todosStore = new TodoStore(); 3export const todosStore = new TodoStore();
4 4
5export default function initTodos(stores: { todos?: any }, actions: any) { 5export default function initTodos(stores: { todos?: any }, actions: any) {
6 // eslint-disable-next-line no-param-reassign
6 stores.todos = todosStore; 7 stores.todos = todosStore;
7 todosStore.start(stores, actions); 8 todosStore.start(stores, actions);
8} 9}
diff --git a/src/features/webControls/containers/WebControlsScreen.tsx b/src/features/webControls/containers/WebControlsScreen.tsx
index b492264bf..8709fcba5 100644
--- a/src/features/webControls/containers/WebControlsScreen.tsx
+++ b/src/features/webControls/containers/WebControlsScreen.tsx
@@ -118,8 +118,10 @@ class WebControlsScreen extends Component<IProps> {
118 } 118 }
119 119
120 try { 120 try {
121 // eslint-disable-next-line no-param-reassign
121 url = new URL(url).toString(); 122 url = new URL(url).toString();
122 } catch { 123 } catch {
124 // eslint-disable-next-line no-param-reassign
123 url = 125 url =
124 /^((?!-))(xn--)?[\da-z][\d_a-z-]{0,61}[\da-z]{0,1}\.(xn--)?([\da-z-]{1,61}|[\da-z-]{1,30}\.[a-z]{2,})$/.test( 126 /^((?!-))(xn--)?[\da-z][\d_a-z-]{0,61}[\da-z]{0,1}\.(xn--)?([\da-z-]{1,61}|[\da-z-]{1,30}\.[a-z]{2,})$/.test(
125 url, 127 url,
diff --git a/src/features/workspaces/components/CreateWorkspaceForm.tsx b/src/features/workspaces/components/CreateWorkspaceForm.tsx
index 0c365564a..b35ffe4d8 100644
--- a/src/features/workspaces/components/CreateWorkspaceForm.tsx
+++ b/src/features/workspaces/components/CreateWorkspaceForm.tsx
@@ -81,6 +81,7 @@ class CreateWorkspaceForm extends Component<IProps> {
81 className={classes.input} 81 className={classes.input}
82 showLabel={false} 82 showLabel={false}
83 // @ts-expect-error Expected 1 arguments, but got 2. 83 // @ts-expect-error Expected 1 arguments, but got 2.
84 // eslint-disable-next-line react/jsx-no-bind
84 onEnterKey={this.submitForm.bind(this, form)} 85 onEnterKey={this.submitForm.bind(this, form)}
85 focus={workspaceStore.isUserAllowedToUseFeature} 86 focus={workspaceStore.isUserAllowedToUseFeature}
86 /> 87 />
@@ -89,6 +90,7 @@ class CreateWorkspaceForm extends Component<IProps> {
89 type="submit" 90 type="submit"
90 label={intl.formatMessage(messages.submitButton)} 91 label={intl.formatMessage(messages.submitButton)}
91 // @ts-expect-error Expected 1 arguments, but got 2. 92 // @ts-expect-error Expected 1 arguments, but got 2.
93 // eslint-disable-next-line react/jsx-no-bind
92 onClick={this.submitForm.bind(this, form)} 94 onClick={this.submitForm.bind(this, form)}
93 busy={isSubmitting} 95 busy={isSubmitting}
94 buttonType={isSubmitting ? 'secondary' : 'primary'} 96 buttonType={isSubmitting ? 'secondary' : 'primary'}
diff --git a/src/features/workspaces/components/EditWorkspaceForm.tsx b/src/features/workspaces/components/EditWorkspaceForm.tsx
index 18e7c251e..cc7a2b19b 100644
--- a/src/features/workspaces/components/EditWorkspaceForm.tsx
+++ b/src/features/workspaces/components/EditWorkspaceForm.tsx
@@ -92,6 +92,7 @@ class EditWorkspaceForm extends Component<IProps> {
92 this.form = this.prepareWorkspaceForm(this.props.workspace); 92 this.form = this.prepareWorkspaceForm(this.props.workspace);
93 } 93 }
94 94
95 // eslint-disable-next-line @eslint-react/no-unsafe-component-will-receive-props
95 UNSAFE_componentWillReceiveProps(nextProps): void { 96 UNSAFE_componentWillReceiveProps(nextProps): void {
96 const { workspace } = this.props; 97 const { workspace } = this.props;
97 if (workspace.id !== nextProps.workspace.id) { 98 if (workspace.id !== nextProps.workspace.id) {
@@ -178,11 +179,11 @@ class EditWorkspaceForm extends Component<IProps> {
178 <span className="settings__header-item">{workspace.name}</span> 179 <span className="settings__header-item">{workspace.name}</span>
179 </div> 180 </div>
180 <div className="settings__body"> 181 <div className="settings__body">
181 {updateWorkspaceRequest.error && ( 182 {updateWorkspaceRequest.error ? (
182 <Infobox icon="alert" type="danger"> 183 <Infobox icon="alert" type="danger">
183 Error while saving workspace 184 Error while saving workspace
184 </Infobox> 185 </Infobox>
185 )} 186 ) : null}
186 <div className={classes.nameInput}> 187 <div className={classes.nameInput}>
187 <Input {...form.$('name').bind()} /> 188 <Input {...form.$('name').bind()} />
188 <Toggle {...form.$('keepLoaded').bind()} /> 189 <Toggle {...form.$('keepLoaded').bind()} />
@@ -228,6 +229,7 @@ class EditWorkspaceForm extends Component<IProps> {
228 buttonType={isDeleting ? 'secondary' : 'danger'} 229 buttonType={isDeleting ? 'secondary' : 'danger'}
229 className="settings__delete-button" 230 className="settings__delete-button"
230 disabled={isDeleting} 231 disabled={isDeleting}
232 // eslint-disable-next-line react/jsx-no-bind
231 onClick={this.delete.bind(this)} 233 onClick={this.delete.bind(this)}
232 /> 234 />
233 {/* ===== Save Button ===== */} 235 {/* ===== Save Button ===== */}
@@ -237,6 +239,7 @@ class EditWorkspaceForm extends Component<IProps> {
237 busy={isSaving} 239 busy={isSaving}
238 className="franz-form__button" 240 className="franz-form__button"
239 buttonType={isSaving ? 'secondary' : 'primary'} 241 buttonType={isSaving ? 'secondary' : 'primary'}
242 // eslint-disable-next-line react/jsx-no-bind
240 onClick={this.save.bind(this, form)} 243 onClick={this.save.bind(this, form)}
241 // TODO: Need to disable if no services have been added to this workspace 244 // TODO: Need to disable if no services have been added to this workspace
242 disabled={isSaving} 245 disabled={isSaving}
diff --git a/src/features/workspaces/components/WorkspaceDrawer.tsx b/src/features/workspaces/components/WorkspaceDrawer.tsx
index cce333b31..e92bc4b60 100644
--- a/src/features/workspaces/components/WorkspaceDrawer.tsx
+++ b/src/features/workspaces/components/WorkspaceDrawer.tsx
@@ -129,6 +129,7 @@ class WorkspaceDrawer extends Component<IProps> {
129 <div className={`${classes.drawer} workspaces-drawer`}> 129 <div className={`${classes.drawer} workspaces-drawer`}>
130 <H1 className={classes.headline}> 130 <H1 className={classes.headline}>
131 {intl.formatMessage(messages.headline)} 131 {intl.formatMessage(messages.headline)}
132 {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
132 <span 133 <span
133 className={classes.workspacesSettingsButton} 134 className={classes.workspacesSettingsButton}
134 onKeyDown={noop} 135 onKeyDown={noop}
@@ -179,6 +180,7 @@ class WorkspaceDrawer extends Component<IProps> {
179 shortcutIndex={index + 1} 180 shortcutIndex={index + 1}
180 /> 181 />
181 ))} 182 ))}
183 {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
182 <div 184 <div
183 className={classes.addNewWorkspaceLabel} 185 className={classes.addNewWorkspaceLabel}
184 onClick={() => { 186 onClick={() => {
diff --git a/src/features/workspaces/components/WorkspaceDrawerItem.tsx b/src/features/workspaces/components/WorkspaceDrawerItem.tsx
index 1e4b57dba..01a18ffb0 100644
--- a/src/features/workspaces/components/WorkspaceDrawerItem.tsx
+++ b/src/features/workspaces/components/WorkspaceDrawerItem.tsx
@@ -111,6 +111,7 @@ class WorkspaceDrawerItem extends Component<IProps> {
111 const contextMenu = Menu.buildFromTemplate(contextMenuTemplate); 111 const contextMenu = Menu.buildFromTemplate(contextMenuTemplate);
112 112
113 return ( 113 return (
114 // eslint-disable-next-line jsx-a11y/no-static-element-interactions
114 <div 115 <div
115 className={classnames([ 116 className={classnames([
116 classes.item, 117 classes.item,
diff --git a/src/features/workspaces/components/WorkspaceServiceListItem.tsx b/src/features/workspaces/components/WorkspaceServiceListItem.tsx
index 6f61f8a51..a56e5802f 100644
--- a/src/features/workspaces/components/WorkspaceServiceListItem.tsx
+++ b/src/features/workspaces/components/WorkspaceServiceListItem.tsx
@@ -42,6 +42,7 @@ class WorkspaceServiceListItem extends Component<IProps> {
42 const { classes, isInWorkspace, onToggle, service } = this.props; 42 const { classes, isInWorkspace, onToggle, service } = this.props;
43 return ( 43 return (
44 // onclick in below div used to fix bug raised under toggle duplicate component removal 44 // onclick in below div used to fix bug raised under toggle duplicate component removal
45 // eslint-disable-next-line jsx-a11y/no-static-element-interactions
45 <div className={classes.listItem} onClick={onToggle} onKeyDown={noop}> 46 <div className={classes.listItem} onClick={onToggle} onKeyDown={noop}>
46 <ServiceIcon className={classes.serviceIcon} service={service} /> 47 <ServiceIcon className={classes.serviceIcon} service={service} />
47 <span 48 <span
diff --git a/src/features/workspaces/components/WorkspacesDashboard.tsx b/src/features/workspaces/components/WorkspacesDashboard.tsx
index 8fb2cf923..ad54c6682 100644
--- a/src/features/workspaces/components/WorkspacesDashboard.tsx
+++ b/src/features/workspaces/components/WorkspacesDashboard.tsx
@@ -105,33 +105,33 @@ class WorkspacesDashboard extends Component<IProps> {
105 <div className="settings__body"> 105 <div className="settings__body">
106 {/* ===== Workspace updated info ===== */} 106 {/* ===== Workspace updated info ===== */}
107 {updateWorkspaceRequest.wasExecuted && 107 {updateWorkspaceRequest.wasExecuted &&
108 updateWorkspaceRequest.result && ( 108 updateWorkspaceRequest.result ? (
109 <Appear className={classes.appear}> 109 <Appear className={classes.appear}>
110 <Infobox 110 <Infobox
111 type="success" 111 type="success"
112 icon="checkbox-marked-circle-outline" 112 icon="checkbox-marked-circle-outline"
113 dismissible 113 dismissible
114 onUnmount={updateWorkspaceRequest.reset} 114 onUnmount={updateWorkspaceRequest.reset}
115 > 115 >
116 {intl.formatMessage(messages.updatedInfo)} 116 {intl.formatMessage(messages.updatedInfo)}
117 </Infobox> 117 </Infobox>
118 </Appear> 118 </Appear>
119 )} 119 ) : null}
120 120
121 {/* ===== Workspace deleted info ===== */} 121 {/* ===== Workspace deleted info ===== */}
122 {deleteWorkspaceRequest.wasExecuted && 122 {deleteWorkspaceRequest.wasExecuted &&
123 deleteWorkspaceRequest.result && ( 123 deleteWorkspaceRequest.result ? (
124 <Appear className={classes.appear}> 124 <Appear className={classes.appear}>
125 <Infobox 125 <Infobox
126 type="success" 126 type="success"
127 icon="checkbox-marked-circle-outline" 127 icon="checkbox-marked-circle-outline"
128 dismissible 128 dismissible
129 onUnmount={deleteWorkspaceRequest.reset} 129 onUnmount={deleteWorkspaceRequest.reset}
130 > 130 >
131 {intl.formatMessage(messages.deletedInfo)} 131 {intl.formatMessage(messages.deletedInfo)}
132 </Infobox> 132 </Infobox>
133 </Appear> 133 </Appear>
134 )} 134 ) : null}
135 135
136 {/* ===== Create workspace form ===== */} 136 {/* ===== Create workspace form ===== */}
137 <div className={classes.createForm}> 137 <div className={classes.createForm}>
@@ -169,7 +169,7 @@ class WorkspacesDashboard extends Component<IProps> {
169 </p> 169 </p>
170 </div> 170 </div>
171 ) : ( 171 ) : (
172 <table className={classes.table} role="grid"> 172 <table className={classes.table}>
173 {/* ===== Workspaces list ===== */} 173 {/* ===== Workspaces list ===== */}
174 <tbody> 174 <tbody>
175 {workspaces.map(workspace => ( 175 {workspaces.map(workspace => (
diff --git a/src/features/workspaces/index.ts b/src/features/workspaces/index.ts
index 25975936a..cbe5bb5fd 100644
--- a/src/features/workspaces/index.ts
+++ b/src/features/workspaces/index.ts
@@ -3,6 +3,7 @@ import WorkspacesStore from './store';
3export const workspaceStore = new WorkspacesStore(); 3export const workspaceStore = new WorkspacesStore();
4 4
5export default function initWorkspaces(stores, actions) { 5export default function initWorkspaces(stores, actions) {
6 // eslint-disable-next-line no-param-reassign
6 stores.workspaces = workspaceStore; 7 stores.workspaces = workspaceStore;
7 workspaceStore.start(stores, actions); 8 workspaceStore.start(stores, actions);
8} 9}
diff --git a/src/index.ts b/src/index.ts
index a2fcfb890..999d84348 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -572,6 +572,7 @@ ipcMain.on(
572 for (const key in headers) { 572 for (const key in headers) {
573 if (Object.prototype.hasOwnProperty.call(headers, key)) { 573 if (Object.prototype.hasOwnProperty.call(headers, key)) {
574 const value = headers[key]; 574 const value = headers[key];
575 // eslint-disable-next-line no-param-reassign
575 details.requestHeaders[key] = value; 576 details.requestHeaders[key] = value;
576 } 577 }
577 } 578 }
diff --git a/src/internal-server/app/Controllers/Http/ImageController.js b/src/internal-server/app/Controllers/Http/ImageController.js
index 3ce6fb22d..930eca693 100644
--- a/src/internal-server/app/Controllers/Http/ImageController.js
+++ b/src/internal-server/app/Controllers/Http/ImageController.js
@@ -20,6 +20,7 @@ class ImageController {
20 try { 20 try {
21 await fs.access(iconPath); 21 await fs.access(iconPath);
22 } catch (error) { 22 } catch (error) {
23 // eslint-disable-next-line no-console
23 console.log(error); 24 console.log(error);
24 // File not available. 25 // File not available.
25 return response.status(404).send({ 26 return response.status(404).send({
diff --git a/src/internal-server/start/migrate.js b/src/internal-server/start/migrate.js
index 67533ed9e..bbe12f5ba 100644
--- a/src/internal-server/start/migrate.js
+++ b/src/internal-server/start/migrate.js
@@ -8,6 +8,7 @@ const Database = use('Database');
8const User = use('App/Models/User'); 8const User = use('App/Models/User');
9 9
10const migrateLog = text => { 10const migrateLog = text => {
11 // eslint-disable-next-line no-console
11 console.log('\u001B[36m%s\u001B[0m', 'Ferdium Migration:', '\u001B[0m', text); 12 console.log('\u001B[36m%s\u001B[0m', 'Ferdium Migration:', '\u001B[0m', text);
12}; 13};
13 14
diff --git a/src/internal-server/test.ts b/src/internal-server/test.ts
index c163656fb..991218942 100644
--- a/src/internal-server/test.ts
+++ b/src/internal-server/test.ts
@@ -6,5 +6,5 @@ const dummyUserFolder = join(__dirname, 'user_data');
6 6
7ensureDirSync(dummyUserFolder); 7ensureDirSync(dummyUserFolder);
8 8
9// eslint-disable-next-line unicorn/prefer-top-level-await 9// eslint-disable-next-line unicorn/prefer-top-level-await, no-console
10server(dummyUserFolder, 46_568, 'test').catch(console.log); 10server(dummyUserFolder, 46_568, 'test').catch(console.log);
diff --git a/src/jsUtils.ts b/src/jsUtils.ts
index 31d6a2121..72e8111e6 100644
--- a/src/jsUtils.ts
+++ b/src/jsUtils.ts
@@ -9,7 +9,7 @@ export const convertToJSON = (data?: string | any | null) =>
9export const cleanseJSObject = (data?: any | null) => 9export const cleanseJSObject = (data?: any | null) =>
10 JSON.parse(JSON.stringify(data)); 10 JSON.parse(JSON.stringify(data));
11 11
12export const isEscKeyPress = (keyCode: number) => keyCode === 27; 12export const isEscKeyPress = (key: string) => key === 'Escape';
13 13
14export const safeParseInt = (text?: string | number | null) => { 14export const safeParseInt = (text?: string | number | null) => {
15 if (text === undefined || text === null) { 15 if (text === undefined || text === null) {
diff --git a/src/routes.tsx b/src/routes.tsx
index d2a88950f..3615c9f99 100644
--- a/src/routes.tsx
+++ b/src/routes.tsx
@@ -114,6 +114,7 @@ class FerdiumRoutes extends Component<IProps> {
114 > 114 >
115 <Route 115 <Route
116 path="/releasenotes" 116 path="/releasenotes"
117 // @ts-expect-error Fix me
117 element={<ReleaseNotesScreen {...this.props} />} 118 element={<ReleaseNotesScreen {...this.props} />}
118 /> 119 />
119 </Route> 120 </Route>
@@ -184,10 +185,12 @@ class FerdiumRoutes extends Component<IProps> {
184 /> 185 />
185 <Route 186 <Route
186 path="/settings/support" 187 path="/settings/support"
188 // @ts-expect-error Fix me
187 element={<SupportFerdiumScreen {...this.props} />} 189 element={<SupportFerdiumScreen {...this.props} />}
188 /> 190 />
189 <Route 191 <Route
190 path="/settings/releasenotes" 192 path="/settings/releasenotes"
193 // @ts-expect-error Fix me
191 element={<ReleaseNotesScreen {...this.props} />} 194 element={<ReleaseNotesScreen {...this.props} />}
192 /> 195 />
193 </Route> 196 </Route>
diff --git a/src/stores/AppStore.ts b/src/stores/AppStore.ts
index b0a925411..51058c8eb 100644
--- a/src/stores/AppStore.ts
+++ b/src/stores/AppStore.ts
@@ -571,7 +571,7 @@ export default class AppStore extends TypedStore {
571 debug(`Removed download ${id}`); 571 debug(`Removed download ${id}`);
572 if (id === null) { 572 if (id === null) {
573 const indexesToRemove: number[] = []; 573 const indexesToRemove: number[] = [];
574 this.downloads.map(item => { 574 this.downloads.forEach(item => {
575 if (!item.state) return; 575 if (!item.state) return;
576 if (item.state === 'completed' || item.state === 'cancelled') { 576 if (item.state === 'completed' || item.state === 'cancelled') {
577 indexesToRemove.push(this.downloads.indexOf(item)); 577 indexesToRemove.push(this.downloads.indexOf(item));
diff --git a/src/stores/ServicesStore.ts b/src/stores/ServicesStore.ts
index 8105aa084..6c7a55d6b 100644
--- a/src/stores/ServicesStore.ts
+++ b/src/stores/ServicesStore.ts
@@ -332,6 +332,7 @@ export default class ServicesStore extends TypedStore {
332 .slice() 332 .slice()
333 .sort((a, b) => a.order - b.order) 333 .sort((a, b) => a.order - b.order)
334 .map((s, index) => { 334 .map((s, index) => {
335 // eslint-disable-next-line no-param-reassign
335 s.index = index; 336 s.index = index;
336 return s; 337 return s;
337 }), 338 }),
@@ -462,6 +463,7 @@ export default class ServicesStore extends TypedStore {
462 } 463 }
463 464
464 // set default values for serviceData 465 // set default values for serviceData
466 // eslint-disable-next-line no-param-reassign
465 serviceData = { 467 serviceData = {
466 isEnabled: DEFAULT_SERVICE_SETTINGS.isEnabled, 468 isEnabled: DEFAULT_SERVICE_SETTINGS.isEnabled,
467 isHibernationEnabled: DEFAULT_SERVICE_SETTINGS.isHibernationEnabled, 469 isHibernationEnabled: DEFAULT_SERVICE_SETTINGS.isHibernationEnabled,
@@ -649,6 +651,7 @@ export default class ServicesStore extends TypedStore {
649 } 651 }
650 652
651 @action _setIsActive(service: Service, state: boolean): void { 653 @action _setIsActive(service: Service, state: boolean): void {
654 // eslint-disable-next-line no-param-reassign
652 service.isActive = state; 655 service.isActive = state;
653 } 656 }
654 657
@@ -742,7 +745,9 @@ export default class ServicesStore extends TypedStore {
742 } 745 }
743 746
744 @action _detachService({ service }) { 747 @action _detachService({ service }) {
748 // eslint-disable-next-line no-param-reassign
745 service.webview = null; 749 service.webview = null;
750 // eslint-disable-next-line no-param-reassign
746 service.isAttached = false; 751 service.isAttached = false;
747 } 752 }
748 753
@@ -1023,6 +1028,7 @@ export default class ServicesStore extends TypedStore {
1023 } 1028 }
1024 1029
1025 if (!service.webview) return; 1030 if (!service.webview) return;
1031 // eslint-disable-next-line consistent-return
1026 return service.webview.loadURL(service.url); 1032 return service.webview.loadURL(service.url);
1027 } 1033 }
1028 1034
@@ -1226,7 +1232,9 @@ export default class ServicesStore extends TypedStore {
1226 1232
1227 // eslint-disable-next-line unicorn/consistent-function-scoping 1233 // eslint-disable-next-line unicorn/consistent-function-scoping
1228 const resetTimer = (service: Service) => { 1234 const resetTimer = (service: Service) => {
1235 // eslint-disable-next-line no-param-reassign
1229 service.lastPollAnswer = Date.now(); 1236 service.lastPollAnswer = Date.now();
1237 // eslint-disable-next-line no-param-reassign
1230 service.lastPoll = Date.now(); 1238 service.lastPoll = Date.now();
1231 }; 1239 };
1232 1240
@@ -1375,6 +1383,7 @@ export default class ServicesStore extends TypedStore {
1375 delete serviceData.team; 1383 delete serviceData.team;
1376 } 1384 }
1377 1385
1386 // eslint-disable-next-line consistent-return
1378 return serviceData; 1387 return serviceData;
1379 } 1388 }
1380 1389
diff --git a/src/stores/lib/Request.ts b/src/stores/lib/Request.ts
index e7739bba1..566fa5018 100644
--- a/src/stores/lib/Request.ts
+++ b/src/stores/lib/Request.ts
@@ -4,7 +4,7 @@ import { action, computed, makeObservable, observable } from 'mobx';
4type Hook = (request: Request) => void; 4type Hook = (request: Request) => void;
5 5
6export default class Request { 6export default class Request {
7 static _hooks: Hook[] = []; 7 static readonly _hooks: Hook[] = [];
8 8
9 static registerHook(hook: Hook) { 9 static registerHook(hook: Hook) {
10 Request._hooks.push(hook); 10 Request._hooks.push(hook);
diff --git a/src/styles/settings.scss b/src/styles/settings.scss
index 50accd8d7..1b79fd5c3 100644
--- a/src/styles/settings.scss
+++ b/src/styles/settings.scss
@@ -74,6 +74,7 @@
74 74
75 .settings__help { 75 .settings__help {
76 color: $dark-theme-gray-lightest; 76 color: $dark-theme-gray-lightest;
77 margin-top: 16px;
77 } 78 }
78 79
79 .settings__controls { 80 .settings__controls {
diff --git a/src/themes/default/index.ts b/src/themes/default/index.ts
index 8df7ff06e..458d4999d 100644
--- a/src/themes/default/index.ts
+++ b/src/themes/default/index.ts
@@ -7,6 +7,7 @@ import * as legacyStyles from '../legacy';
7 7
8export default (brandPrimary: string) => { 8export default (brandPrimary: string) => {
9 if (!brandPrimary) { 9 if (!brandPrimary) {
10 // eslint-disable-next-line no-param-reassign
10 brandPrimary = '#7266F0'; 11 brandPrimary = '#7266F0';
11 } 12 }
12 const brandSuccess = '#5cb85c'; 13 const brandSuccess = '#5cb85c';
diff --git a/src/webview/lib/RecipeWebview.ts b/src/webview/lib/RecipeWebview.ts
index 3b6b9cc88..2e967a791 100644
--- a/src/webview/lib/RecipeWebview.ts
+++ b/src/webview/lib/RecipeWebview.ts
@@ -128,7 +128,6 @@ class RecipeWebview {
128 * be an absolute path to the file 128 * be an absolute path to the file
129 */ 129 */
130 injectCSS(...files) { 130 injectCSS(...files) {
131 // eslint-disable-next-line unicorn/no-array-for-each
132 files.forEach(file => { 131 files.forEach(file => {
133 if (pathExistsSync(file)) { 132 if (pathExistsSync(file)) {
134 const styles = document.createElement('style'); 133 const styles = document.createElement('style');
diff --git a/test/jsUtils.test.ts b/test/jsUtils.test.ts
index 0662c3c48..cdded7aca 100644
--- a/test/jsUtils.test.ts
+++ b/test/jsUtils.test.ts
@@ -97,13 +97,13 @@ describe('jsUtils', () => {
97 }); 97 });
98 98
99 describe('isEscKeyPress', () => { 99 describe('isEscKeyPress', () => {
100 it('returns true if the key number is 27', () => { 100 it('returns true if the key is "Escape"', () => {
101 const result = jsUtils.isEscKeyPress(27); 101 const result = jsUtils.isEscKeyPress('Escape');
102 expect(result).toEqual(true); 102 expect(result).toEqual(true);
103 }); 103 });
104 104
105 it('returns false if the key number is 27', () => { 105 it('returns false if the key is some other key', () => {
106 const result = jsUtils.isEscKeyPress(28); 106 const result = jsUtils.isEscKeyPress('Backspace');
107 expect(result).toEqual(false); 107 expect(result).toEqual(false);
108 }); 108 });
109 }); 109 });