mirror of
https://github.com/CringeStudios/element-desktop.git
synced 2025-01-18 23:44:59 +01:00
Merge branch 'develop' of github.com:vector-im/element-desktop into langleyd/fix_seshat_delete_contents
This commit is contained in:
commit
58543536bc
2
.github/workflows/backport.yml
vendored
2
.github/workflows/backport.yml
vendored
@ -10,7 +10,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
backport:
|
backport:
|
||||||
name: Backport
|
name: Backport
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
# Only react to merged PRs for security reasons.
|
# Only react to merged PRs for security reasons.
|
||||||
# See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target.
|
# See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target.
|
||||||
if: >
|
if: >
|
||||||
|
4
.github/workflows/build_and_deploy.yaml
vendored
4
.github/workflows/build_and_deploy.yaml
vendored
@ -99,7 +99,7 @@ jobs:
|
|||||||
- macos
|
- macos
|
||||||
- linux
|
- linux
|
||||||
- windows
|
- windows
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
name: ${{ needs.prepare.outputs.deploy == 'true' && 'Deploy' || 'Deploy (dry-run)' }}
|
name: ${{ needs.prepare.outputs.deploy == 'true' && 'Deploy' || 'Deploy (dry-run)' }}
|
||||||
if: always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled')
|
if: always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled')
|
||||||
environment: ${{ needs.prepare.outputs.deploy == 'true' && 'packages.element.io' || '' }}
|
environment: ${{ needs.prepare.outputs.deploy == 'true' && 'packages.element.io' || '' }}
|
||||||
@ -252,7 +252,7 @@ jobs:
|
|||||||
|
|
||||||
deploy-ess:
|
deploy-ess:
|
||||||
needs: deploy
|
needs: deploy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
name: Deploy builds to ESS
|
name: Deploy builds to ESS
|
||||||
if: needs.prepare.outputs.deploy == 'true' && github.event_name == 'release'
|
if: needs.prepare.outputs.deploy == 'true' && github.event_name == 'release'
|
||||||
env:
|
env:
|
||||||
|
4
.github/workflows/build_and_test.yaml
vendored
4
.github/workflows/build_and_test.yaml
vendored
@ -60,12 +60,12 @@ jobs:
|
|||||||
rsync -a /Volumes/Element/Element.app ~/Applications/ &&
|
rsync -a /Volumes/Element/Element.app ~/Applications/ &&
|
||||||
hdiutil detach /Volumes/Element
|
hdiutil detach /Volumes/Element
|
||||||
- name: "Linux (amd64) (sqlcipher: system)"
|
- name: "Linux (amd64) (sqlcipher: system)"
|
||||||
os: ubuntu-latest
|
os: ubuntu-22.04
|
||||||
artifact: linux-amd64-sqlcipher-system
|
artifact: linux-amd64-sqlcipher-system
|
||||||
executable: "/opt/Element/element-desktop"
|
executable: "/opt/Element/element-desktop"
|
||||||
prepare_cmd: "sudo apt-get -qq update && sudo apt install ./dist/*.deb"
|
prepare_cmd: "sudo apt-get -qq update && sudo apt install ./dist/*.deb"
|
||||||
- name: "Linux (amd64) (sqlcipher: static)"
|
- name: "Linux (amd64) (sqlcipher: static)"
|
||||||
os: ubuntu-latest
|
os: ubuntu-22.04
|
||||||
artifact: linux-amd64-sqlcipher-static
|
artifact: linux-amd64-sqlcipher-static
|
||||||
executable: "/opt/Element/element-desktop"
|
executable: "/opt/Element/element-desktop"
|
||||||
prepare_cmd: "sudo apt-get -qq update && sudo apt install ./dist/*.deb"
|
prepare_cmd: "sudo apt-get -qq update && sudo apt install ./dist/*.deb"
|
||||||
|
6
.github/workflows/build_linux.yaml
vendored
6
.github/workflows/build_linux.yaml
vendored
@ -26,7 +26,7 @@ jobs:
|
|||||||
# We build the hak files on native infrastructure as matrix-seshat fails to cross-compile properly
|
# We build the hak files on native infrastructure as matrix-seshat fails to cross-compile properly
|
||||||
# https://github.com/matrix-org/seshat/issues/135
|
# https://github.com/matrix-org/seshat/issues/135
|
||||||
hak:
|
hak:
|
||||||
runs-on: ${{ inputs.arch == 'arm64' && 'dind-l-arm64' || 'ubuntu-latest' }}
|
runs-on: ${{ inputs.arch == 'arm64' && 'dind-l-arm64' || 'ubuntu-22.04' }}
|
||||||
env:
|
env:
|
||||||
HAK_DOCKER_IMAGE: ghcr.io/element-hq/element-desktop-dockerbuild
|
HAK_DOCKER_IMAGE: ghcr.io/element-hq/element-desktop-dockerbuild
|
||||||
outputs:
|
outputs:
|
||||||
@ -112,7 +112,7 @@ jobs:
|
|||||||
- name: "Get modified files"
|
- name: "Get modified files"
|
||||||
id: changed_files
|
id: changed_files
|
||||||
if: steps.cache.outputs.cache-hit != 'true' && github.event_name == 'pull_request'
|
if: steps.cache.outputs.cache-hit != 'true' && github.event_name == 'pull_request'
|
||||||
uses: tj-actions/changed-files@48d8f15b2aaa3d255ca5af3eba4870f807ce6b3c # v45
|
uses: tj-actions/changed-files@c3a1bb2c992d77180ae65be6ae6c166cf40f857c # v45
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
dockerbuild/**
|
dockerbuild/**
|
||||||
@ -148,7 +148,7 @@ jobs:
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
needs: hak
|
needs: hak
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
6
.github/workflows/build_prepare.yaml
vendored
6
.github/workflows/build_prepare.yaml
vendored
@ -45,7 +45,7 @@ jobs:
|
|||||||
prepare:
|
prepare:
|
||||||
name: Prepare
|
name: Prepare
|
||||||
environment: ${{ inputs.nightly && 'packages.element.io' || '' }}
|
environment: ${{ inputs.nightly && 'packages.element.io' || '' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
outputs:
|
outputs:
|
||||||
nightly-version: ${{ steps.versions.outputs.nightly }}
|
nightly-version: ${{ steps.versions.outputs.nightly }}
|
||||||
steps:
|
steps:
|
||||||
@ -126,8 +126,7 @@ jobs:
|
|||||||
BUNDLE_HASH=$(npx asar l webapp.asar | grep /bundles/ | head -n 1 | sed 's|.*/||')
|
BUNDLE_HASH=$(npx asar l webapp.asar | grep /bundles/ | head -n 1 | sed 's|.*/||')
|
||||||
WEBAPP_VERSION=$(./scripts/get-version.ts)
|
WEBAPP_VERSION=$(./scripts/get-version.ts)
|
||||||
WEB_VERSION=${WEBAPP_VERSION:0:12}
|
WEB_VERSION=${WEBAPP_VERSION:0:12}
|
||||||
REACT_VERSION=${WEBAPP_VERSION:19:12}
|
JS_VERSION=${WEBAPP_VERSION:16:12}
|
||||||
JS_VERSION=${WEBAPP_VERSION:35:12}
|
|
||||||
|
|
||||||
echo "### Nightly build ${{ steps.versions.outputs.nightly }}" >> $GITHUB_STEP_SUMMARY
|
echo "### Nightly build ${{ steps.versions.outputs.nightly }}" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
@ -135,7 +134,6 @@ jobs:
|
|||||||
echo "| ----------- | ------- |" >> $GITHUB_STEP_SUMMARY
|
echo "| ----------- | ------- |" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "| Bundle Hash | $BUNDLE_HASH |" >> $GITHUB_STEP_SUMMARY
|
echo "| Bundle Hash | $BUNDLE_HASH |" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "| Element Web | [$WEB_VERSION](https://github.com/element-hq/element-web/commit/$WEB_VERSION) |" >> $GITHUB_STEP_SUMMARY
|
echo "| Element Web | [$WEB_VERSION](https://github.com/element-hq/element-web/commit/$WEB_VERSION) |" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "| React SDK | [$REACT_VERSION](https://github.com/matrix-org/matrix-react-sdk/commit/$REACT_VERSION) |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| JS SDK | [$JS_VERSION](https://github.com/matrix-org/matrix-js-sdk/commit/$JS_VERSION) |" >> $GITHUB_STEP_SUMMARY
|
echo "| JS SDK | [$JS_VERSION](https://github.com/matrix-org/matrix-js-sdk/commit/$JS_VERSION) |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
|
6
.github/workflows/dockerbuild.yaml
vendored
6
.github/workflows/dockerbuild.yaml
vendored
@ -12,7 +12,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Docker Build
|
name: Docker Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
@ -23,12 +23,12 @@ jobs:
|
|||||||
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3
|
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3
|
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3
|
||||||
with:
|
with:
|
||||||
install: true
|
install: true
|
||||||
|
|
||||||
- name: Log in to the Container registry
|
- name: Log in to the Container registry
|
||||||
uses: docker/login-action@3b8fed7e4b60203b2aa0ecc6c6d6d91d12c06760
|
uses: docker/login-action@1f36f5b7a2d2f7bfd524795fc966e6d88c37baa9
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.REGISTRY }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -26,7 +26,7 @@ jobs:
|
|||||||
check:
|
check:
|
||||||
name: Post release checks
|
name: Post release checks
|
||||||
needs: release
|
needs: release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Wait for desktop packaging
|
- name: Wait for desktop packaging
|
||||||
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
|
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
|
||||||
|
8
.github/workflows/static_analysis.yaml
vendored
8
.github/workflows/static_analysis.yaml
vendored
@ -6,7 +6,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
ts_lint:
|
ts_lint:
|
||||||
name: "Typescript Syntax Check"
|
name: "Typescript Syntax Check"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ jobs:
|
|||||||
|
|
||||||
js_lint:
|
js_lint:
|
||||||
name: "ESLint"
|
name: "ESLint"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ jobs:
|
|||||||
|
|
||||||
workflow_lint:
|
workflow_lint:
|
||||||
name: "Workflow Lint"
|
name: "Workflow Lint"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ jobs:
|
|||||||
|
|
||||||
analyse_dead_code:
|
analyse_dead_code:
|
||||||
name: "Analyse Dead Code"
|
name: "Analyse Dead Code"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
2
.github/workflows/triage-incoming.yml
vendored
2
.github/workflows/triage-incoming.yml
vendored
@ -6,7 +6,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
automate-project-columns-next:
|
automate-project-columns-next:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/add-to-project@main
|
- uses: actions/add-to-project@main
|
||||||
with:
|
with:
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
Changes in [1.11.81](https://github.com/element-hq/element-desktop/releases/tag/v1.11.81) (2024-10-15)
|
||||||
|
======================================================================================================
|
||||||
|
This release fixes High severity vulnerability CVE-2024-47771 / GHSA-963w-49j9-gxj6.
|
||||||
|
|
||||||
Changes in [1.11.80](https://github.com/element-hq/element-desktop/releases/tag/v1.11.80) (2024-10-08)
|
Changes in [1.11.80](https://github.com/element-hq/element-desktop/releases/tag/v1.11.80) (2024-10-08)
|
||||||
======================================================================================================
|
======================================================================================================
|
||||||
## ✨ Features
|
## ✨ Features
|
||||||
|
@ -30,7 +30,11 @@ export default async function buildKeytar(hakEnv: HakEnv, moduleInfo: Dependency
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
proc.on("exit", (code) => {
|
proc.on("exit", (code) => {
|
||||||
code ? reject(code) : resolve();
|
if (code) {
|
||||||
|
reject(code);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,11 @@ export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Prom
|
|||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
});
|
});
|
||||||
proc.on("exit", (code) => {
|
proc.on("exit", (code) => {
|
||||||
code ? reject(code) : resolve();
|
if (code) {
|
||||||
|
reject(code);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -42,7 +46,11 @@ export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Prom
|
|||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
});
|
});
|
||||||
proc.on("exit", (code) => {
|
proc.on("exit", (code) => {
|
||||||
code ? reject(code) : resolve();
|
if (code) {
|
||||||
|
reject(code);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
25
package.json
25
package.json
@ -2,7 +2,7 @@
|
|||||||
"name": "element-desktop",
|
"name": "element-desktop",
|
||||||
"productName": "Element",
|
"productName": "Element",
|
||||||
"main": "lib/electron-main.js",
|
"main": "lib/electron-main.js",
|
||||||
"version": "1.11.80",
|
"version": "1.11.81",
|
||||||
"description": "A feature-rich client for Matrix.org",
|
"description": "A feature-rich client for Matrix.org",
|
||||||
"author": "Element",
|
"author": "Element",
|
||||||
"homepage": "https://element.io",
|
"homepage": "https://element.io",
|
||||||
@ -79,33 +79,34 @@
|
|||||||
"@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",
|
||||||
"@electron/asar": "^3.2.3",
|
"@electron/asar": "3.2.10",
|
||||||
"@electron/fuses": "^1.7.0",
|
"@electron/fuses": "^1.7.0",
|
||||||
"@mapbox/node-pre-gyp": "^1.0.11",
|
"@mapbox/node-pre-gyp": "^1.0.11",
|
||||||
"@playwright/test": "1.47.1",
|
"@playwright/test": "1.48.0",
|
||||||
|
"@stylistic/eslint-plugin": "^2.9.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.54",
|
"@types/node": "18.19.55",
|
||||||
"@types/pacote": "^11.1.1",
|
"@types/pacote": "^11.1.1",
|
||||||
"@types/tar": "^6.1.3",
|
"@types/tar": "^6.1.3",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
"@types/yargs": "^17.0.32",
|
"@types/yargs": "^17.0.32",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
||||||
"@typescript-eslint/parser": "^7.0.0",
|
"@typescript-eslint/parser": "^8.0.0",
|
||||||
"app-builder-lib": "24.13.3",
|
"app-builder-lib": "25.1.8",
|
||||||
"chokidar": "^4.0.0",
|
"chokidar": "^4.0.0",
|
||||||
"detect-libc": "^2.0.0",
|
"detect-libc": "^2.0.0",
|
||||||
"electron": "^32.0.0",
|
"electron": "^32.0.0",
|
||||||
"electron-builder": "24.13.3",
|
"electron-builder": "25.1.8",
|
||||||
"electron-builder-squirrel-windows": "24.13.3",
|
"electron-builder-squirrel-windows": "25.1.8",
|
||||||
"electron-devtools-installer": "^3.2.0",
|
"electron-devtools-installer": "^3.2.0",
|
||||||
"eslint": "^8.26.0",
|
"eslint": "^8.26.0",
|
||||||
"eslint-config-google": "^0.14.0",
|
"eslint-config-google": "^0.14.0",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.0.0",
|
||||||
"eslint-plugin-import": "^2.25.4",
|
"eslint-plugin-import": "^2.25.4",
|
||||||
"eslint-plugin-matrix-org": "^1.0.0",
|
"eslint-plugin-matrix-org": "^2.0.1",
|
||||||
"eslint-plugin-unicorn": "^55.0.0",
|
"eslint-plugin-unicorn": "^56.0.0",
|
||||||
"glob": "^11.0.0",
|
"glob": "^11.0.0",
|
||||||
"knip": "^5.0.0",
|
"knip": "^5.0.0",
|
||||||
"matrix-web-i18n": "^3.2.1",
|
"matrix-web-i18n": "^3.2.1",
|
||||||
@ -122,7 +123,7 @@
|
|||||||
"keytar": "^7.9.0"
|
"keytar": "^7.9.0"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@types/node": "18.19.54",
|
"@types/node": "18.19.55",
|
||||||
"config-file-ts": "0.2.8-rc1"
|
"config-file-ts": "0.2.8-rc1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM mcr.microsoft.com/playwright:v1.46.1-jammy
|
FROM mcr.microsoft.com/playwright:v1.48.1-jammy
|
||||||
|
|
||||||
WORKDIR /work/element-desktop
|
WORKDIR /work/element-desktop
|
||||||
|
|
||||||
|
BIN
res/img/monochrome.ico
Normal file
BIN
res/img/monochrome.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
res/img/monochrome.png
Normal file
BIN
res/img/monochrome.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.3 KiB |
@ -28,7 +28,7 @@ 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 {}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,14 +150,14 @@ 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 (e) {}
|
} catch {}
|
||||||
|
|
||||||
if (!haveDeploy) {
|
if (!haveDeploy) {
|
||||||
const outPath = path.join(pkgDir, filename);
|
const outPath = path.join(pkgDir, filename);
|
||||||
try {
|
try {
|
||||||
await fs.stat(outPath);
|
await fs.stat(outPath);
|
||||||
console.log("Already have " + filename + ": not redownloading");
|
console.log("Already have " + filename + ": not redownloading");
|
||||||
} catch (e) {
|
} catch {
|
||||||
try {
|
try {
|
||||||
await downloadToFile(url, outPath);
|
await downloadToFile(url, outPath);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -170,7 +170,7 @@ async function main(): Promise<number | undefined> {
|
|||||||
try {
|
try {
|
||||||
await fs.stat(outPath + ".asc");
|
await fs.stat(outPath + ".asc");
|
||||||
console.log("Already have " + filename + ".asc: not redownloading");
|
console.log("Already have " + filename + ".asc: not redownloading");
|
||||||
} catch (e) {
|
} catch {
|
||||||
try {
|
try {
|
||||||
await downloadToFile(url + ".asc", outPath + ".asc");
|
await downloadToFile(url + ".asc", outPath + ".asc");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -206,7 +206,7 @@ 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 (e) {}
|
} catch {}
|
||||||
|
|
||||||
if (cfgDir.length) {
|
if (cfgDir.length) {
|
||||||
const configJsonSource = path.join(cfgDir, "config.json");
|
const configJsonSource = path.join(cfgDir, "config.json");
|
||||||
|
@ -18,7 +18,7 @@ export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo):
|
|||||||
try {
|
try {
|
||||||
const stats = await fsProm.stat(moduleInfo.moduleBuildDir);
|
const stats = await fsProm.stat(moduleInfo.moduleBuildDir);
|
||||||
haveModuleBuildDir = stats.isDirectory();
|
haveModuleBuildDir = stats.isDirectory();
|
||||||
} catch (e) {
|
} catch {
|
||||||
haveModuleBuildDir = false;
|
haveModuleBuildDir = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,11 @@ export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo):
|
|||||||
shell: hakEnv.isWin(),
|
shell: hakEnv.isWin(),
|
||||||
});
|
});
|
||||||
proc.on("exit", (code) => {
|
proc.on("exit", (code) => {
|
||||||
code ? reject(code) : resolve();
|
if (code) {
|
||||||
|
reject(code);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -31,8 +31,9 @@ async function main(): Promise<void> {
|
|||||||
const prefix = path.join(__dirname, "..", "..");
|
const prefix = path.join(__dirname, "..", "..");
|
||||||
let packageJson;
|
let packageJson;
|
||||||
try {
|
try {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
packageJson = require(path.join(prefix, "package.json"));
|
packageJson = require(path.join(prefix, "package.json"));
|
||||||
} catch (e) {
|
} catch {
|
||||||
console.error("Can't find a package.json!");
|
console.error("Can't find a package.json!");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@ -69,8 +70,9 @@ async function main(): Promise<void> {
|
|||||||
const hakJsonPath = path.join(prefix, "hak", dep, "hak.json");
|
const hakJsonPath = path.join(prefix, "hak", dep, "hak.json");
|
||||||
let hakJson: Record<string, any>;
|
let hakJson: Record<string, any>;
|
||||||
try {
|
try {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
hakJson = await require(hakJsonPath);
|
hakJson = await require(hakJsonPath);
|
||||||
} catch (e) {
|
} catch {
|
||||||
console.error("No hak.json found for " + dep + ".");
|
console.error("No hak.json found for " + dep + ".");
|
||||||
console.log("Expecting " + hakJsonPath);
|
console.log("Expecting " + hakJsonPath);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -24,7 +24,7 @@ export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo):
|
|||||||
// Also we do this for each module which is unnecessary, but meh.
|
// Also we do this for each module which is unnecessary, but meh.
|
||||||
try {
|
try {
|
||||||
await fsProm.stat(yarnrc);
|
await fsProm.stat(yarnrc);
|
||||||
} catch (e) {
|
} catch {
|
||||||
await fsProm.writeFile(
|
await fsProm.writeFile(
|
||||||
yarnrc,
|
yarnrc,
|
||||||
// XXX: 1. This must be absolute, as yarn will resolve link directories
|
// XXX: 1. This must be absolute, as yarn will resolve link directories
|
||||||
@ -50,7 +50,11 @@ export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo):
|
|||||||
shell: hakEnv.isWin(),
|
shell: hakEnv.isWin(),
|
||||||
});
|
});
|
||||||
proc.on("exit", (code) => {
|
proc.on("exit", (code) => {
|
||||||
code ? reject(code) : resolve();
|
if (code) {
|
||||||
|
reject(code);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -63,7 +67,11 @@ export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo):
|
|||||||
shell: hakEnv.isWin(),
|
shell: hakEnv.isWin(),
|
||||||
});
|
});
|
||||||
proc.on("exit", (code) => {
|
proc.on("exit", (code) => {
|
||||||
code ? reject(code) : resolve();
|
if (code) {
|
||||||
|
reject(code);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import * as childProcess from "child_process";
|
|||||||
export async function versionFromAsar(): Promise<string> {
|
export async function versionFromAsar(): Promise<string> {
|
||||||
try {
|
try {
|
||||||
await fs.stat("webapp.asar");
|
await fs.stat("webapp.asar");
|
||||||
} catch (e) {
|
} catch {
|
||||||
throw new Error("No 'webapp.asar' found. Run 'yarn run fetch'");
|
throw new Error("No 'webapp.asar' found. Run 'yarn run fetch'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
src/@types/global.d.ts
vendored
5
src/@types/global.d.ts
vendored
@ -20,8 +20,8 @@ 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
|
color_icon_path: string; // eslint-disable-line camelcase
|
||||||
icon_path: string;
|
monochrome_icon_path: string; // eslint-disable-line camelcase
|
||||||
brand: string;
|
brand: string;
|
||||||
};
|
};
|
||||||
var store: Store<{
|
var store: Store<{
|
||||||
@ -31,6 +31,7 @@ declare global {
|
|||||||
autoHideMenuBar?: boolean;
|
autoHideMenuBar?: boolean;
|
||||||
locale?: string | string[];
|
locale?: string | string[];
|
||||||
disableHardwareAcceleration?: boolean;
|
disableHardwareAcceleration?: boolean;
|
||||||
|
monochromeIcon?: boolean;
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
/* eslint-enable no-var */
|
/* eslint-enable no-var */
|
||||||
|
@ -97,7 +97,7 @@ 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 (e) {}
|
} catch {}
|
||||||
}
|
}
|
||||||
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) {
|
||||||
@ -137,7 +137,7 @@ async function loadConfig(): Promise<void> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
global.vectorConfig = loadJsonFile(asarPath, "config.json");
|
global.vectorConfig = loadJsonFile(asarPath, "config.json");
|
||||||
} catch (e) {
|
} catch {
|
||||||
// it would be nice to check the error code here and bail if the config
|
// it would be nice to check the error code here and bail if the config
|
||||||
// is unparsable, but we get MODULE_NOT_FOUND in the case of a missing
|
// is unparsable, but we get MODULE_NOT_FOUND in the case of a missing
|
||||||
// file or invalid json, so node is just very unhelpful.
|
// file or invalid json, so node is just very unhelpful.
|
||||||
@ -212,9 +212,11 @@ async function setupGlobals(): Promise<void> {
|
|||||||
|
|
||||||
// The tray icon
|
// The tray icon
|
||||||
// It's important to call `path.join` so we don't end up with the packaged asar in the final path.
|
// It's important to call `path.join` so we don't end up with the packaged asar in the final path.
|
||||||
const iconFile = `element.${process.platform === "win32" ? "ico" : "png"}`;
|
const colorIconFile = `element.${process.platform === "win32" ? "ico" : "png"}`;
|
||||||
|
const monochromeIconFile = `monochrome.${process.platform === "win32" ? "ico" : "png"}`;
|
||||||
global.trayConfig = {
|
global.trayConfig = {
|
||||||
icon_path: path.join(resPath, "img", iconFile),
|
monochrome_icon_path: path.join(resPath, "img", monochromeIconFile),
|
||||||
|
color_icon_path: path.join(resPath, "img", colorIconFile),
|
||||||
brand: global.vectorConfig.brand || "Element",
|
brand: global.vectorConfig.brand || "Element",
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -365,7 +367,7 @@ app.on("ready", async () => {
|
|||||||
|
|
||||||
if (argv["devtools"]) {
|
if (argv["devtools"]) {
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
const { default: installExt, REACT_DEVELOPER_TOOLS, REACT_PERF } = require("electron-devtools-installer");
|
const { default: installExt, REACT_DEVELOPER_TOOLS, REACT_PERF } = require("electron-devtools-installer");
|
||||||
installExt(REACT_DEVELOPER_TOOLS)
|
installExt(REACT_DEVELOPER_TOOLS)
|
||||||
.then((name: string) => console.log(`Added Extension: ${name}`))
|
.then((name: string) => console.log(`Added Extension: ${name}`))
|
||||||
@ -453,7 +455,7 @@ app.on("ready", async () => {
|
|||||||
titleBarStyle: process.platform === "darwin" ? "hidden" : "default",
|
titleBarStyle: process.platform === "darwin" ? "hidden" : "default",
|
||||||
trafficLightPosition: { x: 9, y: 8 },
|
trafficLightPosition: { x: 9, y: 8 },
|
||||||
|
|
||||||
icon: global.trayConfig.icon_path,
|
icon: global.trayConfig.color_icon_path,
|
||||||
show: false,
|
show: false,
|
||||||
autoHideMenuBar: global.store.get("autoHideMenuBar", true),
|
autoHideMenuBar: global.store.get("autoHideMenuBar", true),
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
|
|||||||
if (ret === null) {
|
if (ret === null) {
|
||||||
ret = await keytar?.getPassword("riot.im", `${args[0]}|${args[1]}`);
|
ret = await keytar?.getPassword("riot.im", `${args[0]}|${args[1]}`);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch {
|
||||||
// if an error is thrown (e.g. keytar can't connect to the keychain),
|
// if an error is thrown (e.g. keytar can't connect to the keychain),
|
||||||
// then return null, which means the default pickle key will be used
|
// then return null, which means the default pickle key will be used
|
||||||
ret = null;
|
ret = null;
|
||||||
@ -159,7 +159,7 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
|
|||||||
const pickleKey = await randomArray(32);
|
const pickleKey = await randomArray(32);
|
||||||
await keytar?.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey);
|
await keytar?.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey);
|
||||||
ret = pickleKey;
|
ret = pickleKey;
|
||||||
} catch (e) {
|
} catch {
|
||||||
ret = null;
|
ret = null;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -170,7 +170,7 @@ 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 (e) {}
|
} catch {}
|
||||||
break;
|
break;
|
||||||
case "getDesktopCapturerSources":
|
case "getDesktopCapturerSources":
|
||||||
ret = (await desktopCapturer.getSources(args[0])).map((source) => ({
|
ret = (await desktopCapturer.getSources(args[0])).map((source) => ({
|
||||||
|
@ -9,7 +9,7 @@ import type * as Keytar from "keytar"; // Hak dependency type
|
|||||||
|
|
||||||
let keytar: typeof Keytar | undefined;
|
let keytar: typeof Keytar | undefined;
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
keytar = require("keytar");
|
keytar = require("keytar");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if ((<NodeJS.ErrnoException>e).code === "MODULE_NOT_FOUND") {
|
if ((<NodeJS.ErrnoException>e).code === "MODULE_NOT_FOUND") {
|
||||||
|
@ -33,39 +33,74 @@ async function getAccessToken(window: BrowserWindow): Promise<string | undefined
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the homeserver url
|
||||||
|
* This requires asking the renderer process for the homeserver url.
|
||||||
|
*/
|
||||||
|
async function getHomeserverUrl(window: BrowserWindow): Promise<string> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
ipcMain.once("homeserverUrl", (_, homeserver) => {
|
||||||
|
resolve(homeserver);
|
||||||
|
});
|
||||||
|
window.webContents.send("homeserverUrl"); // ping now that the listener exists
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function setupMediaAuth(window: BrowserWindow): void {
|
export function setupMediaAuth(window: BrowserWindow): void {
|
||||||
session.defaultSession.webRequest.onBeforeRequest(async (req, callback) => {
|
session.defaultSession.webRequest.onBeforeRequest(async (req, callback) => {
|
||||||
// This handler emulates the element-web service worker, where URLs are rewritten late in the request
|
// This handler emulates the element-web service worker, where URLs are rewritten late in the request
|
||||||
// for backwards compatibility. As authenticated media becomes more prevalent, this should be replaced
|
// for backwards compatibility. As authenticated media becomes more prevalent, this should be replaced
|
||||||
// by the app using authenticated URLs from the outset.
|
// by the app using authenticated URLs from the outset.
|
||||||
let url = req.url;
|
try {
|
||||||
if (!url.includes("/_matrix/media/v3/download") && !url.includes("/_matrix/media/v3/thumbnail")) {
|
const url = new URL(req.url);
|
||||||
return callback({}); // not a URL we care about
|
if (
|
||||||
}
|
!url.pathname.startsWith("/_matrix/media/v3/download") &&
|
||||||
|
!url.pathname.startsWith("/_matrix/media/v3/thumbnail")
|
||||||
|
) {
|
||||||
|
return callback({}); // not a URL we care about
|
||||||
|
}
|
||||||
|
|
||||||
const supportedVersions = await getSupportedVersions(window);
|
const supportedVersions = await getSupportedVersions(window);
|
||||||
// We have to check that the access token is truthy otherwise we'd be intercepting pre-login media request too,
|
// We have to check that the access token is truthy otherwise we'd be intercepting pre-login media request too,
|
||||||
// e.g. those required for SSO button icons.
|
// e.g. those required for SSO button icons.
|
||||||
const accessToken = await getAccessToken(window);
|
const accessToken = await getAccessToken(window);
|
||||||
if (supportedVersions.includes("v1.11") && accessToken) {
|
if (supportedVersions.includes("v1.11") && accessToken) {
|
||||||
url = url.replace(/\/media\/v3\/(.*)\//, "/client/v1/media/$1/");
|
url.href = url.href.replace(/\/media\/v3\/(.*)\//, "/client/v1/media/$1/");
|
||||||
return callback({ redirectURL: url });
|
return callback({ redirectURL: url.toString() });
|
||||||
} else {
|
} else {
|
||||||
return callback({}); // no support == no modification
|
return callback({}); // no support == no modification
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
session.defaultSession.webRequest.onBeforeSendHeaders(async (req, callback) => {
|
session.defaultSession.webRequest.onBeforeSendHeaders(async (req, callback) => {
|
||||||
if (!req.url.includes("/_matrix/client/v1/media")) {
|
try {
|
||||||
return callback({}); // invoke unmodified
|
const url = new URL(req.url);
|
||||||
}
|
if (!url.pathname.startsWith("/_matrix/client/v1/media")) {
|
||||||
|
return callback({}); // invoke unmodified
|
||||||
|
}
|
||||||
|
|
||||||
// Only add authorization header to authenticated media URLs. This emulates the service worker
|
// Is this request actually going to the homeserver?
|
||||||
// behaviour in element-web.
|
// We don't combine this check with the one above on purpose.
|
||||||
const accessToken = await getAccessToken(window);
|
// We're fetching the homeserver url through IPC and should do so
|
||||||
// `accessToken` can be falsy, but if we're trying to download media without authentication
|
// as sparingly as possible.
|
||||||
// then we should expect failure anyway.
|
const homeserver = await getHomeserverUrl(window);
|
||||||
const headers = { ...req.requestHeaders, Authorization: `Bearer ${accessToken}` };
|
const isRequestToHomeServer = homeserver && url.origin === new URL(homeserver).origin;
|
||||||
return callback({ requestHeaders: headers });
|
if (!isRequestToHomeServer) {
|
||||||
|
return callback({}); // invoke unmodified
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only add authorization header to authenticated media URLs. This emulates the service worker
|
||||||
|
// behaviour in element-web.
|
||||||
|
const accessToken = await getAccessToken(window);
|
||||||
|
// `accessToken` can be falsy, but if we're trying to download media without authentication
|
||||||
|
// then we should expect failure anyway.
|
||||||
|
const headers = { ...req.requestHeaders, Authorization: `Bearer ${accessToken}` };
|
||||||
|
return callback({ requestHeaders: headers });
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ const CHANNELS = [
|
|||||||
"userDownloadAction",
|
"userDownloadAction",
|
||||||
"openDesktopCapturerSourcePicker",
|
"openDesktopCapturerSourcePicker",
|
||||||
"userAccessToken",
|
"userAccessToken",
|
||||||
|
"homeserverUrl",
|
||||||
"serverSupportedVersions",
|
"serverSupportedVersions",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ function readStore(): Record<string, string> {
|
|||||||
const s = fs.readFileSync(storePath, { encoding: "utf8" });
|
const s = fs.readFileSync(storePath, { encoding: "utf8" });
|
||||||
const o = JSON.parse(s);
|
const o = JSON.parse(s);
|
||||||
return typeof o === "object" ? o : {};
|
return typeof o === "object" ? o : {};
|
||||||
} catch (e) {
|
} catch {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ let SeshatRecovery: typeof SeshatRecoveryType;
|
|||||||
let ReindexError: typeof ReindexErrorType;
|
let ReindexError: typeof ReindexErrorType;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
const seshatModule = require("matrix-seshat");
|
const seshatModule = require("matrix-seshat");
|
||||||
Seshat = seshatModule.Seshat;
|
Seshat = seshatModule.Seshat;
|
||||||
SeshatRecovery = seshatModule.SeshatRecovery;
|
SeshatRecovery = seshatModule.SeshatRecovery;
|
||||||
@ -267,7 +267,7 @@ ipcMain.on("seshat", async function (_ev: IpcMainEvent, payload): Promise<void>
|
|||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
ret = await eventIndex.loadCheckpoints();
|
ret = await eventIndex.loadCheckpoints();
|
||||||
} catch (e) {
|
} catch {
|
||||||
ret = [];
|
ret = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,4 +67,13 @@ export const Settings: Record<string, Setting> = {
|
|||||||
global.store.set("disableHardwareAcceleration", !value);
|
global.store.set("disableHardwareAcceleration", !value);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"Electron.monochromeIcon": {
|
||||||
|
async read(): Promise<any> {
|
||||||
|
return tray.isMonochrome();
|
||||||
|
},
|
||||||
|
async write(value: any): Promise<void> {
|
||||||
|
global.store.set("monochromeIcon", value);
|
||||||
|
tray.refreshIcon();
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
20
src/tray.ts
20
src/tray.ts
@ -28,6 +28,19 @@ export function destroy(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isMonochrome(): boolean {
|
||||||
|
return global.store.get("monochromeIcon", process.platform === "linux");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function refreshIcon(): void {
|
||||||
|
const monochrome = isMonochrome();
|
||||||
|
if (monochrome) {
|
||||||
|
trayIcon?.setImage(nativeImage.createFromPath(global.trayConfig.monochrome_icon_path));
|
||||||
|
} else {
|
||||||
|
trayIcon?.setImage(nativeImage.createFromPath(global.trayConfig.color_icon_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function toggleWin(): void {
|
function toggleWin(): void {
|
||||||
if (global.mainWindow?.isVisible() && !global.mainWindow.isMinimized() && global.mainWindow.isFocused()) {
|
if (global.mainWindow?.isVisible() && !global.mainWindow.isMinimized() && global.mainWindow.isFocused()) {
|
||||||
global.mainWindow.hide();
|
global.mainWindow.hide();
|
||||||
@ -39,7 +52,8 @@ function toggleWin(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface IConfig {
|
interface IConfig {
|
||||||
icon_path: string; // eslint-disable-line camelcase
|
color_icon_path: string; // eslint-disable-line camelcase
|
||||||
|
monochrome_icon_path: string; // eslint-disable-line camelcase
|
||||||
brand: string;
|
brand: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +66,9 @@ function getUuid(): string {
|
|||||||
export function create(config: IConfig): void {
|
export function create(config: IConfig): void {
|
||||||
// no trays on darwin
|
// no trays on darwin
|
||||||
if (process.platform === "darwin" || trayIcon) return;
|
if (process.platform === "darwin" || trayIcon) return;
|
||||||
const defaultIcon = nativeImage.createFromPath(config.icon_path);
|
const defaultIcon = nativeImage.createFromPath(
|
||||||
|
isMonochrome() ? config.monochrome_icon_path : config.color_icon_path,
|
||||||
|
);
|
||||||
|
|
||||||
let guid: string | undefined;
|
let guid: string | undefined;
|
||||||
if (process.platform === "win32" && app.isPackaged) {
|
if (process.platform === "win32" && app.isPackaged) {
|
||||||
|
@ -176,15 +176,18 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
|
|||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
function cutCopyPasteSelectContextMenus(params: ContextMenuParams): MenuItemConstructorOptions[] {
|
function cutCopyPasteSelectContextMenus(
|
||||||
|
params: ContextMenuParams,
|
||||||
|
webContents: WebContents,
|
||||||
|
): MenuItemConstructorOptions[] {
|
||||||
const options: MenuItemConstructorOptions[] = [];
|
const options: MenuItemConstructorOptions[] = [];
|
||||||
|
|
||||||
if (params.misspelledWord) {
|
if (params.misspelledWord) {
|
||||||
params.dictionarySuggestions.forEach((word) => {
|
params.dictionarySuggestions.forEach((word) => {
|
||||||
options.push({
|
options.push({
|
||||||
label: word,
|
label: word,
|
||||||
click: (menuItem, browserWindow) => {
|
click: () => {
|
||||||
browserWindow?.webContents.replaceMisspelling(word);
|
webContents.replaceMisspelling(word);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -194,8 +197,8 @@ function cutCopyPasteSelectContextMenus(params: ContextMenuParams): MenuItemCons
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: _t("right_click_menu|add_to_dictionary"),
|
label: _t("right_click_menu|add_to_dictionary"),
|
||||||
click: (menuItem, browserWindow) => {
|
click: () => {
|
||||||
browserWindow?.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord);
|
webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -237,8 +240,8 @@ function cutCopyPasteSelectContextMenus(params: ContextMenuParams): MenuItemCons
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSelectedContextMenu(ev: Event, params: ContextMenuParams): void {
|
function onSelectedContextMenu(ev: Event, params: ContextMenuParams, webContents: WebContents): void {
|
||||||
const items = cutCopyPasteSelectContextMenus(params);
|
const items = cutCopyPasteSelectContextMenus(params, webContents);
|
||||||
const popupMenu = Menu.buildFromTemplate(items);
|
const popupMenu = Menu.buildFromTemplate(items);
|
||||||
|
|
||||||
// popup() requires an options object even for no options
|
// popup() requires an options object even for no options
|
||||||
@ -246,12 +249,12 @@ function onSelectedContextMenu(ev: Event, params: ContextMenuParams): void {
|
|||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onEditableContextMenu(ev: Event, params: ContextMenuParams): void {
|
function onEditableContextMenu(ev: Event, params: ContextMenuParams, webContents: WebContents): void {
|
||||||
const items: MenuItemConstructorOptions[] = [
|
const items: MenuItemConstructorOptions[] = [
|
||||||
{ role: "undo" },
|
{ role: "undo" },
|
||||||
{ role: "redo", enabled: params.editFlags.canRedo },
|
{ role: "redo", enabled: params.editFlags.canRedo },
|
||||||
{ type: "separator" },
|
{ type: "separator" },
|
||||||
...cutCopyPasteSelectContextMenus(params),
|
...cutCopyPasteSelectContextMenus(params, webContents),
|
||||||
];
|
];
|
||||||
|
|
||||||
const popupMenu = Menu.buildFromTemplate(items);
|
const popupMenu = Menu.buildFromTemplate(items);
|
||||||
@ -286,9 +289,9 @@ export default (webContents: WebContents): void => {
|
|||||||
if (params.linkURL || params.srcURL) {
|
if (params.linkURL || params.srcURL) {
|
||||||
onLinkContextMenu(ev, params, webContents);
|
onLinkContextMenu(ev, params, webContents);
|
||||||
} else if (params.selectionText) {
|
} else if (params.selectionText) {
|
||||||
onSelectedContextMenu(ev, params);
|
onSelectedContextMenu(ev, params, webContents);
|
||||||
} else if (params.isEditable) {
|
} else if (params.isEditable) {
|
||||||
onEditableContextMenu(ev, params);
|
onEditableContextMenu(ev, params, webContents);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user