Merge bec02c96d417299828ad1434d1dc566d1e0d7a70 into 7c858d358bfd3e54ba6958aabb3badcc164067eb

This commit is contained in:
Michael Telatynski 2025-03-18 09:58:17 +00:00 committed by GitHub
commit bc238b4ca0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 355 additions and 1798 deletions

View File

@ -1,88 +0,0 @@
module.exports = {
plugins: ["matrix-org", "n"],
extends: ["plugin:matrix-org/javascript"],
parserOptions: {
ecmaVersion: 2021,
project: ["tsconfig.json"],
},
env: {
es6: true,
node: true,
// we also have some browser code (ie. the preload script)
browser: true,
},
// NOTE: These rules are frozen and new rules should not be added here.
// New changes belong in https://github.com/matrix-org/eslint-plugin-matrix-org/
rules: {
"quotes": "off",
"indent": "off",
"prefer-promise-reject-errors": "off",
"no-async-promise-executor": "off",
"n/file-extension-in-import": ["error", "always"],
"unicorn/prefer-node-protocol": ["error"],
},
overrides: [
{
files: ["src/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
{
files: ["hak/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
parserOptions: {
project: ["hak/tsconfig.json"],
},
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
{
files: ["scripts/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
parserOptions: {
project: ["scripts/tsconfig.json"],
},
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
{
files: ["playwright/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
parserOptions: {
project: ["playwright/tsconfig.json"],
},
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
],
};

View File

@ -1,4 +1,3 @@
{ {
"*": "prettier --write", "*": ["biome check --no-errors-on-unmatched --files-ignore-unknown=true"]
"*.(ts|tsx)": ["eslint --fix"]
} }

View File

@ -1,21 +0,0 @@
/build/
/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

View File

@ -1 +0,0 @@
module.exports = require("eslint-plugin-matrix-org/.prettierrc.js");

136
biome.jsonc Normal file
View File

@ -0,0 +1,136 @@
{
"$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,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 4,
"lineEnding": "lf",
"lineWidth": 120,
"attributePosition": "auto",
"bracketSpacing": true
},
"organizeImports": { "enabled": true },
"linter": {
"enabled": true,
"rules": {
"recommended": false,
"complexity": {
"noExtraBooleanCast": "error",
"noMultipleSpacesInRegularExpressionLiterals": "error",
"noUselessCatch": "error",
"noWith": "error"
},
"correctness": {
"noConstAssign": "error",
"noConstantCondition": "error",
"noEmptyCharacterClassInRegex": "error",
"noEmptyPattern": "error",
"noGlobalObjectCalls": "error",
"noInnerDeclarations": "error",
"noInvalidConstructorSuper": "error",
"noNewSymbol": "error",
"noNonoctalDecimalEscape": "error",
"noPrecisionLoss": "error",
"noSelfAssign": "error",
"noSetterReturn": "error",
"noSwitchDeclarations": "error",
"noUndeclaredVariables": "error",
"noUnreachable": "error",
"noUnreachableSuper": "error",
"noUnsafeFinally": "error",
"noUnsafeOptionalChaining": "error",
"noUnusedLabels": "error",
"noUnusedVariables": "error",
"useArrayLiterals": "error",
"useIsNan": "error",
"useValidForDirection": "error",
"useYield": "error"
},
"style": {
"noArguments": "error",
"noVar": "error",
"useBlockStatements": "off",
"useConsistentBuiltinInstantiation": "error",
"useConst": "error",
"useNodejsImportProtocol": "error",
"useSingleVarDeclarator": "error",
"useThrowOnlyError": "error",
"useImportType": "error",
"useExportType": "error"
},
"suspicious": {
"noAssignInExpressions": "error",
"noAsyncPromiseExecutor": "error",
"noCatchAssign": "error",
"noClassAssign": "error",
"noCompareNegZero": "error",
"noConsole": "off",
"noControlCharactersInRegex": "error",
"noDebugger": "error",
"noDuplicateCase": "error",
"noDuplicateClassMembers": "error",
"noDuplicateObjectKeys": "error",
"noDuplicateParameters": "error",
"noEmptyBlockStatements": "error",
"noFallthroughSwitchClause": "error",
"noFunctionAssign": "error",
"noGlobalAssign": "error",
"noImportAssign": "error",
"noMisleadingCharacterClass": "error",
"noPrototypeBuiltins": "error",
"noRedeclare": "error",
"noShadowRestrictedNames": "error",
"noSparseArray": "error",
"noUnsafeNegation": "error",
"useGetterReturn": "error",
"useIsArray": "error",
"useValidTypeof": "error"
}
}
},
"javascript": {
"formatter": {
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "all",
"semicolons": "always",
"arrowParentheses": "always",
"bracketSameLine": false,
"quoteStyle": "double",
"attributePosition": "auto",
"bracketSpacing": true
}
},
"overrides": [
{
"include": ["src/**/*.ts", "hak/**/*.ts", "scripts/**/*.ts", "playwright/**/*.ts"],
"linter": {
"rules": {
"style": { "noNonNullAssertion": "off" },
"suspicious": { "noExplicitAny": "off" }
}
}
},
{
"include": ["playwright/**/*.ts"],
"linter": {
"rules": {
"correctness": {
"noEmptyPattern": "off"
}
}
}
}
]
}

View File

@ -1,10 +1,10 @@
import * as os from "node:os";
import * as fs from "node:fs"; 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 { 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. * This script has different outputs depending on your os platform.

View File

@ -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. 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 { DependencyInfo } from "../../scripts/hak/dep.js";
import type HakEnv from "../../scripts/hak/hakEnv.js";
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> { export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const env = hakEnv.makeGypEnv(); const env = hakEnv.makeGypEnv();

View File

@ -9,11 +9,11 @@ Please see LICENSE files in the repository root for full details.
import childProcess from "node:child_process"; import childProcess from "node:child_process";
import fsProm from "node:fs/promises"; import fsProm from "node:fs/promises";
import type { DependencyInfo } from "../../scripts/hak/dep.js";
import type HakEnv from "../../scripts/hak/hakEnv.js"; import type HakEnv from "../../scripts/hak/hakEnv.js";
import type { Tool } 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> { export default async function (hakEnv: HakEnv, _moduleInfo: DependencyInfo): Promise<void> {
const tools: Tool[] = [ const tools: Tool[] = [
["rustc", "--version"], ["rustc", "--version"],
["python", "--version"], // node-gyp uses python for reasons beyond comprehension ["python", "--version"], // node-gyp uses python for reasons beyond comprehension
@ -33,7 +33,7 @@ export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Prom
const rustc = childProcess.execFile( const rustc = childProcess.execFile(
"rustc", "rustc",
["--target", hakEnv.getTargetId(), "--emit=obj", "-o", "tmp", "-"], ["--target", hakEnv.getTargetId(), "--emit=obj", "-o", "tmp", "-"],
(err, out) => { (err) => {
if (err) { if (err) {
reject( reject(
"rustc can't build for target " + "rustc can't build for target " +

View File

@ -1,4 +1,4 @@
import { KnipConfig } from "knip"; import type { KnipConfig } from "knip";
export default { export default {
entry: ["src/electron-main.ts", "src/preload.ts", "electron-builder.ts", ".eslintrc-*.js", "scripts/**", "hak/**"], entry: ["src/electron-main.ts", "src/preload.ts", "electron-builder.ts", ".eslintrc-*.js", "scripts/**", "hak/**"],

View File

@ -20,15 +20,15 @@
"scripts": { "scripts": {
"i18n": "matrix-gen-i18n && yarn i18n:sort && yarn i18n:lint", "i18n": "matrix-gen-i18n && yarn i18n:sort && yarn i18n:lint",
"i18n:sort": "jq --sort-keys '.' src/i18n/strings/en_EN.json > src/i18n/strings/en_EN.json.tmp && mv src/i18n/strings/en_EN.json.tmp src/i18n/strings/en_EN.json", "i18n:sort": "jq --sort-keys '.' src/i18n/strings/en_EN.json > src/i18n/strings/en_EN.json.tmp && mv src/i18n/strings/en_EN.json.tmp src/i18n/strings/en_EN.json",
"i18n:lint": "prettier --log-level=silent --write src/i18n/strings/ --ignore-path /dev/null", "i18n:lint": "biome format --log-level=none --write src/i18n/strings/",
"i18n:diff": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && yarn i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json", "i18n:diff": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && yarn i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
"mkdirs": "mkdirp packages deploys", "mkdirs": "mkdirp packages deploys",
"fetch": "yarn run mkdirs && tsx scripts/fetch-package.ts", "fetch": "yarn run mkdirs && tsx scripts/fetch-package.ts",
"asar-webapp": "asar p webapp webapp.asar", "asar-webapp": "asar p webapp webapp.asar",
"start": "yarn run build:ts && yarn run build:res && electron .", "start": "yarn run build:ts && yarn run build:res && electron .",
"lint": "yarn lint:types && yarn lint:js && yarn lint:workflows", "lint": "yarn lint:types && yarn lint:js && yarn lint:workflows",
"lint:js": "eslint --max-warnings 0 src hak playwright scripts && prettier --check .", "lint:js": "biome check",
"lint:js-fix": "eslint --fix --max-warnings 0 src hak playwright scripts && prettier --log-level=warn --write .", "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": "yarn lint:types:src && yarn lint:types:test && yarn lint:types:scripts && yarn lint:types:hak",
"lint:types:src": "tsc --noEmit", "lint:types:src": "tsc --noEmit",
"lint:types:test": "tsc --noEmit -p playwright/tsconfig.json", "lint:types:test": "tsc --noEmit -p playwright/tsconfig.json",
@ -74,16 +74,14 @@
"@babel/core": "^7.18.10", "@babel/core": "^7.18.10",
"@babel/preset-env": "^7.18.10", "@babel/preset-env": "^7.18.10",
"@babel/preset-typescript": "^7.18.6", "@babel/preset-typescript": "^7.18.6",
"@biomejs/biome": "^1.9.4",
"@electron/asar": "3.3.1", "@electron/asar": "3.3.1",
"@playwright/test": "1.51.0", "@playwright/test": "1.51.0",
"@stylistic/eslint-plugin": "^3.0.0",
"@types/auto-launch": "^5.0.1", "@types/auto-launch": "^5.0.1",
"@types/counterpart": "^0.18.1", "@types/counterpart": "^0.18.1",
"@types/minimist": "^1.2.1", "@types/minimist": "^1.2.1",
"@types/node": "18.19.79", "@types/node": "18.19.79",
"@types/pacote": "^11.1.1", "@types/pacote": "^11.1.1",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"app-builder-lib": "26.0.11", "app-builder-lib": "26.0.11",
"chokidar": "^4.0.0", "chokidar": "^4.0.0",
"detect-libc": "^2.0.0", "detect-libc": "^2.0.0",
@ -91,13 +89,6 @@
"electron-builder": "26.0.11", "electron-builder": "26.0.11",
"electron-builder-squirrel-windows": "26.0.11", "electron-builder-squirrel-windows": "26.0.11",
"electron-devtools-installer": "^4.0.0", "electron-devtools-installer": "^4.0.0",
"eslint": "^8.26.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^10.0.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-matrix-org": "^2.0.1",
"eslint-plugin-n": "^17.12.0",
"eslint-plugin-unicorn": "^56.0.0",
"glob": "^11.0.0", "glob": "^11.0.0",
"husky": "^9.1.6", "husky": "^9.1.6",
"knip": "^5.0.0", "knip": "^5.0.0",
@ -106,7 +97,6 @@
"mkdirp": "^3.0.0", "mkdirp": "^3.0.0",
"pacote": "^21.0.0", "pacote": "^21.0.0",
"plist": "^3.1.0", "plist": "^3.1.0",
"prettier": "^3.0.0",
"rimraf": "^6.0.0", "rimraf": "^6.0.0",
"tar": "^7.0.0", "tar": "^7.0.0",
"tsx": "^4.19.2", "tsx": "^4.19.2",

View File

@ -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. 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 { 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)); const __dirname = dirname(fileURLToPath(import.meta.url));

View File

@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
import { platform } from "node:os"; import { platform } from "node:os";
import { test, expect } from "../../element-desktop-test.js"; import { expect, test } from "../../element-desktop-test.js";
declare global { declare global {
interface Window { interface Window {
@ -63,7 +63,7 @@ test.describe("App launch", () => {
// XXX: this test works fine locally but in CI the app start races with the test plumbing up the stdout/stderr pipes // XXX: this test works fine locally but in CI the app start races with the test plumbing up the stdout/stderr pipes
// which means the logs are missed, disabling for now. // which means the logs are missed, disabling for now.
test.skip("should respect option", async ({ page, stdout }) => { test.skip("should respect option", async ({ page: _page, stdout }) => {
expect(stdout.data.toString()).toContain("Auto update disabled via command line flag"); expect(stdout.data.toString()).toContain("Auto update disabled via command line flag");
}); });
}); });

View File

@ -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. 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 fs from "node:fs/promises";
import path, { dirname } from "node:path";
import os from "node:os"; import os from "node:os";
import { fileURLToPath } from "node:url"; import path, { dirname } from "node:path";
import { PassThrough } from "node:stream"; 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. * A PassThrough stream that captures all data written to it.
@ -50,16 +50,13 @@ export const test = base.extend<Fixtures>({
extraEnv: {}, extraEnv: {},
extraArgs: [], extraArgs: [],
// eslint-disable-next-line no-empty-pattern
stdout: async ({}, use) => { stdout: async ({}, use) => {
await use(new CapturedPassThrough()); await use(new CapturedPassThrough());
}, },
// eslint-disable-next-line no-empty-pattern
stderr: async ({}, use) => { stderr: async ({}, use) => {
await use(new CapturedPassThrough()); await use(new CapturedPassThrough());
}, },
// eslint-disable-next-line no-empty-pattern
tmpDir: async ({}, use) => { tmpDir: async ({}, use) => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "element-desktop-tests-")); const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "element-desktop-tests-"));
console.log("Using temp profile directory: ", tmpDir); console.log("Using temp profile directory: ", tmpDir);

View File

@ -2,10 +2,10 @@
// copies resources into the lib directory. // 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 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), {}); const argv = parseArgs(process.argv.slice(2), {});

View File

@ -1,11 +1,11 @@
#!/usr/bin/env -S npx tsx --resolveJsonModule #!/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 childProcess from "node:child_process";
import * as tar from "tar"; import { promises as fs, createWriteStream } from "node:fs";
import * as asar from "@electron/asar"; import * as path from "node:path";
import { promises as stream } from "node:stream"; import { promises as stream } from "node:stream";
import * as asar from "@electron/asar";
import * as tar from "tar";
import riotDesktopPackageJson from "../package.json"; import riotDesktopPackageJson from "../package.json";
import { setPackageVersion } from "./set-version.js"; import { setPackageVersion } from "./set-version.js";
@ -27,7 +27,9 @@ async function downloadToFile(url: string, filename: string): Promise<void> {
console.error(e); console.error(e);
try { try {
await fs.unlink(filename); await fs.unlink(filename);
} catch {} } catch {
// ignore
}
throw e; throw e;
} }
} }
@ -151,7 +153,9 @@ async function main(): Promise<number | undefined> {
await fs.opendir(expectedDeployDir); await fs.opendir(expectedDeployDir);
console.log(expectedDeployDir + "already exists"); console.log(expectedDeployDir + "already exists");
haveDeploy = true; haveDeploy = true;
} catch {} } catch {
// ignore
}
if (!haveDeploy) { if (!haveDeploy) {
const outPath = path.join(pkgDir, filename); const outPath = path.join(pkgDir, filename);
@ -207,7 +211,9 @@ async function main(): Promise<number | undefined> {
await fs.stat(ASAR_PATH); await fs.stat(ASAR_PATH);
console.log(ASAR_PATH + " already present: removing"); console.log(ASAR_PATH + " already present: removing");
await fs.unlink(ASAR_PATH); await fs.unlink(ASAR_PATH);
} catch {} } catch {
// ignore
}
if (cfgDir.length) { if (cfgDir.length) {
const configJsonSource = path.join(cfgDir, "config.json"); const configJsonSource = path.join(cfgDir, "config.json");

View File

@ -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. 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 childProcess from "node:child_process";
import fsProm from "node:fs/promises";
import path from "node:path";
import { glob } from "glob"; import { glob } from "glob";
import { mkdirp } from "mkdirp"; import { mkdirp } from "mkdirp";
import type HakEnv from "./hakEnv.js";
import type { DependencyInfo } from "./dep.js"; import type { DependencyInfo } from "./dep.js";
import type HakEnv from "./hakEnv.js";
export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> { export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
if (moduleInfo.cfg.copy) { if (moduleInfo.cfg.copy) {

View File

@ -9,8 +9,8 @@ Please see LICENSE files in the repository root for full details.
import fsProm from "node:fs/promises"; import fsProm from "node:fs/promises";
import pacote from "pacote"; import pacote from "pacote";
import type HakEnv from "./hakEnv.js";
import type { DependencyInfo } from "./dep.js"; import type { DependencyInfo } from "./dep.js";
import type HakEnv from "./hakEnv.js";
export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> { export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
let haveModuleBuildDir; let haveModuleBuildDir;

View File

@ -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. 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 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> { async function getRuntimeVersion(projectRoot: string): Promise<string> {
const electronVersion = await getElectronVersionFromInstalled(projectRoot); const electronVersion = await getElectronVersionFromInstalled(projectRoot);

View File

@ -9,11 +9,11 @@ Please see LICENSE files in the repository root for full details.
import path, { dirname } from "node:path"; import path, { dirname } from "node:path";
import { fileURLToPath } from "node:url"; 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 HakEnv from "./hakEnv.js";
import type { TargetId } from "./target.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 // These can only be run on specific modules
const MODULECOMMANDS = ["check", "fetch", "link", "build", "copy", "clean"]; 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 // Can be specified multiple times for the copy command to bundle
// multiple arches into a single universal output module) // multiple arches into a single universal output module)
for (;;) { for (;;) {
// eslint-disable-line no-constant-condition
const targetIndex = process.argv.indexOf("--target"); const targetIndex = process.argv.indexOf("--target");
if (targetIndex === -1) break; if (targetIndex === -1) break;

View File

@ -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. 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 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 HakEnv from "./hakEnv.js";
import { type DependencyInfo } from "./dep.js";
export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> { export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const yarnrc = path.join(hakEnv.projectRoot, ".yarnrc"); const yarnrc = path.join(hakEnv.projectRoot, ".yarnrc");

View File

@ -5,10 +5,10 @@
* version metadata of the package to match. * 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 * as childProcess from "node:child_process";
import { promises as fs } from "node:fs";
import * as url from "node:url"; import * as url from "node:url";
import * as asar from "@electron/asar";
export async function versionFromAsar(): Promise<string> { export async function versionFromAsar(): Promise<string> {
try { try {

View File

@ -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. 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 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 // global type extensions need to use var for whatever reason
/* eslint-disable no-var */
declare global { declare global {
var mainWindow: BrowserWindow | null; var mainWindow: BrowserWindow | null;
var appQuitting: boolean; var appQuitting: boolean;
@ -20,7 +19,6 @@ declare global {
var launcher: AutoLaunch; var launcher: AutoLaunch;
var vectorConfig: Record<string, any>; var vectorConfig: Record<string, any>;
var trayConfig: { var trayConfig: {
// eslint-disable-next-line camelcase
icon_path: string; icon_path: string;
brand: string; brand: string;
}; };
@ -33,4 +31,3 @@ declare global {
disableHardwareAcceleration?: boolean; disableHardwareAcceleration?: boolean;
}>; }>;
} }
/* eslint-enable no-var */

View File

@ -11,7 +11,6 @@ declare module "matrix-seshat" {
passphrase?: string; passphrase?: string;
} }
/* eslint-disable camelcase */
interface IMatrixEvent { interface IMatrixEvent {
event_id: string; event_id: string;
sender: string; sender: string;
@ -49,7 +48,6 @@ declare module "matrix-seshat" {
context: ISearchContext; context: ISearchContext;
}>; }>;
} }
/* eslint-enable camelcase */
interface ICheckpoint { interface ICheckpoint {
roomId: string; roomId: string;

View File

@ -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. // 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 "./squirrelhooks.js";
import { app, BrowserWindow, Menu, autoUpdater, protocol, dialog, type Input, type Event, session } from "electron"; import fs, { promises as afs } from "node:fs";
// eslint-disable-next-line n/file-extension-in-import import path, { dirname } from "node:path";
import { URL, fileURLToPath } from "node:url";
import * as Sentry from "@sentry/electron/main"; import * as Sentry from "@sentry/electron/main";
import AutoLaunch from "auto-launch"; import AutoLaunch from "auto-launch";
import path, { dirname } from "node:path"; import { BrowserWindow, type Event, type Input, Menu, app, autoUpdater, dialog, protocol, session } from "electron";
import windowStateKeeper from "electron-window-state";
import Store from "electron-store"; import Store from "electron-store";
import fs, { promises as afs } from "node:fs"; import windowStateKeeper from "electron-window-state";
import { URL, fileURLToPath } from "node:url";
import minimist from "minimist"; import minimist from "minimist";
import "./ipc.js"; import "./ipc.js";
import "./seshat.js"; import "./seshat.js";
import "./settings.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 tray from "./tray.js";
import * as updater from "./updater.js";
import { loadJsonFile } from "./utils.js";
import { buildMenuTemplate } from "./vectormenu.js"; import { buildMenuTemplate } from "./vectormenu.js";
import webContentsHandler from "./webcontents-handler.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)); const __dirname = dirname(fileURLToPath(import.meta.url));
@ -105,7 +104,9 @@ async function tryPaths(name: string, root: string, rawPaths: string[]): Promise
try { try {
await afs.stat(p); await afs.stat(p);
return p + "/"; return p + "/";
} catch {} } catch {
// ignore
}
} }
console.log(`Couldn't find ${name} files in any of: `); console.log(`Couldn't find ${name} files in any of: `);
for (const p of paths) { for (const p of paths) {
@ -528,7 +529,7 @@ app.on("ready", async () => {
if (process.platform === "win32") { if (process.platform === "win32") {
// Handle forward/backward mouse buttons in Windows // 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()) { if (cmd === "browser-backward" && global.mainWindow?.webContents.canGoBack()) {
global.mainWindow.webContents.goBack(); global.mainWindow.webContents.goBack();
} else if (cmd === "browser-forward" && global.mainWindow?.webContents.canGoForward()) { } else if (cmd === "browser-forward" && global.mainWindow?.webContents.canGoForward()) {
@ -568,7 +569,7 @@ function beforeQuit(): void {
app.on("before-quit", beforeQuit); app.on("before-quit", beforeQuit);
autoUpdater.on("before-quit-for-update", beforeQuit); autoUpdater.on("before-quit-for-update", beforeQuit);
app.on("second-instance", (ev, commandLine, workingDirectory) => { app.on("second-instance", (_ev, commandLine) => {
// If other instance launched with --hidden then skip showing window // If other instance launched with --hidden then skip showing window
if (commandLine.includes("--hidden")) return; if (commandLine.includes("--hidden")) return;

View File

@ -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. 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 { relaunchApp } from "@standardnotes/electron-clear-data";
import {
type IpcMainEvent,
TouchBar,
app,
autoUpdater,
desktopCapturer,
ipcMain,
nativeImage,
powerSaveBlocker,
} from "electron";
import keytar from "keytar-forked"; 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 { 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 { ipcMain.on("setBadgeCount", function (_ev: IpcMainEvent, count: number): void {
if (process.platform !== "win32") { 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 // migrate from riot.im (remove once we think there will no longer be
// logins from the time of riot.im) // logins from the time of riot.im)
await keytar.deletePassword("riot.im", `${args[0]}|${args[1]}`); await keytar.deletePassword("riot.im", `${args[0]}|${args[1]}`);
} catch {} } catch (e) {
console.error("Failed to destroy pickle key", e);
}
break; break;
case "getDesktopCapturerSources": case "getDesktopCapturerSources":
ret = (await desktopCapturer.getSources(args[0])).map((source) => ({ ret = (await desktopCapturer.getSources(args[0])).map((source) => ({

View File

@ -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. 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 { dirname } from "node:path";
import { fileURLToPath } from "node:url"; 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 Store from "electron-store";
import type EN from "./i18n/strings/en_EN.json"; import type EN from "./i18n/strings/en_EN.json";
@ -79,7 +79,6 @@ export class AppLocalization {
this.store = store; this.store = store;
if (this.store.has(AppLocalization.STORE_KEY)) { if (this.store.has(AppLocalization.STORE_KEY)) {
const locales = this.store.get(AppLocalization.STORE_KEY); const locales = this.store.get(AppLocalization.STORE_KEY);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.setAppLocale(locales!); this.setAppLocale(locales!);
} }

View File

@ -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. // 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 // Expose only expected IPC wrapper APIs to the renderer process to avoid
// handing out generalised messaging access. // handing out generalised messaging access.

View File

@ -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. 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 fs from "node:fs";
import path from "node:path";
import { URL } from "node:url";
import { app } from "electron";
const LEGACY_PROTOCOL = "element"; const LEGACY_PROTOCOL = "element";
const PROTOCOL = "io.element.desktop"; const PROTOCOL = "io.element.desktop";
@ -115,7 +115,7 @@ export function protocolInit(): void {
}); });
} else { } else {
// Protocol handler for win32/Linux // Protocol handler for win32/Linux
app.on("second-instance", (ev, commandLine) => { app.on("second-instance", (_ev, commandLine) => {
const url = commandLine[commandLine.length - 1]; const url = commandLine[commandLine.length - 1];
if (!url.startsWith(`${PROTOCOL}://`) && !url.startsWith(`${LEGACY_PROTOCOL}://`)) return; if (!url.startsWith(`${PROTOCOL}://`) && !url.startsWith(`${LEGACY_PROTOCOL}://`)) return;
processUrl(url); processUrl(url);

View File

@ -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. Please see LICENSE files in the repository root for full details.
*/ */
import { app, ipcMain } from "electron";
import { promises as afs } from "node:fs"; import { promises as afs } from "node:fs";
import path from "node:path"; import path from "node:path";
import { type IpcMainEvent, app, ipcMain } from "electron";
import keytar from "keytar-forked"; import keytar from "keytar-forked";
import type { import type {
Seshat as SeshatType,
SeshatRecovery as SeshatRecoveryType,
ReindexError as ReindexErrorType, ReindexError as ReindexErrorType,
SeshatRecovery as SeshatRecoveryType,
Seshat as SeshatType,
} from "matrix-seshat"; // Hak dependency type } from "matrix-seshat"; // Hak dependency type
import IpcMainEvent = Electron.IpcMainEvent;
import { randomArray } from "./utils.js"; import { randomArray } from "./utils.js";
let seshatSupported = false; let seshatSupported = false;

View File

@ -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. Please see LICENSE files in the repository root for full details.
*/ */
import path from "node:path";
import { spawn } from "node:child_process"; import { spawn } from "node:child_process";
import path from "node:path";
import { app } from "electron"; import { app } from "electron";
export function getSquirrelExecutable(): string { export function getSquirrelExecutable(): string {

View File

@ -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. 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 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 { v5 as uuidv5 } from "uuid";
import { _t } from "./language-helper.js"; import { _t } from "./language-helper.js";
@ -39,7 +39,7 @@ function toggleWin(): void {
} }
interface IConfig { interface IConfig {
icon_path: string; // eslint-disable-line camelcase icon_path: string;
brand: string; brand: string;
} }
@ -72,7 +72,7 @@ export function create(config: IConfig): void {
trayIcon.on("click", toggleWin); trayIcon.on("click", toggleWin);
let lastFavicon: string | null = null; 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 (!favicons || favicons.length <= 0 || !favicons[0].startsWith("data:")) {
if (lastFavicon !== null) { if (lastFavicon !== null) {
global.mainWindow?.setIcon(defaultIcon); global.mainWindow?.setIcon(defaultIcon);
@ -103,7 +103,7 @@ export function create(config: IConfig): void {
global.mainWindow?.setIcon(newFavicon); 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); trayIcon?.setToolTip(title);
}); });
} }

View File

@ -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. Please see LICENSE files in the repository root for full details.
*/ */
import { app, autoUpdater, ipcMain } from "electron";
import fs from "node:fs/promises"; import fs from "node:fs/promises";
import { app, autoUpdater, ipcMain } from "electron";
import { getSquirrelExecutable } from "./squirrelhooks.js"; import { getSquirrelExecutable } from "./squirrelhooks.js";
@ -165,7 +165,7 @@ autoUpdater
ipcChannelSendUpdateStatus(error.message); ipcChannelSendUpdateStatus(error.message);
}); });
autoUpdater.on("update-downloaded", (ev, releaseNotes, releaseName, releaseDate, updateURL) => { autoUpdater.on("update-downloaded", (_ev, releaseNotes, releaseName, releaseDate, updateURL) => {
// forward to renderer // forward to renderer
latestUpdateDownloaded = { releaseNotes, releaseName, releaseDate, updateURL }; latestUpdateDownloaded = { releaseNotes, releaseName, releaseDate, updateURL };
global.mainWindow?.webContents.send("update-downloaded", latestUpdateDownloaded); global.mainWindow?.webContents.send("update-downloaded", latestUpdateDownloaded);

View File

@ -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. 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"; import { _t } from "./language-helper.js";

View File

@ -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. 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 { import {
clipboard,
nativeImage,
Menu,
MenuItem,
shell,
dialog,
ipcMain,
type NativeImage,
type WebContents,
type ContextMenuParams, type ContextMenuParams,
type DownloadItem, type DownloadItem,
type MenuItemConstructorOptions,
type IpcMainEvent,
type Event, type Event,
type IpcMainEvent,
Menu,
MenuItem,
type MenuItemConstructorOptions,
type NativeImage,
type WebContents,
clipboard,
dialog,
ipcMain,
nativeImage,
shell,
} from "electron"; } 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"; import { _t } from "./language-helper.js";
@ -75,7 +75,7 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
if (url.startsWith("vector://vector/webapp")) { if (url.startsWith("vector://vector/webapp")) {
// Avoid showing a context menu for app icons // Avoid showing a context menu for app icons
if (params.hasImageContents) return; 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 // Rewrite URL so that it can be used outside the app
url = baseUrl + url.substring(23); url = baseUrl + url.substring(23);
} }
@ -265,7 +265,7 @@ function onEditableContextMenu(ev: Event, params: ContextMenuParams, webContents
let userDownloadIndex = 0; let userDownloadIndex = 0;
const userDownloadMap = new Map<number, string>(); // Map from id to path 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); const path = userDownloadMap.get(id);
if (open && path) { if (open && path) {
void shell.openPath(path); void shell.openPath(path);
@ -294,8 +294,8 @@ export default (webContents: WebContents): void => {
} }
}); });
webContents.session.on("will-download", (event: Event, item: DownloadItem): void => { webContents.session.on("will-download", (_event: Event, item: DownloadItem): void => {
item.once("done", (event, state) => { item.once("done", (_event, state) => {
if (state === "completed") { if (state === "completed") {
const savePath = item.getSavePath(); const savePath = item.getSavePath();
const id = userDownloadIndex++; const id = userDownloadIndex++;

1644
yarn.lock

File diff suppressed because it is too large Load Diff