From bec02c96d417299828ad1434d1dc566d1e0d7a70 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 18 Mar 2025 09:58:09 +0000
Subject: [PATCH] Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
 .lintstagedrc                                |   3 +-
 biome.jsonc                                  | 114 ++++---------------
 electron-builder.ts                          |  10 +-
 hak/matrix-seshat/build.ts                   |   2 +-
 hak/matrix-seshat/check.ts                   |   2 +-
 knip.ts                                      |   2 +-
 package.json                                 |   5 +-
 playwright/e2e/launch/config-options.spec.ts |   4 +-
 playwright/e2e/launch/launch.spec.ts         |   2 +-
 playwright/element-desktop-test.ts           |   9 +-
 scripts/copy-res.ts                          |   6 +-
 scripts/fetch-package.ts                     |  20 ++--
 scripts/hak/copy.ts                          |   6 +-
 scripts/hak/fetch.ts                         |   2 +-
 scripts/hak/hakEnv.ts                        |   8 +-
 scripts/hak/index.ts                         |   7 +-
 scripts/hak/link.ts                          |   6 +-
 scripts/set-version.ts                       |   4 +-
 src/@types/global.d.ts                       |   9 +-
 src/@types/matrix-seshat.d.ts                |   2 -
 src/electron-main.ts                         |  31 ++---
 src/ipc.ts                                   |  22 +++-
 src/language-helper.ts                       |   5 +-
 src/preload.cts                              |   2 +-
 src/protocol.ts                              |   8 +-
 src/seshat.ts                                |   7 +-
 src/squirrelhooks.ts                         |   2 +-
 src/tray.ts                                  |  12 +-
 src/updater.ts                               |   4 +-
 src/vectormenu.ts                            |   2 +-
 src/webcontents-handler.ts                   |  38 +++----
 yarn.lock                                    |  54 ---------
 32 files changed, 146 insertions(+), 264 deletions(-)

diff --git a/.lintstagedrc b/.lintstagedrc
index c29a05af..a037fa7e 100644
--- a/.lintstagedrc
+++ b/.lintstagedrc
@@ -1,4 +1,3 @@
 {
-    "*": "prettier --write",
-    "*.(ts|tsx)": ["eslint --fix"]
+    "*": ["biome check --no-errors-on-unmatched --files-ignore-unknown=true"]
 }
diff --git a/biome.jsonc b/biome.jsonc
index e9704857..36024a45 100644
--- a/biome.jsonc
+++ b/biome.jsonc
@@ -1,5 +1,14 @@
 {
     "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
+    "vcs": {
+        "enabled": true,
+        "clientKind": "git",
+        "useIgnoreFile": true
+    },
+    "files": {
+        "ignoreUnknown": false,
+        "ignore": []
+    },
     "formatter": {
         "enabled": true,
         "useEditorconfig": true,
@@ -9,43 +18,17 @@
         "lineEnding": "lf",
         "lineWidth": 120,
         "attributePosition": "auto",
-        "bracketSpacing": true,
-        "ignore": [
-            "../element-web",
-            "./build/",
-            "./docker/",
-            "./dist/**",
-            "./.hak/**",
-            "./dockerbuild/",
-            "./lib/",
-            "./node_modules/",
-            "./packages.elememt.io/",
-            "./webapp",
-            "./src/i18n/strings",
-            "./CHANGELOG.md",
-            "./package-lock.json",
-            "./yarn.lock",
-            "./playwright/html-report",
-            "./playwright/test-results",
-            "**/.idea",
-            "**/.vscode",
-            "**/.vscode/",
-            "**/.tmp",
-            "**/.env",
-            "./coverage",
-            "./.npmrc",
-            "./*.log"
-        ]
+        "bracketSpacing": true
     },
-    "organizeImports": { "enabled": false },
+    "organizeImports": { "enabled": true },
     "linter": {
-        "enabled": false,
+        "enabled": true,
         "rules": {
             "recommended": false,
             "complexity": {
                 "noExtraBooleanCast": "error",
                 "noMultipleSpacesInRegularExpressionLiterals": "error",
-                "noUselessCatch": "off",
+                "noUselessCatch": "error",
                 "noWith": "error"
             },
             "correctness": {
@@ -77,16 +60,18 @@
             "style": {
                 "noArguments": "error",
                 "noVar": "error",
-                "useBlockStatements": "error",
+                "useBlockStatements": "off",
                 "useConsistentBuiltinInstantiation": "error",
                 "useConst": "error",
                 "useNodejsImportProtocol": "error",
                 "useSingleVarDeclarator": "error",
-                "useThrowOnlyError": "error"
+                "useThrowOnlyError": "error",
+                "useImportType": "error",
+                "useExportType": "error"
             },
             "suspicious": {
                 "noAssignInExpressions": "error",
-                "noAsyncPromiseExecutor": "off",
+                "noAsyncPromiseExecutor": "error",
                 "noCatchAssign": "error",
                 "noClassAssign": "error",
                 "noCompareNegZero": "error",
@@ -103,7 +88,7 @@
                 "noGlobalAssign": "error",
                 "noImportAssign": "error",
                 "noMisleadingCharacterClass": "error",
-                "noPrototypeBuiltins": "off",
+                "noPrototypeBuiltins": "error",
                 "noRedeclare": "error",
                 "noShadowRestrictedNames": "error",
                 "noSparseArray": "error",
@@ -129,25 +114,7 @@
     },
     "overrides": [
         {
-            "include": ["src/**/*.ts"],
-            "linter": {
-                "rules": {
-                    "style": { "noNonNullAssertion": "off" },
-                    "suspicious": { "noExplicitAny": "off" }
-                }
-            }
-        },
-        {
-            "include": ["hak/**/*.ts"],
-            "linter": {
-                "rules": {
-                    "style": { "noNonNullAssertion": "off" },
-                    "suspicious": { "noExplicitAny": "off" }
-                }
-            }
-        },
-        {
-            "include": ["scripts/**/*.ts"],
+            "include": ["src/**/*.ts", "hak/**/*.ts", "scripts/**/*.ts", "playwright/**/*.ts"],
             "linter": {
                 "rules": {
                     "style": { "noNonNullAssertion": "off" },
@@ -159,44 +126,9 @@
             "include": ["playwright/**/*.ts"],
             "linter": {
                 "rules": {
-                    "style": { "noNonNullAssertion": "off" },
-                    "suspicious": { "noExplicitAny": "off" }
-                }
-            }
-        },
-        {
-            "include": ["src/**/*.ts"],
-            "linter": {
-                "rules": {
-                    "style": { "noNonNullAssertion": "off" },
-                    "suspicious": { "noExplicitAny": "off" }
-                }
-            }
-        },
-        {
-            "include": ["hak/**/*.ts"],
-            "linter": {
-                "rules": {
-                    "style": { "noNonNullAssertion": "off" },
-                    "suspicious": { "noExplicitAny": "off" }
-                }
-            }
-        },
-        {
-            "include": ["scripts/**/*.ts"],
-            "linter": {
-                "rules": {
-                    "style": { "noNonNullAssertion": "off" },
-                    "suspicious": { "noExplicitAny": "off" }
-                }
-            }
-        },
-        {
-            "include": ["playwright/**/*.ts"],
-            "linter": {
-                "rules": {
-                    "style": { "noNonNullAssertion": "off" },
-                    "suspicious": { "noExplicitAny": "off" }
+                    "correctness": {
+                        "noEmptyPattern": "off"
+                    }
                 }
             }
         }
diff --git a/electron-builder.ts b/electron-builder.ts
index 660721d1..5261244e 100644
--- a/electron-builder.ts
+++ b/electron-builder.ts
@@ -1,10 +1,10 @@
-import * as os from "node:os";
 import * as fs from "node:fs";
-import * as path from "node:path";
-import * as plist from "plist";
-import { AfterPackContext, Arch, Configuration as BaseConfiguration, Platform } from "electron-builder";
-import { computeData } from "app-builder-lib/out/asar/integrity";
 import { readFile, writeFile } from "node:fs/promises";
+import * as os from "node:os";
+import * as path from "node:path";
+import { computeData } from "app-builder-lib/out/asar/integrity";
+import { type AfterPackContext, Arch, type Configuration as BaseConfiguration, Platform } from "electron-builder";
+import * as plist from "plist";
 
 /**
  * This script has different outputs depending on your os platform.
diff --git a/hak/matrix-seshat/build.ts b/hak/matrix-seshat/build.ts
index b4e46f1f..9dc5ef1b 100644
--- a/hak/matrix-seshat/build.ts
+++ b/hak/matrix-seshat/build.ts
@@ -6,8 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import type HakEnv from "../../scripts/hak/hakEnv.js";
 import type { DependencyInfo } from "../../scripts/hak/dep.js";
+import type HakEnv from "../../scripts/hak/hakEnv.js";
 
 export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
     const env = hakEnv.makeGypEnv();
diff --git a/hak/matrix-seshat/check.ts b/hak/matrix-seshat/check.ts
index 604cb5ae..dad949b6 100644
--- a/hak/matrix-seshat/check.ts
+++ b/hak/matrix-seshat/check.ts
@@ -9,9 +9,9 @@ Please see LICENSE files in the repository root for full details.
 import childProcess from "node:child_process";
 import fsProm from "node:fs/promises";
 
+import type { DependencyInfo } from "../../scripts/hak/dep.js";
 import type HakEnv from "../../scripts/hak/hakEnv.js";
 import type { Tool } from "../../scripts/hak/hakEnv.js";
-import type { DependencyInfo } from "../../scripts/hak/dep.js";
 
 export default async function (hakEnv: HakEnv, _moduleInfo: DependencyInfo): Promise<void> {
     const tools: Tool[] = [
diff --git a/knip.ts b/knip.ts
index e6ddebdf..fbc1c99c 100644
--- a/knip.ts
+++ b/knip.ts
@@ -1,4 +1,4 @@
-import { KnipConfig } from "knip";
+import type { KnipConfig } from "knip";
 
 export default {
     entry: ["src/electron-main.ts", "src/preload.ts", "electron-builder.ts", ".eslintrc-*.js", "scripts/**", "hak/**"],
diff --git a/package.json b/package.json
index 48034ef3..d1e1dbe9 100644
--- a/package.json
+++ b/package.json
@@ -27,8 +27,8 @@
         "asar-webapp": "asar p webapp webapp.asar",
         "start": "yarn run build:ts && yarn run build:res && electron .",
         "lint": "yarn lint:types && yarn lint:js && yarn lint:workflows",
-        "lint:js": "biome lint",
-        "lint:js-fix": "biome lint --write",
+        "lint:js": "biome check",
+        "lint:js-fix": "biome check --write",
         "lint:types": "yarn lint:types:src && yarn lint:types:test && yarn lint:types:scripts && yarn lint:types:hak",
         "lint:types:src": "tsc --noEmit",
         "lint:types:test": "tsc --noEmit -p playwright/tsconfig.json",
@@ -95,7 +95,6 @@
         "lint-staged": "^15.2.10",
         "matrix-web-i18n": "^3.2.1",
         "mkdirp": "^3.0.0",
-        "oxlint": "^0.16.0",
         "pacote": "^21.0.0",
         "plist": "^3.1.0",
         "rimraf": "^6.0.0",
diff --git a/playwright/e2e/launch/config-options.spec.ts b/playwright/e2e/launch/config-options.spec.ts
index 39d7c1d5..90f4e5fc 100644
--- a/playwright/e2e/launch/config-options.spec.ts
+++ b/playwright/e2e/launch/config-options.spec.ts
@@ -5,10 +5,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import { resolve, dirname } from "node:path";
+import { dirname, resolve } from "node:path";
 import { fileURLToPath } from "node:url";
 
-import { test, expect } from "../../element-desktop-test.js";
+import { expect, test } from "../../element-desktop-test.js";
 
 const __dirname = dirname(fileURLToPath(import.meta.url));
 
diff --git a/playwright/e2e/launch/launch.spec.ts b/playwright/e2e/launch/launch.spec.ts
index cd3c9444..f56a14eb 100644
--- a/playwright/e2e/launch/launch.spec.ts
+++ b/playwright/e2e/launch/launch.spec.ts
@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
 
 import { platform } from "node:os";
 
-import { test, expect } from "../../element-desktop-test.js";
+import { expect, test } from "../../element-desktop-test.js";
 
 declare global {
     interface Window {
diff --git a/playwright/element-desktop-test.ts b/playwright/element-desktop-test.ts
index 3d8d4f54..7a28b272 100644
--- a/playwright/element-desktop-test.ts
+++ b/playwright/element-desktop-test.ts
@@ -6,12 +6,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import { _electron as electron, test as base, expect as baseExpect, type ElectronApplication } from "@playwright/test";
 import fs from "node:fs/promises";
-import path, { dirname } from "node:path";
 import os from "node:os";
-import { fileURLToPath } from "node:url";
+import path, { dirname } from "node:path";
 import { PassThrough } from "node:stream";
+import { fileURLToPath } from "node:url";
+import { type ElectronApplication, test as base, expect as baseExpect, _electron as electron } from "@playwright/test";
 
 /**
  * A PassThrough stream that captures all data written to it.
@@ -50,16 +50,13 @@ export const test = base.extend<Fixtures>({
     extraEnv: {},
     extraArgs: [],
 
-    // eslint-disable-next-line no-empty-pattern
     stdout: async ({}, use) => {
         await use(new CapturedPassThrough());
     },
-    // eslint-disable-next-line no-empty-pattern
     stderr: async ({}, use) => {
         await use(new CapturedPassThrough());
     },
 
-    // eslint-disable-next-line no-empty-pattern
     tmpDir: async ({}, use) => {
         const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "element-desktop-tests-"));
         console.log("Using temp profile directory: ", tmpDir);
diff --git a/scripts/copy-res.ts b/scripts/copy-res.ts
index fd5aa60f..9c92d9f3 100755
--- a/scripts/copy-res.ts
+++ b/scripts/copy-res.ts
@@ -2,10 +2,10 @@
 
 // copies resources into the lib directory.
 
-import parseArgs from "minimist";
-import * as chokidar from "chokidar";
-import * as path from "node:path";
 import * as fs from "node:fs";
+import * as path from "node:path";
+import * as chokidar from "chokidar";
+import parseArgs from "minimist";
 
 const argv = parseArgs(process.argv.slice(2), {});
 
diff --git a/scripts/fetch-package.ts b/scripts/fetch-package.ts
index 72829454..200be530 100644
--- a/scripts/fetch-package.ts
+++ b/scripts/fetch-package.ts
@@ -1,11 +1,11 @@
 #!/usr/bin/env -S npx tsx --resolveJsonModule
 
-import * as path from "node:path";
-import { createWriteStream, promises as fs } from "node:fs";
 import * as childProcess from "node:child_process";
-import * as tar from "tar";
-import * as asar from "@electron/asar";
+import { promises as fs, createWriteStream } from "node:fs";
+import * as path from "node:path";
 import { promises as stream } from "node:stream";
+import * as asar from "@electron/asar";
+import * as tar from "tar";
 
 import riotDesktopPackageJson from "../package.json";
 import { setPackageVersion } from "./set-version.js";
@@ -27,7 +27,9 @@ async function downloadToFile(url: string, filename: string): Promise<void> {
         console.error(e);
         try {
             await fs.unlink(filename);
-        } catch {}
+        } catch {
+            // ignore
+        }
         throw e;
     }
 }
@@ -151,7 +153,9 @@ async function main(): Promise<number | undefined> {
         await fs.opendir(expectedDeployDir);
         console.log(expectedDeployDir + "already exists");
         haveDeploy = true;
-    } catch {}
+    } catch {
+        // ignore
+    }
 
     if (!haveDeploy) {
         const outPath = path.join(pkgDir, filename);
@@ -207,7 +211,9 @@ async function main(): Promise<number | undefined> {
         await fs.stat(ASAR_PATH);
         console.log(ASAR_PATH + " already present: removing");
         await fs.unlink(ASAR_PATH);
-    } catch {}
+    } catch {
+        // ignore
+    }
 
     if (cfgDir.length) {
         const configJsonSource = path.join(cfgDir, "config.json");
diff --git a/scripts/hak/copy.ts b/scripts/hak/copy.ts
index 607792e6..3043624d 100644
--- a/scripts/hak/copy.ts
+++ b/scripts/hak/copy.ts
@@ -6,14 +6,14 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import path from "node:path";
-import fsProm from "node:fs/promises";
 import childProcess from "node:child_process";
+import fsProm from "node:fs/promises";
+import path from "node:path";
 import { glob } from "glob";
 import { mkdirp } from "mkdirp";
 
-import type HakEnv from "./hakEnv.js";
 import type { DependencyInfo } from "./dep.js";
+import type HakEnv from "./hakEnv.js";
 
 export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
     if (moduleInfo.cfg.copy) {
diff --git a/scripts/hak/fetch.ts b/scripts/hak/fetch.ts
index dc2dbd66..40c625c3 100644
--- a/scripts/hak/fetch.ts
+++ b/scripts/hak/fetch.ts
@@ -9,8 +9,8 @@ Please see LICENSE files in the repository root for full details.
 import fsProm from "node:fs/promises";
 import pacote from "pacote";
 
-import type HakEnv from "./hakEnv.js";
 import type { DependencyInfo } from "./dep.js";
+import type HakEnv from "./hakEnv.js";
 
 export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
     let haveModuleBuildDir;
diff --git a/scripts/hak/hakEnv.ts b/scripts/hak/hakEnv.ts
index ed2bff60..cf8df1b2 100644
--- a/scripts/hak/hakEnv.ts
+++ b/scripts/hak/hakEnv.ts
@@ -6,12 +6,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import path from "node:path";
-import os from "node:os";
-import { getElectronVersionFromInstalled } from "app-builder-lib/out/electron/electronVersion.js";
 import childProcess, { type SpawnOptions } from "node:child_process";
+import os from "node:os";
+import path from "node:path";
+import { getElectronVersionFromInstalled } from "app-builder-lib/out/electron/electronVersion.js";
 
-import { type Arch, type Target, TARGETS, getHost, isHostId, type TargetId } from "./target.js";
+import { type Arch, TARGETS, type Target, type TargetId, getHost, isHostId } from "./target.js";
 
 async function getRuntimeVersion(projectRoot: string): Promise<string> {
     const electronVersion = await getElectronVersionFromInstalled(projectRoot);
diff --git a/scripts/hak/index.ts b/scripts/hak/index.ts
index b78d6474..9a3efee5 100644
--- a/scripts/hak/index.ts
+++ b/scripts/hak/index.ts
@@ -9,11 +9,11 @@ Please see LICENSE files in the repository root for full details.
 import path, { dirname } from "node:path";
 import { fileURLToPath } from "node:url";
 
+import packageJson from "../../package.json";
+import { loadJsonFile } from "../../src/utils.js";
+import type { DependencyInfo } from "./dep.js";
 import HakEnv from "./hakEnv.js";
 import type { TargetId } from "./target.js";
-import type { DependencyInfo } from "./dep.js";
-import { loadJsonFile } from "../../src/utils.js";
-import packageJson from "../../package.json";
 
 // These can only be run on specific modules
 const MODULECOMMANDS = ["check", "fetch", "link", "build", "copy", "clean"];
@@ -38,7 +38,6 @@ async function main(): Promise<void> {
     // Can be specified multiple times for the copy command to bundle
     // multiple arches into a single universal output module)
     for (;;) {
-        // eslint-disable-line no-constant-condition
         const targetIndex = process.argv.indexOf("--target");
         if (targetIndex === -1) break;
 
diff --git a/scripts/hak/link.ts b/scripts/hak/link.ts
index c2c43ceb..c83c521f 100644
--- a/scripts/hak/link.ts
+++ b/scripts/hak/link.ts
@@ -6,12 +6,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import path from "node:path";
-import os from "node:os";
 import fsProm from "node:fs/promises";
+import os from "node:os";
+import path from "node:path";
 
+import type { DependencyInfo } from "./dep.js";
 import type HakEnv from "./hakEnv.js";
-import { type DependencyInfo } from "./dep.js";
 
 export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
     const yarnrc = path.join(hakEnv.projectRoot, ".yarnrc");
diff --git a/scripts/set-version.ts b/scripts/set-version.ts
index 9890f098..2050c9a2 100755
--- a/scripts/set-version.ts
+++ b/scripts/set-version.ts
@@ -5,10 +5,10 @@
  * version metadata of the package to match.
  */
 
-import { promises as fs } from "node:fs";
-import * as asar from "@electron/asar";
 import * as childProcess from "node:child_process";
+import { promises as fs } from "node:fs";
 import * as url from "node:url";
+import * as asar from "@electron/asar";
 
 export async function versionFromAsar(): Promise<string> {
     try {
diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts
index d3b13bea..ab08a65e 100644
--- a/src/@types/global.d.ts
+++ b/src/@types/global.d.ts
@@ -5,14 +5,13 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import { type BrowserWindow } from "electron";
+import type { BrowserWindow } from "electron";
 
-import type Store from "electron-store";
 import type AutoLaunch from "auto-launch";
-import { type AppLocalization } from "../language-helper.js";
+import type Store from "electron-store";
+import type { AppLocalization } from "../language-helper.js";
 
 // global type extensions need to use var for whatever reason
-/* eslint-disable no-var */
 declare global {
     var mainWindow: BrowserWindow | null;
     var appQuitting: boolean;
@@ -20,7 +19,6 @@ declare global {
     var launcher: AutoLaunch;
     var vectorConfig: Record<string, any>;
     var trayConfig: {
-        // eslint-disable-next-line camelcase
         icon_path: string;
         brand: string;
     };
@@ -33,4 +31,3 @@ declare global {
         disableHardwareAcceleration?: boolean;
     }>;
 }
-/* eslint-enable no-var */
diff --git a/src/@types/matrix-seshat.d.ts b/src/@types/matrix-seshat.d.ts
index e93147b6..d68846fd 100644
--- a/src/@types/matrix-seshat.d.ts
+++ b/src/@types/matrix-seshat.d.ts
@@ -11,7 +11,6 @@ declare module "matrix-seshat" {
         passphrase?: string;
     }
 
-    /* eslint-disable camelcase */
     interface IMatrixEvent {
         event_id: string;
         sender: string;
@@ -49,7 +48,6 @@ declare module "matrix-seshat" {
             context: ISearchContext;
         }>;
     }
-    /* eslint-enable camelcase */
 
     interface ICheckpoint {
         roomId: string;
diff --git a/src/electron-main.ts b/src/electron-main.ts
index 4b0b26fb..59960a93 100644
--- a/src/electron-main.ts
+++ b/src/electron-main.ts
@@ -10,30 +10,29 @@ Please see LICENSE files in the repository root for full details.
 
 // Squirrel on windows starts the app with various flags as hooks to tell us when we've been installed/uninstalled etc.
 import "./squirrelhooks.js";
-import { app, BrowserWindow, Menu, autoUpdater, protocol, dialog, type Input, type Event, session } from "electron";
-// eslint-disable-next-line n/file-extension-in-import
+import fs, { promises as afs } from "node:fs";
+import path, { dirname } from "node:path";
+import { URL, fileURLToPath } from "node:url";
 import * as Sentry from "@sentry/electron/main";
 import AutoLaunch from "auto-launch";
-import path, { dirname } from "node:path";
-import windowStateKeeper from "electron-window-state";
+import { BrowserWindow, type Event, type Input, Menu, app, autoUpdater, dialog, protocol, session } from "electron";
 import Store from "electron-store";
-import fs, { promises as afs } from "node:fs";
-import { URL, fileURLToPath } from "node:url";
+import windowStateKeeper from "electron-window-state";
 import minimist from "minimist";
 
 import "./ipc.js";
 import "./seshat.js";
 import "./settings.js";
+import { setDisplayMediaCallback } from "./displayMediaCallback.js";
+import { AppLocalization, _t } from "./language-helper.js";
+import { setupMacosTitleBar } from "./macos-titlebar.js";
+import { setupMediaAuth } from "./media-auth.js";
+import { getProfileFromDeeplink, protocolInit } from "./protocol.js";
 import * as tray from "./tray.js";
+import * as updater from "./updater.js";
+import { loadJsonFile } from "./utils.js";
 import { buildMenuTemplate } from "./vectormenu.js";
 import webContentsHandler from "./webcontents-handler.js";
-import * as updater from "./updater.js";
-import { getProfileFromDeeplink, protocolInit } from "./protocol.js";
-import { _t, AppLocalization } from "./language-helper.js";
-import { setDisplayMediaCallback } from "./displayMediaCallback.js";
-import { setupMacosTitleBar } from "./macos-titlebar.js";
-import { loadJsonFile } from "./utils.js";
-import { setupMediaAuth } from "./media-auth.js";
 
 const __dirname = dirname(fileURLToPath(import.meta.url));
 
@@ -105,7 +104,9 @@ async function tryPaths(name: string, root: string, rawPaths: string[]): Promise
         try {
             await afs.stat(p);
             return p + "/";
-        } catch {}
+        } catch {
+            // ignore
+        }
     }
     console.log(`Couldn't find ${name} files in any of: `);
     for (const p of paths) {
@@ -528,7 +529,7 @@ app.on("ready", async () => {
 
     if (process.platform === "win32") {
         // Handle forward/backward mouse buttons in Windows
-        global.mainWindow.on("app-command", (e, cmd) => {
+        global.mainWindow.on("app-command", (_e, cmd) => {
             if (cmd === "browser-backward" && global.mainWindow?.webContents.canGoBack()) {
                 global.mainWindow.webContents.goBack();
             } else if (cmd === "browser-forward" && global.mainWindow?.webContents.canGoForward()) {
diff --git a/src/ipc.ts b/src/ipc.ts
index c2f6371d..875fddc9 100644
--- a/src/ipc.ts
+++ b/src/ipc.ts
@@ -5,15 +5,23 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import { app, autoUpdater, desktopCapturer, ipcMain, powerSaveBlocker, TouchBar, nativeImage } from "electron";
 import { relaunchApp } from "@standardnotes/electron-clear-data";
+import {
+    type IpcMainEvent,
+    TouchBar,
+    app,
+    autoUpdater,
+    desktopCapturer,
+    ipcMain,
+    nativeImage,
+    powerSaveBlocker,
+} from "electron";
 import keytar from "keytar-forked";
 
-import IpcMainEvent = Electron.IpcMainEvent;
-import { recordSSOSession } from "./protocol.js";
-import { randomArray } from "./utils.js";
-import { Settings } from "./settings.js";
 import { getDisplayMediaCallback, setDisplayMediaCallback } from "./displayMediaCallback.js";
+import { recordSSOSession } from "./protocol.js";
+import { Settings } from "./settings.js";
+import { randomArray } from "./utils.js";
 
 ipcMain.on("setBadgeCount", function (_ev: IpcMainEvent, count: number): void {
     if (process.platform !== "win32") {
@@ -173,7 +181,9 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
                 // migrate from riot.im (remove once we think there will no longer be
                 // logins from the time of riot.im)
                 await keytar.deletePassword("riot.im", `${args[0]}|${args[1]}`);
-            } catch {}
+            } catch (e) {
+                console.error("Failed to destroy pickle key", e);
+            }
             break;
         case "getDesktopCapturerSources":
             ret = (await desktopCapturer.getSources(args[0])).map((source) => ({
diff --git a/src/language-helper.ts b/src/language-helper.ts
index 5eeb0fb5..4313529f 100644
--- a/src/language-helper.ts
+++ b/src/language-helper.ts
@@ -5,10 +5,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import counterpart from "counterpart";
-import { type TranslationKey as TKey } from "matrix-web-i18n";
 import { dirname } from "node:path";
 import { fileURLToPath } from "node:url";
+import counterpart from "counterpart";
+import type { TranslationKey as TKey } from "matrix-web-i18n";
 
 import type Store from "electron-store";
 import type EN from "./i18n/strings/en_EN.json";
@@ -79,7 +79,6 @@ export class AppLocalization {
         this.store = store;
         if (this.store.has(AppLocalization.STORE_KEY)) {
             const locales = this.store.get(AppLocalization.STORE_KEY);
-            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             this.setAppLocale(locales!);
         }
 
diff --git a/src/preload.cts b/src/preload.cts
index 5ab287da..ea285b01 100644
--- a/src/preload.cts
+++ b/src/preload.cts
@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
 
 // This file is compiled to CommonJS rather than ESM otherwise the browser chokes on the import statement.
 
-import { ipcRenderer, contextBridge, IpcRendererEvent } from "electron";
+import { type IpcRendererEvent, contextBridge, ipcRenderer } from "electron";
 
 // Expose only expected IPC wrapper APIs to the renderer process to avoid
 // handing out generalised messaging access.
diff --git a/src/protocol.ts b/src/protocol.ts
index 6cb31ae5..b1361fd0 100644
--- a/src/protocol.ts
+++ b/src/protocol.ts
@@ -6,10 +6,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import { app } from "electron";
-import { URL } from "node:url";
-import path from "node:path";
 import fs from "node:fs";
+import path from "node:path";
+import { URL } from "node:url";
+import { app } from "electron";
 
 const LEGACY_PROTOCOL = "element";
 const PROTOCOL = "io.element.desktop";
@@ -115,7 +115,7 @@ export function protocolInit(): void {
         });
     } else {
         // Protocol handler for win32/Linux
-        app.on("second-instance", (ev, commandLine) => {
+        app.on("second-instance", (_ev, commandLine) => {
             const url = commandLine[commandLine.length - 1];
             if (!url.startsWith(`${PROTOCOL}://`) && !url.startsWith(`${LEGACY_PROTOCOL}://`)) return;
             processUrl(url);
diff --git a/src/seshat.ts b/src/seshat.ts
index 93f2e0b1..b0c1171f 100644
--- a/src/seshat.ts
+++ b/src/seshat.ts
@@ -5,17 +5,16 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import { app, ipcMain } from "electron";
 import { promises as afs } from "node:fs";
 import path from "node:path";
+import { type IpcMainEvent, app, ipcMain } from "electron";
 import keytar from "keytar-forked";
 
 import type {
-    Seshat as SeshatType,
-    SeshatRecovery as SeshatRecoveryType,
     ReindexError as ReindexErrorType,
+    SeshatRecovery as SeshatRecoveryType,
+    Seshat as SeshatType,
 } from "matrix-seshat"; // Hak dependency type
-import IpcMainEvent = Electron.IpcMainEvent;
 import { randomArray } from "./utils.js";
 
 let seshatSupported = false;
diff --git a/src/squirrelhooks.ts b/src/squirrelhooks.ts
index 50b30a4e..0b855dc1 100644
--- a/src/squirrelhooks.ts
+++ b/src/squirrelhooks.ts
@@ -6,8 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import path from "node:path";
 import { spawn } from "node:child_process";
+import path from "node:path";
 import { app } from "electron";
 
 export function getSquirrelExecutable(): string {
diff --git a/src/tray.ts b/src/tray.ts
index bbf477bf..b12d40fe 100644
--- a/src/tray.ts
+++ b/src/tray.ts
@@ -7,10 +7,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import { app, Tray, Menu, nativeImage } from "electron";
-import pngToIco from "png-to-ico";
-import path from "node:path";
 import fs from "node:fs";
+import path from "node:path";
+import { Menu, Tray, app, nativeImage } from "electron";
+import pngToIco from "png-to-ico";
 import { v5 as uuidv5 } from "uuid";
 
 import { _t } from "./language-helper.js";
@@ -39,7 +39,7 @@ function toggleWin(): void {
 }
 
 interface IConfig {
-    icon_path: string; // eslint-disable-line camelcase
+    icon_path: string;
     brand: string;
 }
 
@@ -72,7 +72,7 @@ export function create(config: IConfig): void {
     trayIcon.on("click", toggleWin);
 
     let lastFavicon: string | null = null;
-    global.mainWindow?.webContents.on("page-favicon-updated", async function (ev, favicons) {
+    global.mainWindow?.webContents.on("page-favicon-updated", async function (_ev, favicons) {
         if (!favicons || favicons.length <= 0 || !favicons[0].startsWith("data:")) {
             if (lastFavicon !== null) {
                 global.mainWindow?.setIcon(defaultIcon);
@@ -103,7 +103,7 @@ export function create(config: IConfig): void {
         global.mainWindow?.setIcon(newFavicon);
     });
 
-    global.mainWindow?.webContents.on("page-title-updated", function (ev, title) {
+    global.mainWindow?.webContents.on("page-title-updated", function (_ev, title) {
         trayIcon?.setToolTip(title);
     });
 }
diff --git a/src/updater.ts b/src/updater.ts
index d0cdf7f8..6cafaa6b 100644
--- a/src/updater.ts
+++ b/src/updater.ts
@@ -5,8 +5,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import { app, autoUpdater, ipcMain } from "electron";
 import fs from "node:fs/promises";
+import { app, autoUpdater, ipcMain } from "electron";
 
 import { getSquirrelExecutable } from "./squirrelhooks.js";
 
@@ -165,7 +165,7 @@ autoUpdater
         ipcChannelSendUpdateStatus(error.message);
     });
 
-autoUpdater.on("update-downloaded", (ev, releaseNotes, releaseName, releaseDate, updateURL) => {
+autoUpdater.on("update-downloaded", (_ev, releaseNotes, releaseName, releaseDate, updateURL) => {
     // forward to renderer
     latestUpdateDownloaded = { releaseNotes, releaseName, releaseDate, updateURL };
     global.mainWindow?.webContents.send("update-downloaded", latestUpdateDownloaded);
diff --git a/src/vectormenu.ts b/src/vectormenu.ts
index d5bab05e..878b32f3 100644
--- a/src/vectormenu.ts
+++ b/src/vectormenu.ts
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
-import { app, shell, Menu, type MenuItem, type MenuItemConstructorOptions } from "electron";
+import { Menu, type MenuItem, type MenuItemConstructorOptions, app, shell } from "electron";
 
 import { _t } from "./language-helper.js";
 
diff --git a/src/webcontents-handler.ts b/src/webcontents-handler.ts
index 78dbfd79..b97b2ac5 100644
--- a/src/webcontents-handler.ts
+++ b/src/webcontents-handler.ts
@@ -5,26 +5,26 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
 Please see LICENSE files in the repository root for full details.
 */
 
+import fs from "node:fs";
+import path from "node:path";
+import { pipeline } from "node:stream/promises";
+import url from "node:url";
 import {
-    clipboard,
-    nativeImage,
-    Menu,
-    MenuItem,
-    shell,
-    dialog,
-    ipcMain,
-    type NativeImage,
-    type WebContents,
     type ContextMenuParams,
     type DownloadItem,
-    type MenuItemConstructorOptions,
-    type IpcMainEvent,
     type Event,
+    type IpcMainEvent,
+    Menu,
+    MenuItem,
+    type MenuItemConstructorOptions,
+    type NativeImage,
+    type WebContents,
+    clipboard,
+    dialog,
+    ipcMain,
+    nativeImage,
+    shell,
 } from "electron";
-import url from "node:url";
-import fs from "node:fs";
-import { pipeline } from "node:stream/promises";
-import path from "node:path";
 
 import { _t } from "./language-helper.js";
 
@@ -75,7 +75,7 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
     if (url.startsWith("vector://vector/webapp")) {
         // Avoid showing a context menu for app icons
         if (params.hasImageContents) return;
-        const baseUrl = vectorConfig.web_base_url ?? "https://app.element.io/";
+        const baseUrl = global.vectorConfig.web_base_url ?? "https://app.element.io/";
         // Rewrite URL so that it can be used outside the app
         url = baseUrl + url.substring(23);
     }
@@ -265,7 +265,7 @@ function onEditableContextMenu(ev: Event, params: ContextMenuParams, webContents
 
 let userDownloadIndex = 0;
 const userDownloadMap = new Map<number, string>(); // Map from id to path
-ipcMain.on("userDownloadAction", function (ev: IpcMainEvent, { id, open = false }) {
+ipcMain.on("userDownloadAction", function (_ev: IpcMainEvent, { id, open = false }) {
     const path = userDownloadMap.get(id);
     if (open && path) {
         void shell.openPath(path);
@@ -294,8 +294,8 @@ export default (webContents: WebContents): void => {
         }
     });
 
-    webContents.session.on("will-download", (event: Event, item: DownloadItem): void => {
-        item.once("done", (event, state) => {
+    webContents.session.on("will-download", (_event: Event, item: DownloadItem): void => {
+        item.once("done", (_event, state) => {
             if (state === "completed") {
                 const savePath = item.getSavePath();
                 const id = userDownloadIndex++;
diff --git a/yarn.lock b/yarn.lock
index bc1aa093..8463cc97 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1854,46 +1854,6 @@
   dependencies:
     "@opentelemetry/core" "^1.1.0"
 
-"@oxlint/darwin-arm64@0.16.0":
-  version "0.16.0"
-  resolved "https://registry.yarnpkg.com/@oxlint/darwin-arm64/-/darwin-arm64-0.16.0.tgz#a7d69d0bd29a8d99c1a744adda7d5635822f408d"
-  integrity sha512-t4v+WxVuU+cQNZuDDZ+I9p6FTuSrQpTs787UspcB3j3E50lw6+aDWiLx/Snvkn5C214B8hp+z8lnwYkgWoFqiw==
-
-"@oxlint/darwin-x64@0.16.0":
-  version "0.16.0"
-  resolved "https://registry.yarnpkg.com/@oxlint/darwin-x64/-/darwin-x64-0.16.0.tgz#4dac005e8ca0ca11592d906116efa864bf8dd339"
-  integrity sha512-CbV7VHpO7OpBXgBZRaNMOgVlnZ29gocjaFbrbEv/23XqeeDLQP3++O7i1Q7SEmeaELxM6NYW1u9+OcvX3uudwQ==
-
-"@oxlint/linux-arm64-gnu@0.16.0":
-  version "0.16.0"
-  resolved "https://registry.yarnpkg.com/@oxlint/linux-arm64-gnu/-/linux-arm64-gnu-0.16.0.tgz#dd8a8798a16a43dd3103368d1aa6399aeb6b26f6"
-  integrity sha512-wwwTsSk62vFAYYsj4Et/leb9VndZwZBf1R6Nta1yWhljkSVq1GBKJ9SeU3it833QEJuFth2A2L5xdfiGkZZIYg==
-
-"@oxlint/linux-arm64-musl@0.16.0":
-  version "0.16.0"
-  resolved "https://registry.yarnpkg.com/@oxlint/linux-arm64-musl/-/linux-arm64-musl-0.16.0.tgz#5645e52baa284dea52221be60ffbd9df566ffd1a"
-  integrity sha512-YW7g8hG/XJ+g2RgDvhjY/GUaq/p8xIldsQD9AZkFJAaBsmN3tTi1VUS2orhxBi7feXE7FhP85LqQk+WJxarUSw==
-
-"@oxlint/linux-x64-gnu@0.16.0":
-  version "0.16.0"
-  resolved "https://registry.yarnpkg.com/@oxlint/linux-x64-gnu/-/linux-x64-gnu-0.16.0.tgz#b1bcba9644fcb4f8ba2a86d03893068c59b6ccfe"
-  integrity sha512-QY8W3724Fv9W5Mh42/EdV5j4qfwFnV1rouLzvWgUz/g51nROt/6rMbv65ssJo2yBUHHj5KGMfmC97VJZAF9TKA==
-
-"@oxlint/linux-x64-musl@0.16.0":
-  version "0.16.0"
-  resolved "https://registry.yarnpkg.com/@oxlint/linux-x64-musl/-/linux-x64-musl-0.16.0.tgz#f8320a9a40eb6705d4baf3de2849b15f15530ada"
-  integrity sha512-adH6bJipJL/WjaMAc8JNevTgU7IpY5nh8a8tM/DAZdUyt7e/zd+vDw+o3NCBGcCWKu3VcY+XsMZK2NMqnyzeig==
-
-"@oxlint/win32-arm64@0.16.0":
-  version "0.16.0"
-  resolved "https://registry.yarnpkg.com/@oxlint/win32-arm64/-/win32-arm64-0.16.0.tgz#7b4c5bc84ea748edb7b82b3992a35398643b984e"
-  integrity sha512-0GPNs354IHKdbvqsdjf1YGqaKbFWcT/ngly9+oAUSsDC5/Rg4sZj4glZCVDhZUFMQ1kyClAYxX+vbKbTW/cOmQ==
-
-"@oxlint/win32-x64@0.16.0":
-  version "0.16.0"
-  resolved "https://registry.yarnpkg.com/@oxlint/win32-x64/-/win32-x64-0.16.0.tgz#a0f579ffc86897ca3fb014f0bd3c19ddab757acc"
-  integrity sha512-0Lb599lav9THJRiUYkNugueq98VliinY92yzv5u2NDiIsq5aqqHIjmpJ8L051zCEhyzcbw8KBRV3FofqnroJTA==
-
 "@pkgjs/parseargs@^0.11.0":
   version "0.11.0"
   resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
@@ -4901,20 +4861,6 @@ ora@^5.1.0:
     strip-ansi "^6.0.0"
     wcwidth "^1.0.1"
 
-oxlint@^0.16.0:
-  version "0.16.0"
-  resolved "https://registry.yarnpkg.com/oxlint/-/oxlint-0.16.0.tgz#aa564afdd71a300d0e608dfa0a345b576374df9d"
-  integrity sha512-Kx3ehMy+F0sIvg8PPKB967SB7cjjj98vxVOpQaAfKFIYrQFkM10usb3aQKqk1HXYivMvs6axdZM1sLq2fvjbKw==
-  optionalDependencies:
-    "@oxlint/darwin-arm64" "0.16.0"
-    "@oxlint/darwin-x64" "0.16.0"
-    "@oxlint/linux-arm64-gnu" "0.16.0"
-    "@oxlint/linux-arm64-musl" "0.16.0"
-    "@oxlint/linux-x64-gnu" "0.16.0"
-    "@oxlint/linux-x64-musl" "0.16.0"
-    "@oxlint/win32-arm64" "0.16.0"
-    "@oxlint/win32-x64" "0.16.0"
-
 p-cancelable@^2.0.0:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"