mirror of
https://github.com/Novaloop-AG/healthchat-web.git
synced 2026-11-11 02:38:39 +00:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 66bfe9250e | |||
| b1e36ff959 | |||
| dcfd82b773 | |||
| c66c7797e4 | |||
| 04ccaf3e78 | |||
| 11e3f90c81 | |||
| 45bbbd7379 | |||
| 8f15f0352f | |||
| 6f8df665ff | |||
| 697c7efe15 | |||
| 637eaa7356 | |||
| 30bb2bfca3 | |||
| 09e66dba47 | |||
| 8530b1f09a | |||
| 10a380bc81 | |||
| ab295d810c | |||
| 675e812f00 | |||
| 831a928d04 | |||
| f345ca55b3 | |||
| ab91e1a7bc | |||
| be3ab5fb3d | |||
| f33708c705 | |||
| ce7f9230c3 | |||
| 5e3f235442 | |||
| 0d2ccb9d59 | |||
| a9cd6fabb4 | |||
| 745069128f | |||
| 1697be5239 | |||
| 209cd37d0f | |||
| d2aa9ef7a0 | |||
| 8a2754c7c0 | |||
| ead9847d76 | |||
| 9d53c2b131 | |||
| 22b2d8ca6f | |||
| dd461ddca9 | |||
| 8b4b63b245 | |||
| c2b11111dd |
@@ -9,24 +9,57 @@ Releases are driven by git tags of the form `healthchat-v<semver>` pushed to
|
||||
`origin`. The tag triggers two workflows in parallel:
|
||||
|
||||
- `.github/workflows/build-healthchat.yaml` (web) — builds the HealthChat Docker
|
||||
image, publishes it to ghcr.io under `healthchat-web:<version>`, `:stable`, and
|
||||
image, publishes it to ghcr.io under `healthchat-web:<version>`, `:latest`, and
|
||||
`:<sha>`, and creates a GitHub Release whose body is the matching section of
|
||||
`HEALTHCHAT_CHANGES.md`.
|
||||
|
||||
**`:latest` is the tag production deploys from.** It only moves for a clean
|
||||
`X.Y.Z` **tag push** — never for `-rc1`/`-hotfix1`/`-dryrun1` tags, and never for
|
||||
a manual `workflow_dispatch` run. Those builds still publish `:<version>` and
|
||||
`:<sha>`, so you can deploy them deliberately by overriding the image ref (see
|
||||
"Deploying the release"), but they can never become production by accident.
|
||||
- `.github/workflows/build-healthchat-desktop.yaml` (desktop) — builds the Electron
|
||||
app for macOS (universal, signed+notarised) and Windows (x64/arm64, signed), and
|
||||
attaches the installers (.dmg/.zip/.exe/.msi) to the **same** GitHub Release. The two
|
||||
workflows create-if-missing then upload, so they race safely. (Linux is intentionally
|
||||
not built — the upstream Linux reusable pulls a build-env Docker image keyed by commit
|
||||
SHA that only exists in the upstream element-hq registry, so it cannot succeed in this
|
||||
fork.) The `release` job additionally **mirrors the Squirrel update feed and the public
|
||||
installers to `https://healthchat.ch/packages/desktop/` over FTPS** (the private GitHub
|
||||
Release can serve neither end users nor the auto-updater). This is what makes installed
|
||||
apps self-update; see `apps/desktop/element.io/healthchat/README` for the feed layout and
|
||||
app for macOS (universal, signed+notarised) and Windows (x64/arm64, signed) and
|
||||
publishes to the **same** GitHub Release as the web workflow (both create-if-missing,
|
||||
so they race safely). (Linux is intentionally not built — the upstream Linux reusable
|
||||
pulls a build-env Docker image keyed by commit SHA that only exists in the upstream
|
||||
element-hq registry, so it cannot succeed in this fork.) The `release` job **stages**
|
||||
the Squirrel update feed and public installers and uploads them to the versioned
|
||||
archive at `https://packages.healthchat.ch/desktop-releases/<version>/` — but it
|
||||
**does not publish them** to the live feed. Nothing binary is attached to the GitHub
|
||||
Release (the compressed feed outgrew GitHub's 2 GiB per-asset cap at 1.6.0); the
|
||||
Release notes get a "## Downloads" section linking the installers' public URLs on
|
||||
packages.healthchat.ch, which resolve once the version is deployed. See "Deploying
|
||||
the desktop release" below.
|
||||
- `.github/workflows/deploy-healthchat-desktop.yaml` (desktop deploy) — **manual
|
||||
dispatch only.** Fetches the staged archive for the requested version and mirrors it
|
||||
to the live feed at `https://packages.healthchat.ch/desktop/` over FTPS (the private
|
||||
GitHub Release can serve neither end users nor the auto-updater). The pre-1.6.0 feed
|
||||
at `https://healthchat.ch/packages/desktop/` is retired and frozen at 1.5.0 — installs
|
||||
that old must reinstall once from the new download URL. This is what makes installed apps
|
||||
self-update; see `apps/desktop/element.io/healthchat/README` for the feed layout and
|
||||
the two caveats (first install is manual; Windows auto-update needs the Setup.exe path,
|
||||
not the .msi).
|
||||
|
||||
Publish target: **ghcr.io Docker image + GitHub Release (web bundle + desktop
|
||||
installers).** No npm, no mobile fan-out.
|
||||
Publish target: **ghcr.io Docker image + versioned feed archive on
|
||||
packages.healthchat.ch + GitHub Release (web bundle + installer download links).**
|
||||
No npm, no mobile fan-out.
|
||||
|
||||
## Release ≠ deploy
|
||||
|
||||
Cutting a tag never changes what any user is running. Both halves of the deployment are
|
||||
separate, manual, and need no code change:
|
||||
|
||||
| Component | Released by | Deployed by |
|
||||
| --- | --- | --- |
|
||||
| Web (ghcr.io image) | `healthchat-v*` tag push → `:latest` moves | `gh workflow run deploy.yml` on the ansible repo |
|
||||
| Desktop (update feed) | `healthchat-v*` tag push → staged feed archive on packages.healthchat.ch | `gh workflow run deploy-healthchat-desktop.yaml` |
|
||||
|
||||
Writing the desktop feed pushes an update to **every installed client**, so it is a
|
||||
deployment, not a publication step — hence the same manual gate as the server side.
|
||||
Deploy the two together unless you have a reason not to: a desktop client talks to the
|
||||
web deployment, so leaving one behind means users run a client built against a different
|
||||
release.
|
||||
|
||||
The desktop app version is taken from `apps/desktop/package.json` (the per-job
|
||||
`version` input cannot set it — Windows squirrel mangles it into a nightly string,
|
||||
@@ -99,6 +132,123 @@ Examples:
|
||||
The workflow triggers automatically. Watch it via `gh run watch` or GitHub
|
||||
Actions UI.
|
||||
|
||||
## Deploying the release
|
||||
|
||||
Publishing the image does **not** deploy it. Deployment is a separate manual
|
||||
dispatch against the ansible repo — but it needs **no code change anywhere**: the
|
||||
inventory pins `matrix_client_element_container_image` to
|
||||
`ghcr.io/novaloop-ag/healthchat-web/healthchat-web:latest`, and the ansible role pulls
|
||||
with `pull: always`, so it picks up whatever `:latest` now points at and restarts
|
||||
the container only if the digest actually moved.
|
||||
|
||||
The image path is derived from the repository name
|
||||
(`format('{0}/healthchat-web', github.repository)`). Renaming the repository moves
|
||||
the image to a new package and the old one stops receiving builds, so the inventory
|
||||
pin must follow. This happened on 2026-07-29 when `element-web` became
|
||||
`healthchat-web`; 1.7.0 was the first release that hit it.
|
||||
|
||||
Wait for the release workflow to go green first (the deploy pulls whatever is in the
|
||||
registry at that moment), then:
|
||||
|
||||
```bash
|
||||
gh workflow run deploy.yml \
|
||||
--repo Novaloop-AG/matrix-docker-ansible-deploy \
|
||||
--ref release/healthchat \
|
||||
-f command="install-service client-element"
|
||||
```
|
||||
|
||||
Watch it: `gh run watch --repo Novaloop-AG/matrix-docker-ansible-deploy`.
|
||||
|
||||
Or via the UI: GitHub → `Novaloop-AG/matrix-docker-ansible-deploy` → Actions →
|
||||
"Deploy HealthChat (Synapse, Web app etc.)" → Run workflow → **command:**
|
||||
`install-service client-element`.
|
||||
|
||||
Add `-f check_mode=true` for a dry run (`--check --diff`).
|
||||
|
||||
### Deploying a specific version instead of `:latest`
|
||||
|
||||
RCs, hotfix tags and dispatch builds do not move `:latest`. To ship one — or to roll
|
||||
back — pass an explicit image ref through `extra_args`, which the workflow forwards
|
||||
verbatim to `ansible-playbook`. **No inventory edit, no commit:**
|
||||
|
||||
```bash
|
||||
gh workflow run deploy.yml \
|
||||
--repo Novaloop-AG/matrix-docker-ansible-deploy \
|
||||
--ref release/healthchat \
|
||||
-f command="install-service client-element" \
|
||||
-f extra_args="-e matrix_client_element_container_image=ghcr.io/novaloop-ag/healthchat-web/healthchat-web:1.5.0"
|
||||
```
|
||||
|
||||
Note this is a one-shot override: the *next* plain deploy returns to `:latest`. For a
|
||||
sustained hold, pin the version in the inventory instead.
|
||||
|
||||
### Confirming what actually shipped
|
||||
|
||||
Because the inventory tracks `:latest`, git no longer records the deployed version —
|
||||
check the running app, not the repo:
|
||||
|
||||
```bash
|
||||
curl -fsS https://app.healthchat.ch/version
|
||||
```
|
||||
|
||||
That serves the build version baked in by `scripts/docker-package.sh` (e.g.
|
||||
`healthchat-v1.5.0`). If it still reports the old version, the deploy either did not
|
||||
run or `:latest` had not moved yet.
|
||||
|
||||
## Deploying the desktop release
|
||||
|
||||
The desktop build stages the feed at
|
||||
`https://packages.healthchat.ch/desktop-releases/<version>/` but
|
||||
leaves the live feed at `https://packages.healthchat.ch/desktop/` untouched. Until you run this, installed
|
||||
apps keep whatever version they have and the public download links still serve the old
|
||||
installers.
|
||||
|
||||
Wait for "Build HealthChat Desktop" to go green, then:
|
||||
|
||||
```bash
|
||||
gh workflow run deploy-healthchat-desktop.yaml \
|
||||
--ref release/healthchat \
|
||||
-f version=1.5.0
|
||||
```
|
||||
|
||||
Or: GitHub → Actions → "Deploy HealthChat Desktop" → Run workflow → **version:** `1.5.0`.
|
||||
|
||||
Dry run first if you want to see what would be written without touching the server:
|
||||
|
||||
```bash
|
||||
gh workflow run deploy-healthchat-desktop.yaml \
|
||||
--ref release/healthchat \
|
||||
-f version=1.5.0 -f dry_run=true
|
||||
```
|
||||
|
||||
The workflow refuses to publish a partial feed — it fails before contacting the server if
|
||||
`releases.json`, either arch's `RELEASES`, or the macOS `*-mac.zip` payload is missing. A
|
||||
half-written feed breaks auto-update for everyone already installed, which is much worse
|
||||
than not deploying.
|
||||
|
||||
On success it curls the five load-bearing URLs and fails if any is not 200, so a green run
|
||||
means the feed is genuinely live. Installed apps pick it up on their next update check.
|
||||
|
||||
### Deploying an RC or rolling back
|
||||
|
||||
`version` accepts any released version, including `1.5.0-rc1`. Because staged feeds
|
||||
persist in the versioned archive (`desktop-releases/<version>/`), **re-running this
|
||||
workflow with an older version republishes that feed** — no rebuild, no re-signing.
|
||||
That is the desktop rollback path:
|
||||
|
||||
```bash
|
||||
gh workflow run deploy-healthchat-desktop.yaml --ref release/healthchat -f version=1.4.1
|
||||
```
|
||||
|
||||
Caveat: `mirror -R` does not delete, so rolling back rewrites the manifests but leaves the
|
||||
newer `*.nupkg` files in place. That is intentional — Squirrel.Windows needs the delta
|
||||
history — and harmless, since clients follow `RELEASES`/`releases.json`, not directory
|
||||
listings.
|
||||
|
||||
Versions with no staged archive (cut before the archive design) fail the deploy with a
|
||||
pointer; dispatch "Build HealthChat Desktop" with `version=<version>` to rebuild and
|
||||
stage that version, then re-run the deploy.
|
||||
|
||||
## Manual / retry path (workflow_dispatch)
|
||||
|
||||
Use when retrying a failed run, testing the pipeline, or rebuilding an image
|
||||
@@ -112,12 +262,16 @@ without moving tags.
|
||||
lookup.
|
||||
3. Run. Docker image is pushed. **No GitHub Release is created on the dispatch
|
||||
path** — only the tag-push path creates Releases (keeps manual retries from
|
||||
clobbering the release history).
|
||||
clobbering the release history). **`:latest` is not moved either**, for the same
|
||||
reason: a retry or pipeline test must not become production. The build still
|
||||
publishes `:<version>` and `:<sha>`; deploy it with the explicit-version
|
||||
override in "Deploying the release" if that is what you want.
|
||||
|
||||
The desktop workflow ("Build HealthChat Desktop") has its own workflow_dispatch
|
||||
with the same inputs; like the web path, its `release` job only publishes on a
|
||||
real tag push, so a manual dispatch builds and uploads run artifacts but does not
|
||||
attach anything to a Release.
|
||||
with the same inputs. Its `release` job **also runs on dispatch** to (re)stage the
|
||||
feed archive at `desktop-releases/<version>/` — that is the recovery path when a
|
||||
version's archive is missing — but the GitHub Release steps (create + Downloads
|
||||
links) stay tag-only, so a dispatch can never touch release history.
|
||||
|
||||
## Tag format
|
||||
|
||||
@@ -161,22 +315,44 @@ warning. Prefer fixing the changelog over relying on the fallback.
|
||||
## After the release
|
||||
|
||||
- [ ] Workflow run is green in GitHub Actions.
|
||||
- [ ] `docker pull ghcr.io/<owner>/healthchat-web:<version>` succeeds.
|
||||
- [ ] `docker pull ghcr.io/novaloop-ag/healthchat-web/healthchat-web:<version>` succeeds.
|
||||
(Note the image path contains the repo segment — the workflow builds it as
|
||||
`format('{0}/healthchat-web', github.repository)`.)
|
||||
- [ ] GitHub Release exists at
|
||||
`https://github.com/<owner>/<repo>/releases/tag/healthchat-v<version>`
|
||||
with the correct body.
|
||||
- [ ] The `:stable` tag on ghcr.io now points at the new digest
|
||||
(`docker buildx imagetools inspect ghcr.io/<owner>/healthchat-web:stable`).
|
||||
- [ ] The desktop workflow run ("Build HealthChat Desktop") is green and the
|
||||
GitHub Release has the desktop installers attached (.dmg, *-mac.zip, *.msi,
|
||||
"* Setup*.exe").
|
||||
- [ ] The update feed + installers published to healthchat.ch: `curl -fsI`
|
||||
`https://healthchat.ch/packages/desktop/update/macos/releases.json`,
|
||||
`.../update/win32/x64/RELEASES`, and the public installer URLs
|
||||
`.../install/macos/HealthChat.dmg` / `.../install/win32/x64/HealthChat-Setup.exe`
|
||||
all return 200.
|
||||
- [ ] Smoke-check signing: macOS `spctl -a -vvv -t install <app>` is accepted;
|
||||
Windows installer shows a valid publisher (no SmartScreen block).
|
||||
- [ ] The `:latest` tag on ghcr.io now points at the new digest, and matches
|
||||
`:<version>`:
|
||||
|
||||
```bash
|
||||
docker buildx imagetools inspect ghcr.io/novaloop-ag/healthchat-web/healthchat-web:latest
|
||||
docker buildx imagetools inspect ghcr.io/novaloop-ag/healthchat-web/healthchat-web:<version>
|
||||
```
|
||||
|
||||
For an `-rc`/`-hotfix`/`-dryrun` tag the opposite is expected: `:latest` must
|
||||
be **unchanged**.
|
||||
- [ ] The desktop workflow run ("Build HealthChat Desktop") is green, the GitHub
|
||||
Release notes carry the "## Downloads" section, and the staged archive exists:
|
||||
`curl -fsS https://packages.healthchat.ch/desktop-releases/<version>/update/macos/releases.json`.
|
||||
Without that archive the desktop deploy has nothing to publish.
|
||||
- [ ] Confirm the live feed is still on the **previous** version — releasing must not have
|
||||
moved it. `curl -fsS https://packages.healthchat.ch/desktop/update/macos/releases.json`
|
||||
- [ ] Smoke-check signing before shipping to users: macOS `spctl -a -vvv -t install <app>`
|
||||
is accepted; Windows installer shows a valid publisher (no SmartScreen block).
|
||||
|
||||
## After the deployment
|
||||
|
||||
Two independent deploys — do both (see "Deploying the release" and "Deploying the desktop
|
||||
release"):
|
||||
|
||||
- [ ] Web deployed and `curl -fsS https://app.healthchat.ch/version` reports the new version.
|
||||
- [ ] Desktop feed deployed: the "Deploy HealthChat Desktop" run is green. Its own verify
|
||||
step already asserts the feed URLs return 200, so a green run is
|
||||
the check.
|
||||
- [ ] `releases.json` now advertises the new version:
|
||||
`curl -fsS https://packages.healthchat.ch/desktop/update/macos/releases.json | jq -r '.releases[0].updateTo.version'`
|
||||
- [ ] Spot-check auto-update on a real installed client (or at least confirm the app's
|
||||
update check reaches the feed) before announcing.
|
||||
|
||||
## Required secrets
|
||||
|
||||
@@ -186,7 +362,7 @@ Configured in repo Settings → Secrets and variables → Actions:
|
||||
|---|---|
|
||||
| `HEALTHCHAT_WORKSPACE_TOKEN` | PAT with read access to `Novaloop-AG/healthchat-workspace`. Needed by `actions/checkout` for the private plugin repo. |
|
||||
| `GITHUB_TOKEN` | Auto-provided. Used for ghcr.io login and GitHub Release creation. No manual setup required. |
|
||||
| `FTP_SERVER` / `FTP_USERNAME` / `FTP_PASSWORD` | Credentials for the healthchat.ch FTP(S) account. The desktop `release` job uses them to publish the update feed + public installers under `/public_html/healthchat.ch/packages/desktop/`. `FTP_SERVER` is the hostname only (explicit FTPS / AUTH TLS). Without them the FTP publish step fails (but the GitHub Release still gets the installers). |
|
||||
| `FTP_SERVER` / `FTP_USERNAME` / `FTP_PASSWORD` | Credentials for the healthchat.ch FTP(S) account (docroot of packages.healthchat.ch is `/public_html/packages`). Used by the `release` job of `build-healthchat-desktop.yaml` to stage the feed archive under `/public_html/packages/desktop-releases/<version>/`, and by `deploy-healthchat-desktop.yaml` to publish the live feed under `/public_html/packages/desktop/`. `FTP_SERVER` is the hostname only (explicit FTPS / AUTH TLS). |
|
||||
|
||||
Desktop signing additionally requires two GitHub **environments** (Settings →
|
||||
Environments). Without them the desktop builds still run but produce
|
||||
@@ -206,9 +382,26 @@ fork must stay **internal** (not public). Add branch/environment protection so o
|
||||
|
||||
## Rollback
|
||||
|
||||
- **Bad image already deployed** → redeploy the previous version immediately using the
|
||||
explicit-version override in "Deploying the release" (no commit, no inventory edit).
|
||||
That restores service; then fix forward with a hotfix tag. Remember the override is
|
||||
one-shot — the next plain deploy goes back to `:latest`, so land the real fix before
|
||||
anyone runs `setup-all`.
|
||||
- **Bad image, notes fine** → fix the cause, commit, tag `healthchat-v<ver>-hotfix1`.
|
||||
Note a `-hotfix1` tag does **not** move `:latest`; once you have verified it, either
|
||||
deploy it via the explicit-version override or cut a clean `X.Y.Z` tag to promote it.
|
||||
- **Bad desktop build already deployed to the feed** → re-run "Deploy HealthChat Desktop"
|
||||
with the previous version (see "Deploying an RC or rolling back"). Clients that already
|
||||
auto-updated stay on the bad version until the next release — the feed only controls what
|
||||
is offered next, it cannot recall an installed build. That asymmetry is exactly why the
|
||||
desktop deploy is gated behind a manual dispatch.
|
||||
- **Bad desktop build caught before deploying** → nothing to undo. Do not run the deploy
|
||||
workflow; fix forward and cut a new tag.
|
||||
- **Bad release notes** → edit `HEALTHCHAT_CHANGES.md` and the GitHub Release
|
||||
body manually (GitHub UI). The ghcr.io tag is immutable, don't try to move it.
|
||||
body manually (GitHub UI). The ghcr.io tag is immutable, don't try to move it. Note the
|
||||
desktop feed bakes the notes in at **build** time (into `releases.json` and `notes.txt`),
|
||||
so a post-hoc edit to `HEALTHCHAT_CHANGES.md` does not reach the update dialog — rebuild
|
||||
that version if the notes matter to desktop users.
|
||||
- **Completely wrong tag** → delete the GitHub Release (UI). Do **not** delete
|
||||
the ghcr.io image tag — treat it as burned. Re-tag with a new version.
|
||||
|
||||
@@ -220,6 +413,7 @@ during rebase):
|
||||
|
||||
- `.github/workflows/build-healthchat.yaml`
|
||||
- `.github/workflows/build-healthchat-desktop.yaml`
|
||||
- `.github/workflows/deploy-healthchat-desktop.yaml`
|
||||
- `HEALTHCHAT_CHANGES.md`
|
||||
- `.healthchat-workspace-version`
|
||||
- `.claude/skills/releasing-healthchat/SKILL.md`
|
||||
|
||||
@@ -10,6 +10,12 @@ name: Build HealthChat Desktop
|
||||
# (via `webapp-artifact`) and the per-platform build_desktop_{macos,windows}.yaml reusables.
|
||||
#
|
||||
# Notes:
|
||||
# - This workflow RELEASES but does not DEPLOY. It stages the update feed + public installers
|
||||
# to the versioned archive at packages.healthchat.ch/desktop-releases/<version>/ and links
|
||||
# the public installer URLs in the Release notes (nothing binary is attached to the GitHub
|
||||
# Release); the live auto-update feed at packages.healthchat.ch/desktop/ is only touched by
|
||||
# the manually dispatched deploy-healthchat-desktop.yaml. So cutting a tag never pushes an
|
||||
# update to already-installed apps until a human decides to ship it.
|
||||
# - The reusable build workflows are pointed at THIS fork (repository/ref inputs) so the Electron
|
||||
# shell, icons (apps/desktop/build/icon.*) and the healthchat:// deep-link handler
|
||||
# (apps/desktop/src/protocol.ts) are all fork-branded. Branding values come from
|
||||
@@ -191,10 +197,10 @@ jobs:
|
||||
targets: "dmg zip"
|
||||
# Generates dist/releases.json (the Squirrel.Mac feed manifest). The reusable appends
|
||||
# `/update/macos/<zip>` to this, so the in-manifest URL becomes
|
||||
# https://healthchat.ch/packages/desktop/update/macos/<zip>, matching where the
|
||||
# https://packages.healthchat.ch/desktop/update/macos/<zip>, matching where the
|
||||
# `release` job publishes the feed. Keep in sync with update_base_url in
|
||||
# element.io/healthchat/config.json (.../packages/desktop/update/).
|
||||
base-url: https://healthchat.ch/packages/desktop
|
||||
# element.io/healthchat/config.json (.../desktop/update/).
|
||||
base-url: https://packages.healthchat.ch/desktop
|
||||
|
||||
windows:
|
||||
name: Windows ${{ matrix.arch }}
|
||||
@@ -223,10 +229,13 @@ jobs:
|
||||
targets: "squirrel msi"
|
||||
|
||||
release:
|
||||
name: Publish to GitHub Release
|
||||
name: Stage feed archive + Release notes
|
||||
needs: [macos, windows]
|
||||
# Only publish on a real tag push; manual workflow_dispatch runs build but do not publish.
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
# Runs on tag pushes AND manual dispatches: the archive upload is idempotent per version
|
||||
# (mirror --delete into desktop-releases/<version>/), and re-running it via dispatch is
|
||||
# the recovery path for a version whose archive is missing. The GitHub Release steps
|
||||
# below stay tag-only, so a dispatch can never touch release history.
|
||||
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -237,24 +246,31 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Resolve version
|
||||
id: relversion
|
||||
env:
|
||||
INPUT_VERSION: ${{ github.event.inputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
|
||||
VERSION="${GITHUB_REF_NAME#healthchat-v}"
|
||||
else
|
||||
VERSION="${INPUT_VERSION:?No version input on workflow_dispatch}"
|
||||
fi
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Download all build artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
path: dist-artifacts
|
||||
|
||||
- name: Collect installers
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p release-files
|
||||
# macOS: .dmg installer + .zip (Squirrel.Mac update payload)
|
||||
find dist-artifacts -type f \( -iname '*.dmg' -o -iname '*-mac.zip' \) -exec cp -v {} release-files/ \;
|
||||
# Windows: per-machine MSI + Squirrel "Setup" installer
|
||||
find dist-artifacts -type f \( -iname '*.msi' -o -iname '* Setup*.exe' \) -exec cp -v {} release-files/ \;
|
||||
echo "--- release files ---"
|
||||
ls -la release-files
|
||||
test -n "$(ls -A release-files)" || { echo "::error::No installer files collected"; exit 1; }
|
||||
|
||||
- name: Upload to GitHub Release
|
||||
# Installers are NOT attached to the Release: they ship inside the staged feed and are
|
||||
# served from packages.healthchat.ch after the deploy — the Release body links to them
|
||||
# there (see "Link public downloads in the Release notes" below). Attaching them here
|
||||
# would duplicate ~1 GiB per release and the x64/arm64 Setup.exe share a filename, so
|
||||
# they'd clobber each other as flat Release assets anyway.
|
||||
- name: Ensure GitHub Release exists
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
@@ -262,17 +278,21 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# The web workflow (build-healthchat.yaml) also creates this release for the same tag.
|
||||
# Create-if-missing (without touching existing notes) then upload --clobber so the two
|
||||
# workflows race safely regardless of ordering.
|
||||
# Create-if-missing (without touching existing notes) so the two workflows race
|
||||
# safely regardless of ordering.
|
||||
gh release view "$TAG" >/dev/null 2>&1 || \
|
||||
gh release create "$TAG" --title "$TAG" --notes "HealthChat desktop installers for $TAG"
|
||||
gh release upload "$TAG" release-files/* --clobber
|
||||
gh release create "$TAG" --title "$TAG" --notes "HealthChat $TAG"
|
||||
|
||||
# The GitHub Release above is private (internal fork), so it can't serve end users or the
|
||||
# Squirrel auto-updater. Mirror the update feed + public installers to healthchat.ch over
|
||||
# FTPS so installed apps self-update (update_base_url -> .../packages/desktop/update/) and
|
||||
# users can download from a public URL (.../packages/desktop/install/).
|
||||
# The GitHub Release is private (internal fork), so it can't serve end users or the
|
||||
# Squirrel auto-updater. Those are served from packages.healthchat.ch/desktop/, which is
|
||||
# published by the SEPARATE, MANUALLY DISPATCHED "Deploy HealthChat Desktop" workflow
|
||||
# (deploy-healthchat-desktop.yaml) — releasing never touches the live update feed.
|
||||
# This job only *stages* that feed and uploads it to the versioned archive at
|
||||
# packages.healthchat.ch/desktop-releases/<version>/ (the archive persists, so the
|
||||
# deploy workflow can publish any staged version without rebuilding or re-signing).
|
||||
- name: Stage update feed + public installers
|
||||
env:
|
||||
VERSION: ${{ steps.relversion.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# --- Release notes: extract this version's section from HEALTHCHAT_CHANGES.md ---
|
||||
@@ -280,7 +300,6 @@ jobs:
|
||||
# auto-update "See changes" dialog: macOS reads it from releases.json's `notes`
|
||||
# field natively, Windows fetches notes.txt (Squirrel.Windows can't carry notes
|
||||
# through the update-downloaded event — only releaseName is available).
|
||||
VERSION="${GITHUB_REF_NAME#healthchat-v}"
|
||||
NOTES=$(awk -v ver="$VERSION" '
|
||||
/^## Changes in / {
|
||||
if (found) { exit }
|
||||
@@ -328,31 +347,78 @@ jobs:
|
||||
echo "--- staged feed tree ---"
|
||||
find feed -type f | sort
|
||||
|
||||
- name: Install lftp
|
||||
run: sudo apt-get update && sudo apt-get install -y lftp
|
||||
|
||||
- name: Publish to healthchat.ch over FTPS
|
||||
# Upload the staged feed to the versioned archive instead of publishing it. "Deploy
|
||||
# HealthChat Desktop" (deploy-healthchat-desktop.yaml) mirrors this archive to the
|
||||
# live feed when a human decides to ship. The archive directories persist on the
|
||||
# server, so any staged version stays redeployable without rebuilding or re-signing.
|
||||
# (The feed used to be attached to the GitHub Release as a tarball, but the
|
||||
# compressed feed outgrew GitHub's 2 GiB per-asset cap at 1.6.0.)
|
||||
- name: Publish staged feed to the versioned archive
|
||||
env:
|
||||
FTP_SERVER: ${{ secrets.FTP_SERVER }}
|
||||
FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
|
||||
# Passed to lftp via LFTP_PASSWORD (--env-password) so it never appears on the
|
||||
# command line / process list.
|
||||
LFTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
|
||||
VERSION: ${{ steps.relversion.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
: "${FTP_SERVER:?FTP_SERVER secret not set}"
|
||||
: "${FTP_USERNAME:?FTP_USERNAME secret not set}"
|
||||
: "${LFTP_PASSWORD:?FTP_PASSWORD secret not set}"
|
||||
# mirror -R (reverse) uploads the local tree; default is no-delete, so prior
|
||||
# *.nupkg are preserved (Squirrel.Windows delta history) and only the staged files
|
||||
# are written/overwritten. If the host's FTPS cert is untrusted, set
|
||||
# ssl:verify-certificate to no.
|
||||
lftp -u "$FTP_USERNAME" --env-password "$FTP_SERVER" <<'LFTP'
|
||||
sudo apt-get update && sudo apt-get install -y lftp
|
||||
# The archive dir is owned by this version's build: --delete makes re-runs
|
||||
# idempotent (a rebuild fully replaces the staged tree). The live feed under
|
||||
# /public_html/packages/desktop is never touched here.
|
||||
lftp -u "$FTP_USERNAME" --env-password "$FTP_SERVER" <<LFTP
|
||||
set cmd:fail-exit true
|
||||
set ftp:ssl-force true
|
||||
set ftp:ssl-protect-data true
|
||||
set ssl:verify-certificate true
|
||||
mkdir -pf /public_html/healthchat.ch/packages/desktop
|
||||
mirror -R --parallel=4 --verbose feed/ /public_html/healthchat.ch/packages/desktop/
|
||||
mkdir -pf /public_html/packages/desktop-releases/$VERSION
|
||||
mirror -R --delete --parallel=4 --verbose feed/ /public_html/packages/desktop-releases/$VERSION/
|
||||
bye
|
||||
LFTP
|
||||
echo "::notice::Feed staged at https://packages.healthchat.ch/desktop-releases/$VERSION/ — the live feed is UNCHANGED. Run 'Deploy HealthChat Desktop' to publish it."
|
||||
|
||||
# The Release carries no installer binaries (see "Ensure GitHub Release exists"), so
|
||||
# point readers at the public download URLs instead. The links are derived from the
|
||||
# staged feed/install tree, so they stay correct if electron-builder ever renames the
|
||||
# artifacts. They resolve once "Deploy HealthChat Desktop" has published this version.
|
||||
- name: Link public downloads in the Release notes
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
BASE="https://packages.healthchat.ch/desktop"
|
||||
BODY=$(gh release view "$TAG" --json body --jq .body)
|
||||
if [[ "$BODY" == *"## Downloads"* ]]; then
|
||||
echo "Release notes already carry a Downloads section — leaving them untouched."
|
||||
exit 0
|
||||
fi
|
||||
{
|
||||
printf '%s\n\n' "$BODY"
|
||||
echo "## Downloads"
|
||||
echo ""
|
||||
echo "Public installers, live once this version is deployed via \"Deploy HealthChat Desktop\":"
|
||||
echo ""
|
||||
for f in feed/install/macos/* feed/install/win32/x64/* feed/install/win32/arm64/*; do
|
||||
name=$(basename "$f")
|
||||
# Skip the stable "latest" aliases — they track whatever is deployed, not this version.
|
||||
case "$name" in HealthChat.dmg|HealthChat-Setup.exe) continue ;; esac
|
||||
dir=$(dirname "${f#feed/}")
|
||||
case "$dir" in
|
||||
*/macos) platform="macOS" ;;
|
||||
*/x64) platform="Windows x64" ;;
|
||||
*/arm64) platform="Windows arm64" ;;
|
||||
*) platform="$dir" ;;
|
||||
esac
|
||||
enc=$(jq -rn --arg s "$name" '$s|@uri')
|
||||
echo "- [$name]($BASE/$dir/$enc) — $platform"
|
||||
done
|
||||
} > release-body.md
|
||||
gh release edit "$TAG" --notes-file release-body.md
|
||||
echo "::notice::Release notes now link the public installers under $BASE/install/."
|
||||
|
||||
@@ -62,7 +62,17 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "Resolved version: $VERSION"
|
||||
# `:latest` is what the ansible inventory deploys from, so only a clean
|
||||
# X.Y.Z tag push may move it — never an -rc/-hotfix/-dryrun tag, and never
|
||||
# a manual re-run. Otherwise a release candidate or a pipeline test would
|
||||
# become production on the next deploy of any kind.
|
||||
if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ && "$GITHUB_EVENT_NAME" == "push" ]]; then
|
||||
IS_STABLE=true
|
||||
else
|
||||
IS_STABLE=false
|
||||
fi
|
||||
echo "is_stable=$IS_STABLE" >> "$GITHUB_OUTPUT"
|
||||
echo "Resolved version: $VERSION (moves :latest: $IS_STABLE)"
|
||||
|
||||
- name: Resolve workspace ref
|
||||
id: workspace
|
||||
@@ -157,7 +167,7 @@ jobs:
|
||||
images: ${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_IMAGE }}
|
||||
tags: |
|
||||
type=raw,value=${{ steps.version.outputs.version }}
|
||||
type=raw,value=stable
|
||||
type=raw,value=latest,enable=${{ steps.version.outputs.is_stable == 'true' }}
|
||||
type=raw,value=${{ github.sha }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
name: Deploy HealthChat Desktop
|
||||
|
||||
# Publishes an already-released desktop build to packages.healthchat.ch/desktop/ over FTPS.
|
||||
#
|
||||
# This is the DEPLOY half of the desktop pipeline, deliberately split from the release half
|
||||
# (build-healthchat-desktop.yaml). Cutting a `healthchat-v*` tag builds, signs and stages the
|
||||
# update feed + public installers at packages.healthchat.ch/desktop-releases/<version>/, but
|
||||
# never touches the live feed. Nothing reaches installed apps until this workflow is dispatched
|
||||
# by hand.
|
||||
#
|
||||
# Why that split matters: the feed under .../desktop/update/ is what the Squirrel
|
||||
# auto-updater polls. Writing to it pushes an update to every installed client, so it is a
|
||||
# deployment, not a publication step — the same reason the ansible playbook's deploy is a manual
|
||||
# dispatch rather than a release trigger.
|
||||
#
|
||||
# The versioned archive directories persist on the server, so any staged version can be
|
||||
# re-published without rebuilding or re-signing — that is the rollback path.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Version to publish (e.g. 1.5.0). Must have a staged feed at packages.healthchat.ch/desktop-releases/<version>/ (produced by Build HealthChat Desktop)."
|
||||
required: true
|
||||
type: string
|
||||
dry_run:
|
||||
description: "Dry run — list what would be uploaded without writing to the server."
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions: {} # the feed comes from the packages.healthchat.ch archive, not from GitHub
|
||||
|
||||
concurrency:
|
||||
# Never let two runs mirror onto the same FTP tree at once.
|
||||
group: deploy-healthchat-desktop
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Publish update feed to packages.healthchat.ch
|
||||
runs-on: ubuntu-latest
|
||||
# Fetches ~2 GiB from the archive and uploads it to the live feed.
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Resolve version
|
||||
id: version
|
||||
env:
|
||||
INPUT_VERSION: ${{ inputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VERSION="$INPUT_VERSION"
|
||||
# Same regex as the release workflows, so -rc1/-hotfix1 builds can be published
|
||||
# deliberately (e.g. to a test machine) but never by accident.
|
||||
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then
|
||||
echo "::error::Invalid version '$VERSION' — expected e.g. 1.5.0 or 1.5.0-rc1"
|
||||
exit 1
|
||||
fi
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=healthchat-v$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "Publishing HealthChat Desktop $VERSION (tag healthchat-v$VERSION)"
|
||||
|
||||
- name: Install lftp
|
||||
run: sudo apt-get update && sudo apt-get install -y lftp
|
||||
|
||||
- name: Fetch staged feed from the archive
|
||||
env:
|
||||
FTP_SERVER: ${{ secrets.FTP_SERVER }}
|
||||
FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
|
||||
# Passed to lftp via LFTP_PASSWORD (--env-password) so it never appears on the
|
||||
# command line / process list.
|
||||
LFTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
|
||||
VERSION: ${{ steps.version.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
: "${FTP_SERVER:?FTP_SERVER secret not set}"
|
||||
: "${FTP_USERNAME:?FTP_USERNAME secret not set}"
|
||||
: "${LFTP_PASSWORD:?FTP_PASSWORD secret not set}"
|
||||
# The archive is public — probe it over HTTPS first for a clear error before
|
||||
# opening the FTP session.
|
||||
if ! curl -fsSI "https://packages.healthchat.ch/desktop-releases/$VERSION/update/macos/releases.json" >/dev/null 2>&1; then
|
||||
echo "::error::No staged feed at https://packages.healthchat.ch/desktop-releases/$VERSION/ — run 'Build HealthChat Desktop' (workflow_dispatch, version=$VERSION) to build and stage this version, then re-run the deploy."
|
||||
exit 1
|
||||
fi
|
||||
lftp -u "$FTP_USERNAME" --env-password "$FTP_SERVER" <<LFTP
|
||||
set cmd:fail-exit true
|
||||
set ftp:ssl-force true
|
||||
set ftp:ssl-protect-data true
|
||||
set ssl:verify-certificate true
|
||||
mirror --parallel=4 --verbose /public_html/packages/desktop-releases/$VERSION/ feed/
|
||||
bye
|
||||
LFTP
|
||||
test -d feed || { echo "::error::Archive fetch produced no feed/ directory"; exit 1; }
|
||||
echo "--- feed to publish ---"
|
||||
find feed -type f | sort
|
||||
|
||||
- name: Sanity-check the feed before publishing
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# A partial feed is worse than none: Squirrel clients poll these paths, and a
|
||||
# missing manifest breaks auto-update for everyone already installed.
|
||||
fail=0
|
||||
for f in feed/update/macos/releases.json \
|
||||
feed/update/win32/x64/RELEASES \
|
||||
feed/update/win32/arm64/RELEASES; do
|
||||
if [[ ! -s "$f" ]]; then echo "::error::missing or empty: $f"; fail=1; fi
|
||||
done
|
||||
# The macOS updater fetches the zip named in releases.json; make sure it is present.
|
||||
if [[ -s feed/update/macos/releases.json ]]; then
|
||||
if ! ls feed/update/macos/*-mac.zip >/dev/null 2>&1; then
|
||||
echo "::error::releases.json present but no *-mac.zip payload alongside it"; fail=1
|
||||
fi
|
||||
fi
|
||||
exit $fail
|
||||
|
||||
- name: Publish to packages.healthchat.ch over FTPS
|
||||
env:
|
||||
FTP_SERVER: ${{ secrets.FTP_SERVER }}
|
||||
FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
|
||||
# Passed to lftp via LFTP_PASSWORD (--env-password) so it never appears on the
|
||||
# command line / process list.
|
||||
LFTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
|
||||
DRY_RUN: ${{ inputs.dry_run }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
: "${FTP_SERVER:?FTP_SERVER secret not set}"
|
||||
: "${FTP_USERNAME:?FTP_USERNAME secret not set}"
|
||||
: "${LFTP_PASSWORD:?FTP_PASSWORD secret not set}"
|
||||
MIRROR_OPTS="--parallel=4 --verbose"
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "::notice::DRY RUN — no files will be written to the server."
|
||||
MIRROR_OPTS="$MIRROR_OPTS --dry-run"
|
||||
fi
|
||||
# mirror -R (reverse) uploads the local tree; default is no-delete, so prior
|
||||
# *.nupkg are preserved (Squirrel.Windows delta history) and only the staged files
|
||||
# are written/overwritten. If the host's FTPS cert is untrusted, set
|
||||
# ssl:verify-certificate to no.
|
||||
lftp -u "$FTP_USERNAME" --env-password "$FTP_SERVER" <<LFTP
|
||||
set cmd:fail-exit true
|
||||
set ftp:ssl-force true
|
||||
set ftp:ssl-protect-data true
|
||||
set ssl:verify-certificate true
|
||||
mkdir -pf /public_html/packages/desktop
|
||||
mirror -R $MIRROR_OPTS feed/ /public_html/packages/desktop/
|
||||
bye
|
||||
LFTP
|
||||
|
||||
- name: Verify published feed
|
||||
if: ${{ !inputs.dry_run }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
base="https://packages.healthchat.ch/desktop"
|
||||
fail=0
|
||||
for url in "$base/update/macos/releases.json" \
|
||||
"$base/update/win32/x64/RELEASES" \
|
||||
"$base/update/win32/arm64/RELEASES" \
|
||||
"$base/install/macos/HealthChat.dmg" \
|
||||
"$base/install/win32/x64/HealthChat-Setup.exe"; do
|
||||
code=$(curl -fsS -o /dev/null -w '%{http_code}' -I "$url" 2>/dev/null || echo "000")
|
||||
if [[ "$code" == "200" ]]; then echo "ok $code $url"; else echo "FAIL $code $url"; fail=1; fi
|
||||
done
|
||||
if [[ $fail -ne 0 ]]; then
|
||||
echo "::error::One or more feed URLs are not reachable — auto-update may be broken."
|
||||
exit 1
|
||||
fi
|
||||
echo "::notice::Update feed for ${{ steps.version.outputs.version }} is live. Installed apps will pick it up on their next update check."
|
||||
@@ -1 +1 @@
|
||||
v0.6.0
|
||||
v1.2.0
|
||||
|
||||
@@ -133,4 +133,4 @@ Conventions unique to this fork that span multiple files:
|
||||
`pnpm link` is **not** used (it mutates `package.json`/lockfile). Instead, the `postinstall` hook runs `scripts/pnpm-link.ts`, which reads a `.link-config` file of `DEPENDENCY=PATH` lines and replaces those `node_modules` entries with symlinks. To develop against a local SDK, add a line like `matrix-js-sdk=/abs/path/to/matrix-js-sdk` to `.link-config` (not committed) and re-run `pnpm install`.
|
||||
|
||||
### Releasing HealthChat
|
||||
Releases are cut by pushing a `healthchat-v<semver>` tag against `release/healthchat`, which triggers `.github/workflows/build-healthchat.yaml` (web) and `build-healthchat-desktop.yaml` (desktop). Release notes come from `HEALTHCHAT_CHANGES.md` (kept separate from upstream `CHANGELOG.md`); the healthchat-workspace plugin ref is pinned in `.healthchat-workspace-version`. Full runbook: `releasing-healthchat` skill.
|
||||
Releases are cut by pushing a `healthchat-v<semver>` tag against `release/healthchat`, which triggers `.github/workflows/build-healthchat.yaml` (web) and `build-healthchat-desktop.yaml` (desktop). Release notes come from `HEALTHCHAT_CHANGES.md` (kept separate from upstream `CHANGELOG.md`); the healthchat-workspace plugin ref is pinned in `.healthchat-workspace-version`. The image is published to `ghcr.io/novaloop-ag/healthchat-web/healthchat-web` as `:<version>`, `:<sha>`, and `:latest` — where `:latest` moves **only** for a clean `X.Y.Z` tag push, never for `-rc`/`-hotfix` tags or manual dispatch runs. **Deploying is a separate manual step for both halves** and needs no version bump anywhere: the web side is a `gh workflow run deploy.yml` against the ansible repo (whose inventory tracks `:latest`), and the desktop side is `deploy-healthchat-desktop.yaml`, which publishes the update feed to packages.healthchat.ch. Cutting a tag never pushes an update to installed desktop clients — `build-healthchat-desktop.yaml` only stages the feed archive at `packages.healthchat.ch/desktop-releases/<version>/`. Full runbook: `releasing-healthchat` skill.
|
||||
|
||||
@@ -7,6 +7,129 @@ in <version>` section and uses it as the body of the GitHub Release.
|
||||
One section per released version, newest on top. Upstream element-hq
|
||||
`CHANGELOG.md` is kept separate and untouched.
|
||||
|
||||
## Changes in 1.7.2 (2026-10-25)
|
||||
|
||||
🐛 Fixes
|
||||
|
||||
- Opening app.healthchat.ch on a phone or tablet now shows the HealthChat mobile
|
||||
guide with App Store and Google Play links to the HealthChat app, instead of
|
||||
redirecting to the healthchat.ch website. The guide is in German, like the rest
|
||||
of the HealthChat web app.
|
||||
- Universal Links (iOS) and App Links (Android) for app.healthchat.ch now belong to
|
||||
the HealthChat app. Phones with Element or Element X installed no longer open
|
||||
HealthChat links in those apps.
|
||||
|
||||
## Changes in 1.7.1 (2026-10-21)
|
||||
|
||||
🐛 Fixes
|
||||
|
||||
- Calls work again on IPv4-only networks (home lines, mobile hotspots). The desktop
|
||||
and web apps no longer fail with MISSING_MATRIX_RTC_TRANSPORT when the
|
||||
healthchat.ch well-known lookup is blocked by a redirect without CORS headers;
|
||||
the embedded Element Call now carries the LiveKit service URL as a fallback.
|
||||
|
||||
## Changes in 1.7.0 (2026-09-28)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- Direct-chat calls can now use Element Call, so calls to users on the HealthChat
|
||||
Android app connect instead of failing as unsupported. The desktop app now
|
||||
offers the same "Call" / "Call (Legacy)" choice as HealthChat Web.
|
||||
|
||||
## Changes in 1.6.0 (2026-07-29)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- Upgraded the bundled HealthChat workspace plugin to v1.2.0: the user directory
|
||||
search is now gated on approval, so unapproved accounts no longer appear in
|
||||
search results.
|
||||
|
||||
🧹 Internal
|
||||
|
||||
- Desktop installers and the auto-update feed are now hosted at
|
||||
`https://packages.healthchat.ch/desktop/`; the old address is retired. Apps on
|
||||
version 1.5.0 or older do not check the new address — download the current
|
||||
installer once from the new URL, and updates resume automatically afterwards.
|
||||
|
||||
## Changes in 1.5.0 (2026-07-28)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- Upgraded the bundled HealthChat workspace plugin to v1.1.0:
|
||||
- Space administrators can now manage the members of a space directly from the
|
||||
workspace panel.
|
||||
- Removing a member from a space now also removes them from the bot-owned rooms
|
||||
inside that space, instead of leaving them behind.
|
||||
- The admin area shows the version of the deployed API.
|
||||
- The registration form now mentions the SHPC register alongside the diploma
|
||||
upload.
|
||||
- Granting the Verwalter role now force-joins the space administrator, fixing
|
||||
cases where the grant appeared to have no effect.
|
||||
|
||||
## Changes in 1.4.1 (2026-07-14)
|
||||
|
||||
🧹 Internal
|
||||
|
||||
- Consolidated the "HealthChat Light" theme into a single source of truth
|
||||
(`apps/web/element.io/healthchat/HealthChat-Light-Theme.json`) that is synced into the
|
||||
web and desktop configs, with a lint check that fails on drift. No user-visible change.
|
||||
|
||||
## Changes in 1.4.0 (2026-07-14)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- Upgraded the bundled HealthChat workspace plugin to v1.0.0. The plugin now
|
||||
authenticates against the Matrix backend through the MAS Admin API instead of
|
||||
an appservice token.
|
||||
|
||||
## Changes in 1.3.1 (2026-07-10)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- The Help & About settings tab now has a Sign out button, so you can log out
|
||||
without leaving the settings screen.
|
||||
|
||||
## Changes in 1.3.0 (2026-07-08)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- The Help & About tab is back in User Settings, in a slimmed-down form that
|
||||
shows the app version and support links.
|
||||
- The space hierarchy list now uses the shared theme tokens for its hover and
|
||||
separator colours, so it blends in with the rest of the UI.
|
||||
|
||||
## Changes in 1.2.5 (2026-07-01)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- The desktop app's Help link now points at healthchat.ch.
|
||||
|
||||
## Changes in 1.2.4 (2026-07-01)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- The Windows installer splash now shows the HealthChat logo instead of the
|
||||
Element icon.
|
||||
- The desktop About panel now shows the HealthChat brand (author, homepage, and
|
||||
description).
|
||||
- Help links now point at healthchat.ch.
|
||||
|
||||
## Changes in 1.2.3 (2026-06-30)
|
||||
|
||||
🐛 Fixes
|
||||
|
||||
- The desktop app (macOS) now lets you interact with the Mitglieder and Admin
|
||||
pages again. Their inputs and buttons were dead because the window-drag region
|
||||
used for the frameless title bar swallowed all mouse and keyboard events on
|
||||
those pages.
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- Share links and QR codes now resolve against `to.healthchat.ch` instead of the
|
||||
public matrix.to.
|
||||
- The desktop About panel and macOS app menu now show the HealthChat brand
|
||||
instead of "Element".
|
||||
|
||||
## Changes in 1.2.2 (2026-06-30)
|
||||
|
||||
🐛 Fixes
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 9.7 KiB |
@@ -48,8 +48,12 @@ feeds it into build_desktop_prepare.yaml (`config: element.io/healthchat`,
|
||||
`webapp-artifact: healthchat-webapp`) and the per-platform build_desktop_{macos,windows}.yaml
|
||||
reusables. It runs on every `healthchat-v*` tag (alongside the web build) and via
|
||||
workflow_dispatch. The reusables are pointed at THIS fork (`repository`/`ref` inputs) so the
|
||||
Electron shell, icons and the healthchat:// deep-link handler are fork-branded. On a tag push the
|
||||
`release` job attaches the .dmg / .zip / .exe / .msi to the GitHub Release.
|
||||
Electron shell, icons and the healthchat:// deep-link handler are fork-branded. The `release`
|
||||
job uploads the staged update feed + installers to the versioned archive at
|
||||
packages.healthchat.ch/desktop-releases/<ver>/ (also on workflow_dispatch — the recovery path
|
||||
for a missing archive) and, on tag pushes only, links the public installer URLs in the Release
|
||||
notes. Nothing binary is attached to the GitHub Release (the compressed feed outgrew GitHub's
|
||||
2 GiB per-asset cap at 1.6.0).
|
||||
(Linux is not built: the upstream build_desktop_linux.yaml needs a build-env Docker image
|
||||
keyed by commit SHA that only exists in the upstream element-hq registry, so it can't run here.)
|
||||
|
||||
@@ -65,6 +69,12 @@ Regenerate after a logo change with ImageMagick:
|
||||
magick apps/web/res/vector-icons/1024.png -define icon:auto-resize=16,24,32,48,64,128,256 apps/desktop/build/icon.ico
|
||||
cp apps/web/res/vector-icons/1024.png apps/desktop/build/icon.icon/Assets/healthchat.png
|
||||
|
||||
The Windows installer splash (Squirrel loadingGif, auto-discovered by
|
||||
electron-builder at build/install-spinner.gif) is a static HealthChat logo on
|
||||
white. Regenerate it alongside the icons:
|
||||
magick -size 320x320 xc:white \( apps/web/res/vector-icons/1024.png -resize 240x240 \) \
|
||||
-gravity center -composite apps/desktop/build/install-spinner.gif
|
||||
|
||||
Signing (required for trusted installers)
|
||||
-----------------------------------------
|
||||
The macos/windows jobs run with sign: true, which gates on these GitHub environments. Create
|
||||
@@ -92,14 +102,14 @@ runs can reach the signing credentials.
|
||||
|
||||
Auto-update + public installer hosting
|
||||
--------------------------------------
|
||||
The apps self-update over a feed hosted on healthchat.ch (the GitHub Release is private to this
|
||||
internal fork, so it can serve neither end users nor the Squirrel auto-updater). Both the update
|
||||
feed and the public installers live under https://healthchat.ch/packages/desktop/ (FTP web root
|
||||
/public_html/healthchat.ch maps to https://healthchat.ch/; no packages. subdomain, so it's a path):
|
||||
The apps self-update over a feed hosted on packages.healthchat.ch (the GitHub Release is private
|
||||
to this internal fork, so it can serve neither end users nor the Squirrel auto-updater). Both the
|
||||
update feed and the public installers live under https://packages.healthchat.ch/desktop/ (the
|
||||
subdomain's docroot on the healthchat.ch FTP account is /public_html/packages):
|
||||
|
||||
update/ the Squirrel feed the installed apps poll hourly. config.json sets
|
||||
"update_base_url": "https://healthchat.ch/packages/desktop/update/"
|
||||
and the macos job passes base-url: https://healthchat.ch/packages/desktop so the
|
||||
"update_base_url": "https://packages.healthchat.ch/desktop/update/"
|
||||
and the macos job passes base-url: https://packages.healthchat.ch/desktop so the
|
||||
generated releases.json points the *-mac.zip at this origin.
|
||||
update/macos/releases.json + HealthChat-<ver>-mac.zip (Squirrel.Mac)
|
||||
update/win32/<arch>/RELEASES + HealthChat-<ver>-full.nupkg (Squirrel.Windows; x64 + arm64)
|
||||
@@ -107,14 +117,21 @@ feed and the public installers live under https://healthchat.ch/packages/desktop
|
||||
install/macos/HealthChat-<ver>.dmg + HealthChat.dmg (stable "latest")
|
||||
install/win32/<arch>/HealthChat-Setup-<ver>.exe + HealthChat-Setup.exe (stable) + *.msi
|
||||
|
||||
The `release` job in build-healthchat-desktop.yaml stages these trees and uploads them via lftp/FTPS
|
||||
(mirror -R, no-delete so prior nupkgs survive for delta history). Add these repo secrets:
|
||||
The `release` job in build-healthchat-desktop.yaml stages these trees and uploads them to the
|
||||
versioned archive desktop-releases/<ver>/ (sibling of desktop/ under /public_html/packages);
|
||||
the manually dispatched deploy-healthchat-desktop.yaml mirrors that archive onto the live
|
||||
desktop/ tree via lftp/FTPS (mirror -R, no-delete so prior nupkgs survive for delta history).
|
||||
Add these repo secrets:
|
||||
FTP_SERVER hostname only (explicit FTPS / AUTH TLS on port 21; if the host cert is untrusted,
|
||||
flip ssl:verify-certificate to no in the workflow)
|
||||
FTP_USERNAME
|
||||
FTP_PASSWORD
|
||||
|
||||
Caveats:
|
||||
- Builds <= 1.5.0 polled the retired feed at https://healthchat.ch/packages/desktop/, which
|
||||
is frozen at 1.5.0 — those installs never see newer versions. Users on them must download
|
||||
the current installer once from the packages.healthchat.ch install/ URL; updates resume
|
||||
automatically afterwards.
|
||||
- First install is manual. Apps already installed without update_base_url (<= 1.1.2) cannot
|
||||
self-update to the first build that carries it; users must download once from the install/ URL.
|
||||
Every release after that updates automatically.
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"appId": "ch.healthchat.desktop",
|
||||
"name": "healthchat-desktop",
|
||||
"productName": "HealthChat",
|
||||
"description": "HealthChat: secure communication for healthcare",
|
||||
"description": "Die sichere Chat-Lösung für Schweizer HealthProfessionals",
|
||||
"protocols": ["ch.healthchat.desktop", "healthchat"]
|
||||
}
|
||||
|
||||
@@ -8,40 +8,26 @@
|
||||
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||
"default_country_code": "GB",
|
||||
"default_server_config": {
|
||||
"m.homeserver": {
|
||||
"base_url": "https://matrix.healthchat.ch",
|
||||
"server_name": "healthchat.ch"
|
||||
},
|
||||
"m.identity_server": {
|
||||
"base_url": ""
|
||||
}
|
||||
"m.homeserver": { "base_url": "https://matrix.healthchat.ch", "server_name": "healthchat.ch" },
|
||||
"m.identity_server": { "base_url": "" }
|
||||
},
|
||||
"default_theme": "custom-HealthChat Light",
|
||||
"disable_custom_urls": true,
|
||||
"disable_guests": true,
|
||||
"element_call": {},
|
||||
"embedded_pages": {
|
||||
"homeUrl": ""
|
||||
},
|
||||
"embedded_pages": { "homeUrl": "" },
|
||||
"enable_presence_by_hs_url": "",
|
||||
"features": {},
|
||||
"features": { "feature_group_calls": true },
|
||||
"help_url": "https://www.healthchat.ch",
|
||||
"integrations_jitsi_widget_url": "https://scalar.vector.im/api/widgets/jitsi.html",
|
||||
"integrations_rest_url": "https://scalar.vector.im/api",
|
||||
"integrations_ui_url": "https://scalar.vector.im/",
|
||||
"integrations_widgets_urls": ["https://scalar.vector.im/api"],
|
||||
"jitsi": {
|
||||
"preferred_domain": "jitsi.healthchat.ch"
|
||||
},
|
||||
"jitsi": { "preferred_domain": "jitsi.healthchat.ch" },
|
||||
"logout_redirect_url": "",
|
||||
"permalink_prefix": "https://matrix.to",
|
||||
"room_directory": {
|
||||
"servers": ["matrix.org"]
|
||||
},
|
||||
"sso_redirect_options": {
|
||||
"immediate": true,
|
||||
"on_welcome_page": true,
|
||||
"on_login_page": true
|
||||
},
|
||||
"matrix_to_url": "https://to.healthchat.ch",
|
||||
"room_directory": { "servers": ["matrix.org"] },
|
||||
"sso_redirect_options": { "immediate": true, "on_welcome_page": true, "on_login_page": true },
|
||||
"setting_defaults": {
|
||||
"UIFeature.deactivate": false,
|
||||
"UIFeature.advancedEncryption": false,
|
||||
@@ -51,7 +37,6 @@
|
||||
"UIFeature.advancedSettings": false,
|
||||
"UIFeature.feedback": false,
|
||||
"custom_themes": [
|
||||
"HealthChat Light",
|
||||
{
|
||||
"name": "HealthChat Light",
|
||||
"is_dark": false,
|
||||
@@ -79,11 +64,18 @@
|
||||
"reaction-row-button-selected-bg-color": "#d9d9d9",
|
||||
"togglesw-off-color": "#9b9898",
|
||||
"avatar-background-colors": ["#12325c", "#1f4d85", "#376A91"],
|
||||
"username-colors": ["#12325c", "#2a4063", "#1f4d85", "#376A91", "#473e3e", "#1f4d85", "#2a4063", "#12325c"]
|
||||
},
|
||||
"fonts": {
|
||||
"general": "\"Century Gothic\", \"Futura\", \"Trebuchet MS\", \"Arial\", sans-serif"
|
||||
"username-colors": [
|
||||
"#12325c",
|
||||
"#2a4063",
|
||||
"#1f4d85",
|
||||
"#376A91",
|
||||
"#473e3e",
|
||||
"#1f4d85",
|
||||
"#2a4063",
|
||||
"#12325c"
|
||||
]
|
||||
},
|
||||
"fonts": { "general": "\"Century Gothic\", \"Futura\", \"Trebuchet MS\", \"Arial\", sans-serif" },
|
||||
"compound": {
|
||||
"--cpd-color-text-action-accent": "#1f4d85",
|
||||
"--cpd-color-bg-action-primary-rest": "#1f4d85",
|
||||
@@ -96,10 +88,7 @@
|
||||
]
|
||||
},
|
||||
"show_labs_settings": false,
|
||||
"update_base_url": "https://healthchat.ch/packages/desktop/update/",
|
||||
"update_base_url": "https://packages.healthchat.ch/desktop/update/",
|
||||
"modules": ["/modules/healthchat-module.js"],
|
||||
"ch.healthchat": {
|
||||
"api_base_url": "https://api.healthchat.ch",
|
||||
"elements_base_url": "/webapp/modules/elements"
|
||||
}
|
||||
"ch.healthchat": { "api_base_url": "https://api.healthchat.ch", "elements_base_url": "/webapp/modules/elements" }
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
"productName": "Element",
|
||||
"main": "lib/electron-main.js",
|
||||
"exports": "./lib/electron-main.js",
|
||||
"version": "1.2.2",
|
||||
"version": "1.7.2",
|
||||
"description": "Element: the future of secure communication",
|
||||
"author": {
|
||||
"name": "Element",
|
||||
"email": "support@element.io"
|
||||
"name": "HealthChat",
|
||||
"email": "support@healthchat.ch"
|
||||
},
|
||||
"homepage": "https://element.io",
|
||||
"homepage": "https://www.healthchat.ch",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vector-im/element-web"
|
||||
@@ -85,12 +85,12 @@
|
||||
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
||||
"@typescript-eslint/parser": "^8.0.0",
|
||||
"@vitest/coverage-v8": "catalog:",
|
||||
"app-builder-lib": "26.11.1",
|
||||
"app-builder-lib": "26.16.1",
|
||||
"chokidar": "^5.0.0",
|
||||
"detect-libc": "^2.0.0",
|
||||
"electron": "42.2.0",
|
||||
"electron-builder": "26.11.1",
|
||||
"electron-builder-squirrel-windows": "26.11.1",
|
||||
"electron-builder": "26.16.1",
|
||||
"electron-builder-squirrel-windows": "26.16.1",
|
||||
"electron-devtools-installer": "^4.0.0",
|
||||
"eslint": "^8.26.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
|
||||
@@ -310,6 +310,14 @@ app.on("ready", async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Drive the native "About" panel from the configured brand so it shows
|
||||
// "HealthChat" rather than the upstream Electron/bundle default.
|
||||
const brand = global.vectorConfig.brand || "Element";
|
||||
app.setAboutPanelOptions({
|
||||
applicationName: brand,
|
||||
applicationVersion: app.getVersion(),
|
||||
});
|
||||
|
||||
if (argv["devtools"]) {
|
||||
try {
|
||||
const { installExtension, REACT_DEVELOPER_TOOLS } = await import("electron-devtools-installer");
|
||||
|
||||
@@ -106,6 +106,12 @@ export function setupMacosTitleBar(window: BrowserWindow): void {
|
||||
iframe {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
/* HealthChat: exclude the page mounted in the room-view wrapper (incl. module
|
||||
location renderers like the Angular custom elements) so their inputs/buttons
|
||||
receive mouse events instead of being swallowed by the window-drag region */
|
||||
.mx_RoomView_wrapper > * {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
/* Add a bar above room header + left panel */
|
||||
|
||||
|
||||
@@ -141,14 +141,16 @@ export function buildMenuTemplate(): Menu {
|
||||
|
||||
// macOS has specific menu conventions...
|
||||
if (isMac) {
|
||||
// XXX: vectorConfig won't have defaults applied to it so we need to duplicate them here
|
||||
const brand = global.vectorConfig?.brand || app.name;
|
||||
template.unshift({
|
||||
// first macOS menu is the name of the app
|
||||
role: "appMenu",
|
||||
label: app.name,
|
||||
label: brand,
|
||||
submenu: [
|
||||
{
|
||||
role: "about",
|
||||
label: _t("common|about") + " " + app.name,
|
||||
label: _t("common|about") + " " + brand,
|
||||
},
|
||||
{ type: "separator" },
|
||||
{
|
||||
|
||||
+24
-44
@@ -8,44 +8,25 @@
|
||||
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||
"default_country_code": "GB",
|
||||
"default_server_config": {
|
||||
"m.homeserver": {
|
||||
"base_url": "https://matrix.healthchat.ch",
|
||||
"server_name": "healthchat.ch"
|
||||
},
|
||||
"m.identity_server": {
|
||||
"base_url": ""
|
||||
}
|
||||
"m.homeserver": { "base_url": "https://matrix.healthchat.ch", "server_name": "healthchat.ch" },
|
||||
"m.identity_server": { "base_url": "" }
|
||||
},
|
||||
"default_theme": "custom-HealthChat Light",
|
||||
"disable_custom_urls": true,
|
||||
"disable_guests": true,
|
||||
"element_call": {},
|
||||
"embedded_pages": {
|
||||
"homeUrl": ""
|
||||
},
|
||||
"embedded_pages": { "homeUrl": "" },
|
||||
"enable_presence_by_hs_url": "",
|
||||
"features": {},
|
||||
"features": { "feature_group_calls": true },
|
||||
"integrations_jitsi_widget_url": "https://scalar.vector.im/api/widgets/jitsi.html",
|
||||
"integrations_rest_url": "https://scalar.vector.im/api",
|
||||
"integrations_ui_url": "https://scalar.vector.im/",
|
||||
"integrations_widgets_urls": [
|
||||
"https://scalar.vector.im/api"
|
||||
],
|
||||
"jitsi": {
|
||||
"preferred_domain": "jitsi.healthchat.ch"
|
||||
},
|
||||
"integrations_widgets_urls": ["https://scalar.vector.im/api"],
|
||||
"jitsi": { "preferred_domain": "jitsi.healthchat.ch" },
|
||||
"logout_redirect_url": "",
|
||||
"permalink_prefix": "https://matrix.to",
|
||||
"room_directory": {
|
||||
"servers": [
|
||||
"matrix.org"
|
||||
]
|
||||
},
|
||||
"sso_redirect_options": {
|
||||
"immediate": true,
|
||||
"on_welcome_page": true,
|
||||
"on_login_page": true
|
||||
},
|
||||
"matrix_to_url": "https://to.healthchat.ch",
|
||||
"room_directory": { "servers": ["matrix.org"] },
|
||||
"sso_redirect_options": { "immediate": true, "on_welcome_page": true, "on_login_page": true },
|
||||
"setting_defaults": {
|
||||
"UIFeature.deactivate": false,
|
||||
"UIFeature.advancedEncryption": false,
|
||||
@@ -55,7 +36,6 @@
|
||||
"UIFeature.advancedSettings": false,
|
||||
"UIFeature.feedback": false,
|
||||
"custom_themes": [
|
||||
"HealthChat Light",
|
||||
{
|
||||
"name": "HealthChat Light",
|
||||
"is_dark": false,
|
||||
@@ -74,8 +54,8 @@
|
||||
"timeline-highlights-color": "#d9d9d9",
|
||||
"timeline-text-color": "#473e3e",
|
||||
"timeline-text-secondary-color": "#9b9898",
|
||||
"secondary-content": "#6e6a6a",
|
||||
"tertiary-content": "#6e6a6a",
|
||||
"secondary-content": "#9b9898",
|
||||
"tertiary-content": "#9b9898",
|
||||
"focus-bg-color": "#d9d9d9",
|
||||
"menu-selected-color": "#d9d9d9",
|
||||
"other-user-pill-bg-color": "#376A91",
|
||||
@@ -83,30 +63,30 @@
|
||||
"reaction-row-button-selected-bg-color": "#d9d9d9",
|
||||
"togglesw-off-color": "#9b9898",
|
||||
"avatar-background-colors": ["#12325c", "#1f4d85", "#376A91"],
|
||||
"username-colors": ["#12325c", "#2a4063", "#1f4d85", "#376A91", "#473e3e", "#1f4d85", "#2a4063", "#12325c"]
|
||||
},
|
||||
"fonts": {
|
||||
"general": "\"Century Gothic\", \"Futura\", \"Trebuchet MS\", \"Arial\", sans-serif"
|
||||
"username-colors": [
|
||||
"#12325c",
|
||||
"#2a4063",
|
||||
"#1f4d85",
|
||||
"#376A91",
|
||||
"#473e3e",
|
||||
"#1f4d85",
|
||||
"#2a4063",
|
||||
"#12325c"
|
||||
]
|
||||
},
|
||||
"fonts": { "general": "\"Century Gothic\", \"Futura\", \"Trebuchet MS\", \"Arial\", sans-serif" },
|
||||
"compound": {
|
||||
"--cpd-color-text-action-accent": "#1f4d85",
|
||||
"--cpd-color-bg-action-primary-rest": "#1f4d85",
|
||||
"--cpd-color-bg-action-primary-hovered": "#2a4063",
|
||||
"--cpd-color-bg-action-primary-pressed": "#12325c",
|
||||
"--cpd-color-text-link-external": "#1f4d85",
|
||||
"--cpd-color-icon-accent-tertiary": "#376A91",
|
||||
"--cpd-color-icon-tertiary": "#5c6470",
|
||||
"--cpd-color-icon-quaternary": "#7c8591",
|
||||
"--cpd-color-icon-accent-primary": "#1f4d85",
|
||||
"--cpd-color-icon-info-primary": "#1f4d85"
|
||||
"--cpd-color-icon-accent-tertiary": "#376A91"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"show_labs_settings": false,
|
||||
"modules": ["/modules/healthchat-module.js"],
|
||||
"ch.healthchat": {
|
||||
"api_base_url": "http://localhost:5001",
|
||||
"elements_base_url": "/modules/elements"
|
||||
}
|
||||
"ch.healthchat": { "api_base_url": "http://localhost:5001", "elements_base_url": "/modules/elements" }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "HealthChat Light",
|
||||
"is_dark": false,
|
||||
"colors": {
|
||||
"accent-color": "#1f4d85",
|
||||
"primary-color": "#1f4d85",
|
||||
"alert": "#df8e1d",
|
||||
"warning-color": "#d20f39",
|
||||
"sidebar-color": "#12325c",
|
||||
"roomlist-background-color": "#f5f5f5",
|
||||
"roomlist-highlights-color": "#d9d9d9",
|
||||
"roomlist-separator-color": "#9b9898",
|
||||
"roomlist-text-color": "#473e3e",
|
||||
"roomlist-text-secondary-color": "#9b9898",
|
||||
"timeline-background-color": "#ffffff",
|
||||
"timeline-highlights-color": "#d9d9d9",
|
||||
"timeline-text-color": "#473e3e",
|
||||
"timeline-text-secondary-color": "#9b9898",
|
||||
"secondary-content": "#9b9898",
|
||||
"tertiary-content": "#9b9898",
|
||||
"focus-bg-color": "#d9d9d9",
|
||||
"menu-selected-color": "#d9d9d9",
|
||||
"other-user-pill-bg-color": "#376A91",
|
||||
"room-highlight-color": "#376A91",
|
||||
"reaction-row-button-selected-bg-color": "#d9d9d9",
|
||||
"togglesw-off-color": "#9b9898",
|
||||
"avatar-background-colors": ["#12325c", "#1f4d85", "#376A91"],
|
||||
"username-colors": ["#12325c", "#2a4063", "#1f4d85", "#376A91", "#473e3e", "#1f4d85", "#2a4063", "#12325c"]
|
||||
},
|
||||
"fonts": {
|
||||
"general": "\"Century Gothic\", \"Futura\", \"Trebuchet MS\", \"Arial\", sans-serif"
|
||||
},
|
||||
"compound": {
|
||||
"--cpd-color-text-action-accent": "#1f4d85",
|
||||
"--cpd-color-bg-action-primary-rest": "#1f4d85",
|
||||
"--cpd-color-bg-action-primary-hovered": "#2a4063",
|
||||
"--cpd-color-bg-action-primary-pressed": "#12325c",
|
||||
"--cpd-color-text-link-external": "#1f4d85",
|
||||
"--cpd-color-icon-accent-tertiary": "#376A91"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
HealthChat theme — single source of truth
|
||||
=========================================
|
||||
|
||||
HealthChat-Light-Theme.json The canonical "HealthChat Light" theme.
|
||||
|
||||
Edit the palette HERE and nowhere else. apps/web/scripts/healthchat-sync-theme.mjs injects
|
||||
it into the element-web configs that ship it:
|
||||
|
||||
- apps/web/config.json (dev server; also baked into the web image)
|
||||
- apps/desktop/element.io/healthchat/config.json (desktop variant, bundled into the app)
|
||||
|
||||
After editing, run:
|
||||
pnpm --filter element-web healthchat:theme
|
||||
`pnpm lint` runs `healthchat:theme:check`, which fails if a config is out of sync — so an
|
||||
un-propagated edit is caught in CI.
|
||||
|
||||
Production web deployment
|
||||
-------------------------
|
||||
The production web client is deployed by matrix-docker-ansible-deploy, whose
|
||||
matrix-client-element role renders config.json from host_vars (no upstream role change).
|
||||
It carries an INLINE copy of this theme in
|
||||
inventory/host_vars/matrix.healthchat.ch/vars.yml
|
||||
(matrix_client_element_setting_defaults_custom_themes)
|
||||
When you change the theme here, re-copy it into that host_vars block. themes_enabled is off
|
||||
there, so the (stale) Novaloop-AG/element-themes repo does not append an older theme.
|
||||
@@ -18,13 +18,15 @@
|
||||
"i18n:lint": "matrix-i18n-lint && prettier --log-level=silent --write src/i18n/strings/ --ignore-path /dev/null",
|
||||
"i18n:diff": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && pnpm i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
|
||||
"rethemendex": "sh ./res/css/rethemendex.sh",
|
||||
"healthchat:theme": "node scripts/healthchat-sync-theme.mjs",
|
||||
"healthchat:theme:check": "node scripts/healthchat-sync-theme.mjs --check",
|
||||
"build": "nx build",
|
||||
"build-stats": "nx build --json=webpack-stats.json",
|
||||
"vendor:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js && mv src/vector/modernizr.js src/vector/modernizr.cjs",
|
||||
"vendor:jitsi": "curl -s https://meet.element.io/libs/external_api.min.js > ./res/jitsi_external_api.min.js",
|
||||
"dist": "./scripts/package.sh",
|
||||
"start": "nx start",
|
||||
"lint": "pnpm lint:types && pnpm lint:js && pnpm lint:style",
|
||||
"lint": "pnpm healthchat:theme:check && pnpm lint:types && pnpm lint:js && pnpm lint:style",
|
||||
"lint:js": "eslint --max-warnings 0 src test playwright module_system",
|
||||
"lint:js-fix": "eslint --fix src test playwright module_system",
|
||||
"lint:types": "nx lint:types",
|
||||
|
||||
@@ -1,64 +1,4 @@
|
||||
[
|
||||
{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "im.vector.app.debug",
|
||||
"sha256_cert_fingerprints": [
|
||||
"B0:B0:51:DC:56:5C:81:2F:E1:7F:6F:3E:94:5B:4D:79:04:71:23:AB:0D:A6:12:86:76:9E:B2:94:91:97:13:0E"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "im.vector.app.nightly",
|
||||
"sha256_cert_fingerprints": [
|
||||
"CA:D3:85:16:84:3A:05:CC:EB:00:AB:7B:D3:80:0F:01:BA:8F:E0:4B:38:86:F3:97:D8:F7:9A:1B:C4:54:E4:0F"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "im.vector.app",
|
||||
"sha256_cert_fingerprints": [
|
||||
"F3:FF:38:D2:E5:A6:38:84:86:4A:4E:0D:45:C5:3B:19:8E:7E:39:C0:50:5B:D9:63:F5:55:D6:53:2D:EA:BF:5F"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "io.element.android.x.debug",
|
||||
"sha256_cert_fingerprints": [
|
||||
"B0:B0:51:DC:56:5C:81:2F:E1:7F:6F:3E:94:5B:4D:79:04:71:23:AB:0D:A6:12:86:76:9E:B2:94:91:97:13:0E"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "io.element.android.x.nightly",
|
||||
"sha256_cert_fingerprints": [
|
||||
"CA:D3:85:16:84:3A:05:CC:EB:00:AB:7B:D3:80:0F:01:BA:8F:E0:4B:38:86:F3:97:D8:F7:9A:1B:C4:54:E4:0F"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
"namespace": "android_app",
|
||||
"package_name": "io.element.android.x",
|
||||
"sha256_cert_fingerprints": [
|
||||
"C6:DB:9B:9C:8C:BD:D6:5D:16:E8:EC:8C:8B:91:C8:31:B9:EF:C9:5C:BF:98:AE:41:F6:A9:D8:35:15:1A:7E:16"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||
"target": {
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
"details": [
|
||||
{
|
||||
"appIDs": [
|
||||
"7J4U792NQT.im.vector.app",
|
||||
"7J4U792NQT.io.element.elementx",
|
||||
"7J4U792NQT.io.element.elementx.nightly"
|
||||
"6G37K72W82.ch.healthchat.element"
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
@@ -25,9 +23,7 @@
|
||||
},
|
||||
"webcredentials": {
|
||||
"apps": [
|
||||
"7J4U792NQT.im.vector.app",
|
||||
"7J4U792NQT.io.element.elementx",
|
||||
"7J4U792NQT.io.element.elementx.nightly"
|
||||
"6G37K72W82.ch.healthchat.element"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
background-color: $spacePanel-bg-color;
|
||||
background-color: var(--cpd-color-bg-subtle-secondary);
|
||||
|
||||
.mx_AccessibleButton {
|
||||
visibility: visible;
|
||||
@@ -245,7 +245,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background-color: $spacePanel-bg-color;
|
||||
background-color: var(--cpd-color-gray-400);
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
left: 6px;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"matrix_rtc_session": {
|
||||
"wait_for_key_rotation_ms": 5000,
|
||||
"delayed_leave_event_restart_ms": 4000,
|
||||
"delayed_leave_event_delay_ms": 18000
|
||||
},
|
||||
"livekit": {
|
||||
"livekit_service_url": "https://matrix.healthchat.ch/livekit-jwt-service"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
* HealthChat theme sync.
|
||||
*
|
||||
* Single source of truth for the "HealthChat Light" theme lives in
|
||||
* apps/web/element.io/healthchat/HealthChat-Light-Theme.json
|
||||
* This script injects it into every element-web config that ships the theme, so the palette
|
||||
* is authored once and never drifts between the dev and desktop configs.
|
||||
*
|
||||
* The production web deployment (matrix-docker-ansible-deploy) renders its config.json from
|
||||
* host_vars and carries an inline copy of this theme; re-copy this file there when it changes.
|
||||
*
|
||||
* Usage:
|
||||
* node apps/web/scripts/healthchat-sync-theme.mjs # write the theme into all configs
|
||||
* node apps/web/scripts/healthchat-sync-theme.mjs --check # exit 1 if any config is out of sync
|
||||
*
|
||||
* Run `pnpm --filter element-web healthchat:theme` after editing the canonical theme;
|
||||
* the --check variant runs in lint/CI to catch an un-synced edit.
|
||||
*/
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import prettier from "prettier";
|
||||
|
||||
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = resolve(scriptDir, "../../..");
|
||||
|
||||
const CANONICAL = resolve(repoRoot, "apps/web/element.io/healthchat/HealthChat-Light-Theme.json");
|
||||
|
||||
// Configs that must carry the theme in setting_defaults.custom_themes.
|
||||
const TARGETS = [
|
||||
"apps/web/config.json", // dev server config (also served by the web Docker image)
|
||||
"apps/desktop/element.io/healthchat/config.json", // desktop variant config bundled into the app
|
||||
];
|
||||
|
||||
const check = process.argv.includes("--check");
|
||||
|
||||
const theme = JSON.parse(readFileSync(CANONICAL, "utf8"));
|
||||
|
||||
let changed = 0;
|
||||
for (const rel of TARGETS) {
|
||||
const path = resolve(repoRoot, rel);
|
||||
const raw = readFileSync(path, "utf8");
|
||||
const config = JSON.parse(raw);
|
||||
config.setting_defaults ??= {};
|
||||
config.setting_defaults.custom_themes = [theme];
|
||||
|
||||
// Format identically to `prettier --write` so the output is byte-for-byte what the
|
||||
// repo's formatting lint expects, keeping --check stable.
|
||||
const options = await prettier.resolveConfig(path);
|
||||
const next = await prettier.format(JSON.stringify(config), { ...options, filepath: path });
|
||||
|
||||
if (next === raw) {
|
||||
continue;
|
||||
}
|
||||
changed++;
|
||||
if (check) {
|
||||
console.error(`out of sync: ${rel} (run: pnpm --filter element-web healthchat:theme)`);
|
||||
} else {
|
||||
writeFileSync(path, next);
|
||||
console.log(`synced theme -> ${rel}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (check) {
|
||||
if (changed > 0) process.exit(1);
|
||||
console.log("all configs in sync with the canonical HealthChat theme");
|
||||
} else if (changed === 0) {
|
||||
console.log("all configs already in sync");
|
||||
}
|
||||
@@ -70,6 +70,12 @@ export interface IConfigOptions {
|
||||
};
|
||||
|
||||
permalink_prefix?: string;
|
||||
/**
|
||||
* Base URL of a matrix.to-compatible resolver to use for Share links and QR codes,
|
||||
* instead of the public `https://matrix.to`. Must use the matrix.to URL format
|
||||
* (`/#/<entity>`), e.g. a self-hosted matrix.to fork.
|
||||
*/
|
||||
matrix_to_url?: string;
|
||||
|
||||
update_base_url?: string;
|
||||
desktop_builds: {
|
||||
|
||||
@@ -22,7 +22,7 @@ export const DEFAULTS: DeepReadonly<IConfigOptions> = {
|
||||
auth_header_logo_url: "themes/element/img/logos/element-logo.png",
|
||||
welcome_background_url: "themes/element/img/backgrounds/lake.jpg",
|
||||
},
|
||||
help_url: "https://element.io/help",
|
||||
help_url: "https://www.healthchat.ch",
|
||||
help_encryption_url: "https://element.io/help#encryption",
|
||||
help_key_storage_url: "https://element.io/help#encryption5",
|
||||
integrations_ui_url: "https://scalar.vector.im/",
|
||||
|
||||
@@ -20,6 +20,7 @@ import SidebarIcon from "@vector-im/compound-design-tokens/assets/web/icons/side
|
||||
import MicOnIcon from "@vector-im/compound-design-tokens/assets/web/icons/mic-on";
|
||||
import LockIcon from "@vector-im/compound-design-tokens/assets/web/icons/lock";
|
||||
import BlockIcon from "@vector-im/compound-design-tokens/assets/web/icons/block";
|
||||
import HelpIcon from "@vector-im/compound-design-tokens/assets/web/icons/help";
|
||||
|
||||
import TabbedView, { Tab, useActiveTabWithDefault } from "../../structures/TabbedView";
|
||||
import { _t, _td } from "../../../languageHandler";
|
||||
@@ -31,6 +32,7 @@ import NotificationUserSettingsTab from "../settings/tabs/user/NotificationUserS
|
||||
import PreferencesUserSettingsTab from "../settings/tabs/user/PreferencesUserSettingsTab";
|
||||
import VoiceUserSettingsTab from "../settings/tabs/user/VoiceUserSettingsTab";
|
||||
import MjolnirUserSettingsTab from "../settings/tabs/user/MjolnirUserSettingsTab";
|
||||
import HelpUserSettingsTab from "../settings/tabs/user/HelpUserSettingsTab";
|
||||
import { UIFeature } from "../../../settings/UIFeature";
|
||||
import BaseDialog from "./BaseDialog";
|
||||
import SidebarUserSettingsTab from "../settings/tabs/user/SidebarUserSettingsTab";
|
||||
@@ -253,8 +255,7 @@ export default function UserSettingsDialog(props: IProps): JSX.Element {
|
||||
),
|
||||
);
|
||||
}
|
||||
// JP: Disable help tab for now
|
||||
/* tabs.push(
|
||||
tabs.push(
|
||||
new Tab(
|
||||
UserTab.Help,
|
||||
_td("setting|help_about|title"),
|
||||
@@ -262,7 +263,7 @@ export default function UserSettingsDialog(props: IProps): JSX.Element {
|
||||
<HelpUserSettingsTab />,
|
||||
"UserSettingsHelpAbout",
|
||||
),
|
||||
);*/
|
||||
);
|
||||
|
||||
return tabs as NonEmptyArray<Tab<UserTab>>;
|
||||
};
|
||||
|
||||
@@ -6,9 +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 React, { type JSX, type ReactNode } from "react";
|
||||
import React, { type JSX } from "react";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { type EmptyObject } from "matrix-js-sdk/src/matrix";
|
||||
import SignOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/sign-out";
|
||||
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
import { _t } from "../../../../../languageHandler";
|
||||
@@ -21,7 +22,9 @@ import { SettingsSection } from "../../shared/SettingsSection";
|
||||
import { SettingsSubsection, SettingsSubsectionText } from "../../shared/SettingsSubsection";
|
||||
import ExternalLink from "../../../elements/ExternalLink";
|
||||
import MatrixClientContext from "../../../../../contexts/MatrixClientContext";
|
||||
import { BugReportDialogButton } from "../../../elements/BugReportDialogButton";
|
||||
import LogoutDialog, { shouldShowLogoutDialog } from "../../../dialogs/LogoutDialog";
|
||||
import Modal from "../../../../../Modal";
|
||||
import defaultDispatcher from "../../../../../dispatcher/dispatcher";
|
||||
|
||||
interface IState {
|
||||
appVersion: string | null;
|
||||
@@ -67,6 +70,14 @@ export default class HelpUserSettingsTab extends React.Component<EmptyObject, IS
|
||||
};
|
||||
}
|
||||
|
||||
private onSignOut = async (): Promise<void> => {
|
||||
if (await shouldShowLogoutDialog(this.context)) {
|
||||
Modal.createDialog(LogoutDialog);
|
||||
} else {
|
||||
defaultDispatcher.dispatch({ action: "logout" });
|
||||
}
|
||||
};
|
||||
|
||||
private onClearCacheAndReload = (): void => {
|
||||
if (!PlatformPeg.get()) return;
|
||||
|
||||
@@ -79,118 +90,6 @@ export default class HelpUserSettingsTab extends React.Component<EmptyObject, IS
|
||||
});
|
||||
};
|
||||
|
||||
private renderLegal(): ReactNode {
|
||||
const tocLinks = SdkConfig.get().terms_and_conditions_links;
|
||||
if (!tocLinks) return null;
|
||||
|
||||
const legalLinks: JSX.Element[] = [];
|
||||
for (const tocEntry of tocLinks) {
|
||||
legalLinks.push(
|
||||
<div key={tocEntry.url}>
|
||||
<ExternalLink href={tocEntry.url}>{tocEntry.text}</ExternalLink>
|
||||
</div>,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsSubsection heading={_t("common|legal")}>
|
||||
<SettingsSubsectionText>{legalLinks}</SettingsSubsectionText>
|
||||
</SettingsSubsection>
|
||||
);
|
||||
}
|
||||
|
||||
private renderCredits(): JSX.Element {
|
||||
// Note: This is not translated because it is legal text.
|
||||
// Also, is ugly but necessary.
|
||||
return (
|
||||
<SettingsSubsection heading={_t("common|credits")}>
|
||||
<SettingsSubsectionText>
|
||||
<ul>
|
||||
<li>
|
||||
{_t(
|
||||
"credits|default_cover_photo",
|
||||
{},
|
||||
{
|
||||
photo: (sub) => (
|
||||
<ExternalLink
|
||||
href="themes/element/img/backgrounds/lake.jpg"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
{sub}
|
||||
</ExternalLink>
|
||||
),
|
||||
author: (sub) => (
|
||||
<ExternalLink href="https://www.flickr.com/golan">{sub}</ExternalLink>
|
||||
),
|
||||
terms: (sub) => (
|
||||
<ExternalLink
|
||||
href="https://creativecommons.org/licenses/by-sa/4.0/"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
{sub}
|
||||
</ExternalLink>
|
||||
),
|
||||
},
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
{_t(
|
||||
"credits|twemoji_colr",
|
||||
{},
|
||||
{
|
||||
colr: (sub) => (
|
||||
<ExternalLink
|
||||
href="https://github.com/matrix-org/twemoji-colr"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
{sub}
|
||||
</ExternalLink>
|
||||
),
|
||||
author: (sub) => <ExternalLink href="https://mozilla.org">{sub}</ExternalLink>,
|
||||
terms: (sub) => (
|
||||
<ExternalLink
|
||||
href="https://www.apache.org/licenses/LICENSE-2.0"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
{sub}
|
||||
</ExternalLink>
|
||||
),
|
||||
},
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
{_t(
|
||||
"credits|twemoji",
|
||||
{},
|
||||
{
|
||||
twemoji: (sub) => (
|
||||
<ExternalLink href="https://twemoji.twitter.com/">{sub}</ExternalLink>
|
||||
),
|
||||
author: (sub) => (
|
||||
<ExternalLink href="https://twemoji.twitter.com/">{sub}</ExternalLink>
|
||||
),
|
||||
terms: (sub) => (
|
||||
<ExternalLink
|
||||
href="https://creativecommons.org/licenses/by/4.0/"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
{sub}
|
||||
</ExternalLink>
|
||||
),
|
||||
},
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
</SettingsSubsectionText>
|
||||
</SettingsSubsection>
|
||||
);
|
||||
}
|
||||
|
||||
private getVersionTextToCopy = (): string => {
|
||||
const { appVersion, cryptoVersion } = this.getVersionInfo();
|
||||
return `${appVersion}\n${cryptoVersion}`;
|
||||
@@ -214,42 +113,21 @@ export default class HelpUserSettingsTab extends React.Component<EmptyObject, IS
|
||||
updateButton = <UpdateCheckButton />;
|
||||
}
|
||||
|
||||
let bugReportingSection;
|
||||
if (SdkConfig.get().bug_report_endpoint_url) {
|
||||
bugReportingSection = (
|
||||
<SettingsSubsection
|
||||
heading={_t("bug_reporting|title")}
|
||||
description={
|
||||
<>
|
||||
<SettingsSubsectionText>{_t("bug_reporting|introduction")}</SettingsSubsectionText>
|
||||
{_t("bug_reporting|description")}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<BugReportDialogButton />
|
||||
<SettingsSubsectionText>
|
||||
{_t(
|
||||
"bug_reporting|matrix_security_issue",
|
||||
{},
|
||||
{
|
||||
a: (sub) => (
|
||||
<ExternalLink href="https://matrix.org/security-disclosure-policy/">
|
||||
{sub}
|
||||
</ExternalLink>
|
||||
),
|
||||
},
|
||||
)}
|
||||
</SettingsSubsectionText>
|
||||
</SettingsSubsection>
|
||||
);
|
||||
}
|
||||
|
||||
const { appVersion, cryptoVersion } = this.getVersionInfo();
|
||||
|
||||
return (
|
||||
<SettingsTab>
|
||||
<SettingsSection>
|
||||
{bugReportingSection}
|
||||
<SettingsSubsection heading={_t("settings|account|title")}>
|
||||
<AccessibleButton onClick={this.onSignOut} kind="danger_outline">
|
||||
<SignOutIcon
|
||||
className="mx_UserProfileSettings_accountmanageIcon"
|
||||
width="24"
|
||||
height="24"
|
||||
/>
|
||||
{_t("action|logout")}
|
||||
</AccessibleButton>
|
||||
</SettingsSubsection>
|
||||
<SettingsSubsection heading={_t("common|faq")} description={faqText} />
|
||||
<SettingsSubsection heading={_t("setting|help_about|versions")}>
|
||||
<SettingsSubsectionText>
|
||||
@@ -262,8 +140,6 @@ export default class HelpUserSettingsTab extends React.Component<EmptyObject, IS
|
||||
{updateButton}
|
||||
</SettingsSubsectionText>
|
||||
</SettingsSubsection>
|
||||
{this.renderLegal()}
|
||||
{this.renderCredits()}
|
||||
<SettingsSubsection heading={_t("common|advanced")}>
|
||||
<SettingsSubsectionText>
|
||||
{_t(
|
||||
|
||||
@@ -12,7 +12,7 @@ import ToastStore from "../stores/ToastStore";
|
||||
import SdkConfig from "../SdkConfig";
|
||||
|
||||
const onAccept = (): void => {
|
||||
window.location.href = "https://healthchat.ch";
|
||||
window.location.href = "mobile_guide/";
|
||||
};
|
||||
|
||||
const onReject = (): void => {
|
||||
|
||||
@@ -7,10 +7,27 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import PermalinkConstructor, { PermalinkParts } from "./PermalinkConstructor";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
|
||||
export const host = "matrix.to";
|
||||
export const baseUrl = `https://${host}`;
|
||||
export const baseUrlPattern = `^(?:https?://)?${host.replace(".", "\\.")}/#/(.*)`;
|
||||
const DEFAULT_BASE_URL = "https://matrix.to";
|
||||
|
||||
/**
|
||||
* The base URL of the matrix.to-compatible resolver to generate permalinks against.
|
||||
* Defaults to the public `https://matrix.to`, but can be pointed at a self-hosted
|
||||
* matrix.to fork via the `matrix_to_url` config option. Read lazily so the value
|
||||
* reflects the runtime config rather than module-load time.
|
||||
*/
|
||||
export function baseUrl(): string {
|
||||
return SdkConfig.get("matrix_to_url") ?? DEFAULT_BASE_URL;
|
||||
}
|
||||
|
||||
export function host(): string {
|
||||
return new URL(baseUrl()).host;
|
||||
}
|
||||
|
||||
export function baseUrlPattern(): string {
|
||||
return `^(?:https?://)?${host().replaceAll(".", "\\.")}/#/(.*)`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates matrix.to permalinks
|
||||
@@ -21,23 +38,23 @@ export default class MatrixToPermalinkConstructor extends PermalinkConstructor {
|
||||
}
|
||||
|
||||
public forEvent(roomId: string, eventId: string, serverCandidates: string[]): string {
|
||||
return `${baseUrl}/#/${roomId}/${eventId}${this.encodeServerCandidates(serverCandidates)}`;
|
||||
return `${baseUrl()}/#/${roomId}/${eventId}${this.encodeServerCandidates(serverCandidates)}`;
|
||||
}
|
||||
|
||||
public forRoom(roomIdOrAlias: string, serverCandidates: string[]): string {
|
||||
return `${baseUrl}/#/${roomIdOrAlias}${this.encodeServerCandidates(serverCandidates)}`;
|
||||
return `${baseUrl()}/#/${roomIdOrAlias}${this.encodeServerCandidates(serverCandidates)}`;
|
||||
}
|
||||
|
||||
public forUser(userId: string): string {
|
||||
return `${baseUrl}/#/${userId}`;
|
||||
return `${baseUrl()}/#/${userId}`;
|
||||
}
|
||||
|
||||
public forEntity(entityId: string): string {
|
||||
return `${baseUrl}/#/${entityId}`;
|
||||
return `${baseUrl()}/#/${entityId}`;
|
||||
}
|
||||
|
||||
public isPermalinkHost(testHost: string): boolean {
|
||||
return testHost === host;
|
||||
return testHost === host();
|
||||
}
|
||||
|
||||
public encodeServerCandidates(candidates: string[]): string {
|
||||
@@ -52,7 +69,7 @@ export default class MatrixToPermalinkConstructor extends PermalinkConstructor {
|
||||
throw new Error("Does not appear to be a permalink");
|
||||
}
|
||||
|
||||
const matches = [...fullUrl.matchAll(new RegExp(baseUrlPattern, "gi"))][0];
|
||||
const matches = [...fullUrl.matchAll(new RegExp(baseUrlPattern(), "gi"))][0];
|
||||
|
||||
if (!matches || matches.length < 2) {
|
||||
throw new Error("Does not appear to be a permalink");
|
||||
|
||||
@@ -16,6 +16,7 @@ import MatrixToPermalinkConstructor, {
|
||||
baseUrl as matrixtoBaseUrl,
|
||||
baseUrlPattern as matrixToBaseUrlPattern,
|
||||
} from "./MatrixToPermalinkConstructor";
|
||||
// `matrixtoBaseUrl` and `matrixToBaseUrlPattern` are functions (config-driven); call them at use sites.
|
||||
import { type PermalinkParts } from "./PermalinkConstructor";
|
||||
import type PermalinkConstructor from "./PermalinkConstructor";
|
||||
import ElementPermalinkConstructor from "./ElementPermalinkConstructor";
|
||||
@@ -342,13 +343,13 @@ export function tryTransformEntityToPermalink(matrixClient: MatrixClient, entity
|
||||
if (permalinkParts) {
|
||||
if (permalinkParts.roomIdOrAlias) {
|
||||
const eventIdPart = permalinkParts.eventId ? `/${permalinkParts.eventId}` : "";
|
||||
let pl = matrixtoBaseUrl + `/#/${permalinkParts.roomIdOrAlias}${eventIdPart}`;
|
||||
let pl = matrixtoBaseUrl() + `/#/${permalinkParts.roomIdOrAlias}${eventIdPart}`;
|
||||
if (permalinkParts.viaServers?.length) {
|
||||
pl += new MatrixToPermalinkConstructor().encodeServerCandidates(permalinkParts.viaServers);
|
||||
}
|
||||
return pl;
|
||||
} else if (permalinkParts.userId) {
|
||||
return matrixtoBaseUrl + `/#/${permalinkParts.userId}`;
|
||||
return matrixtoBaseUrl() + `/#/${permalinkParts.userId}`;
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
@@ -437,7 +438,7 @@ export function getPrimaryPermalinkEntity(permalink: string): string | null {
|
||||
*/
|
||||
function getPermalinkConstructor(isPill = false): PermalinkConstructor {
|
||||
const elementPrefix = SdkConfig.get("permalink_prefix");
|
||||
if (elementPrefix && elementPrefix !== matrixtoBaseUrl && !isPill) {
|
||||
if (elementPrefix && elementPrefix !== matrixtoBaseUrl() && !isPill) {
|
||||
return new ElementPermalinkConstructor(elementPrefix);
|
||||
}
|
||||
|
||||
@@ -448,7 +449,7 @@ export function parsePermalink(fullUrl: string): PermalinkParts | null {
|
||||
try {
|
||||
const elementPrefix = SdkConfig.get("permalink_prefix");
|
||||
const decodedUrl = decodeURIComponent(fullUrl);
|
||||
if (new RegExp(matrixToBaseUrlPattern, "i").test(decodedUrl)) {
|
||||
if (new RegExp(matrixToBaseUrlPattern(), "i").test(decodedUrl)) {
|
||||
return new MatrixToPermalinkConstructor().parsePermalink(decodedUrl);
|
||||
} else if (fullUrl.startsWith("matrix:")) {
|
||||
return new MatrixSchemePermalinkConstructor().parsePermalink(fullUrl);
|
||||
|
||||
@@ -149,7 +149,7 @@ async function start(): Promise<void> {
|
||||
const isAndroid = /Android/.test(navigator.userAgent);
|
||||
if (isIos || isAndroid) {
|
||||
if (document.cookie.indexOf("element_mobile_redirect_to_guide=false") === -1) {
|
||||
window.location.href = "https://healthchat.ch";
|
||||
window.location.href = "mobile_guide/";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,31 +20,31 @@
|
||||
<feGaussianBlur stdDeviation="16.3415" result="effect1_foregroundBlur_382_1634"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_382_1634" x1="141.636" y1="133.796" x2="141.636" y2="32.6829" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#062993"/>
|
||||
<stop offset="0.040404" stop-color="#02389D"/>
|
||||
<stop offset="0.0808081" stop-color="#0045A6"/>
|
||||
<stop offset="0.121212" stop-color="#0051AD"/>
|
||||
<stop offset="0.161616" stop-color="#005DB4"/>
|
||||
<stop offset="0.20202" stop-color="#0069BA"/>
|
||||
<stop offset="0.242424" stop-color="#0075BB"/>
|
||||
<stop offset="0.282828" stop-color="#0081BB"/>
|
||||
<stop offset="0.323232" stop-color="#008CB9"/>
|
||||
<stop offset="0.363636" stop-color="#0098B7"/>
|
||||
<stop offset="0.40404" stop-color="#00A3B3"/>
|
||||
<stop offset="0.444444" stop-color="#00AEAD"/>
|
||||
<stop offset="0.484848" stop-color="#00B8A4"/>
|
||||
<stop offset="0.525253" stop-color="#00C2A0"/>
|
||||
<stop offset="0.565657" stop-color="#00CC99"/>
|
||||
<stop offset="0.606061" stop-color="#3AD396"/>
|
||||
<stop offset="0.646465" stop-color="#5DD898"/>
|
||||
<stop offset="0.686869" stop-color="#79DD99"/>
|
||||
<stop offset="0.727273" stop-color="#92E29B"/>
|
||||
<stop offset="0.767677" stop-color="#A8E69F"/>
|
||||
<stop offset="0.808081" stop-color="#BBEAA5"/>
|
||||
<stop offset="0.848485" stop-color="#CDEEAE"/>
|
||||
<stop offset="0.888889" stop-color="#DCF2B9"/>
|
||||
<stop offset="0.929293" stop-color="#EAF6C7"/>
|
||||
<stop offset="0.969697" stop-color="#F5FBD5"/>
|
||||
<stop stop-color="#12325C"/>
|
||||
<stop offset="0.040404" stop-color="#143561"/>
|
||||
<stop offset="0.0808081" stop-color="#153966"/>
|
||||
<stop offset="0.121212" stop-color="#173C6C"/>
|
||||
<stop offset="0.161616" stop-color="#194071"/>
|
||||
<stop offset="0.20202" stop-color="#1A4376"/>
|
||||
<stop offset="0.242424" stop-color="#1C467B"/>
|
||||
<stop offset="0.282828" stop-color="#1D4A80"/>
|
||||
<stop offset="0.323232" stop-color="#1F4D85"/>
|
||||
<stop offset="0.363636" stop-color="#225187"/>
|
||||
<stop offset="0.40404" stop-color="#255588"/>
|
||||
<stop offset="0.444444" stop-color="#28588A"/>
|
||||
<stop offset="0.484848" stop-color="#2B5C8B"/>
|
||||
<stop offset="0.525253" stop-color="#2E608D"/>
|
||||
<stop offset="0.565657" stop-color="#31638E"/>
|
||||
<stop offset="0.606061" stop-color="#346790"/>
|
||||
<stop offset="0.646465" stop-color="#3B6D93"/>
|
||||
<stop offset="0.686869" stop-color="#527E9F"/>
|
||||
<stop offset="0.727273" stop-color="#698FAB"/>
|
||||
<stop offset="0.767677" stop-color="#81A0B8"/>
|
||||
<stop offset="0.808081" stop-color="#98B1C4"/>
|
||||
<stop offset="0.848485" stop-color="#AFC2D0"/>
|
||||
<stop offset="0.888889" stop-color="#C6D3DC"/>
|
||||
<stop offset="0.929293" stop-color="#DEE4E9"/>
|
||||
<stop offset="0.969697" stop-color="#F5F5F5"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_382_1634">
|
||||
<rect width="375" height="178" fill="white"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
@@ -3,11 +3,12 @@
|
||||
Please note: This page is similar to the one at mobile.element.io so any changes made here can potentially
|
||||
be applied to that site as well. They still share the mobile-apps.ts file for updating the app metadata.
|
||||
-->
|
||||
<html lang="en">
|
||||
<html lang="de">
|
||||
<head>
|
||||
<title>Element Mobile Guide</title>
|
||||
<meta charset="utf-8" />
|
||||
<title>HealthChat für Smartphone und Tablet</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="apple-itunes-app" content="app-id=id1631335820" />
|
||||
<meta name="apple-itunes-app" content="app-id=id6743060078" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -19,10 +20,15 @@
|
||||
<header>
|
||||
<div class="mx_HomePage_header">
|
||||
<div>
|
||||
<img src="./assets/element-logo.svg" alt="Element Logo" width="148px" height="32px" />
|
||||
<img
|
||||
src="../themes/element/img/logos/element-logo.png"
|
||||
alt="HealthChat Logo"
|
||||
width="32px"
|
||||
height="32px"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p id="header_title">Join Element.</p>
|
||||
<p id="header_title">HealthChat auf dem Smartphone</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
@@ -31,8 +37,8 @@
|
||||
<main>
|
||||
<div class="mx_HomePage_col mx_Spacer">
|
||||
<p>
|
||||
The <a id="back_to_element_button" href="#" class="mx_DesktopLink">desktop site</a> does
|
||||
<b>not</b> work on mobile, please download the app.
|
||||
Die Web-Version ist für den Desktop gedacht und funktioniert auf Smartphone und Tablet
|
||||
<b>nicht</b>. Für Smartphone und Tablet gibt es die HealthChat-App.
|
||||
</p>
|
||||
</div>
|
||||
<div class="mx_HomePage_col mx_Spacer">
|
||||
@@ -41,44 +47,38 @@
|
||||
<span>1</span>
|
||||
</div>
|
||||
<div>
|
||||
<h1 id="step1_heading">Download Element</h1>
|
||||
<h1 id="step1_heading">HealthChat-App laden</h1>
|
||||
<div class="mx_StoreLinks">
|
||||
<a
|
||||
href="https://apps.apple.com/app/element-x-secure-chat-call/id1631335820"
|
||||
href="https://apps.apple.com/ch/app/healthchat/id6743060078"
|
||||
target="_blank"
|
||||
class="mx_StoreBadge"
|
||||
id="app_store_link"
|
||||
>
|
||||
<img
|
||||
src="./assets/app-store-badge.svg"
|
||||
alt="Download on the App Store."
|
||||
alt="Im App Store laden."
|
||||
width="120px"
|
||||
height="40px"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
href="https://play.google.com/store/apps/details?id=io.element.android.x"
|
||||
href="https://play.google.com/store/apps/details?id=ch.healthchat.element"
|
||||
target="_blank"
|
||||
class="mx_StoreBadge"
|
||||
id="play_store_link"
|
||||
>
|
||||
<img
|
||||
src="./assets/google-play-badge.svg"
|
||||
alt="Get it on Google Play."
|
||||
alt="Jetzt bei Google Play."
|
||||
width="135px"
|
||||
height="40px"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<p id="f_droid_section">
|
||||
Also available on
|
||||
<a
|
||||
href="https://f-droid.org/packages/io.element.android.x"
|
||||
target="_blank"
|
||||
class="mx_ClearDecoration"
|
||||
id="f_droid_link"
|
||||
>F-Droid</a
|
||||
>
|
||||
<p id="f_droid_section" style="display: none">
|
||||
Auch verfügbar auf
|
||||
<a href="#" target="_blank" class="mx_ClearDecoration" id="f_droid_link">F-Droid</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -89,12 +89,19 @@
|
||||
<span>2</span>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Come back here to sign in</h1>
|
||||
<p id="step2_description">This will set up your app</p>
|
||||
<a class="mx_Button" id="deep_link_button" href="#">Sign in</a>
|
||||
<h1>Danach hier anmelden</h1>
|
||||
<p id="step2_description">Damit wird die App eingerichtet</p>
|
||||
<a class="mx_Button" id="deep_link_button" href="#">Anmelden</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mx_HomePage_col mx_Spacer">
|
||||
<p>
|
||||
<a id="back_to_element_button" href="#" class="mx_DesktopLink"
|
||||
>Trotzdem die Web-Version öffnen</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ function onBackToElementClick(): void {
|
||||
// NEVER pass user-controlled content to this function! Hardcoded strings only please.
|
||||
function renderConfigError(message: string): void {
|
||||
const contactMsg =
|
||||
"If this is unexpected, please contact your system administrator " + "or technical support representative.";
|
||||
message = `<h2>Error loading Element</h2><p>${message}</p><p>${contactMsg}</p>`;
|
||||
"Falls das unerwartet ist, bitte den Systemadministrator " + "oder den technischen Support kontaktieren.";
|
||||
message = `<h2>HealthChat konnte nicht geladen werden</h2><p>${message}</p><p>${contactMsg}</p>`;
|
||||
|
||||
const toHide = document.getElementsByClassName("mx_HomePage_container");
|
||||
const errorContainers = document.getElementsByClassName(
|
||||
@@ -59,12 +59,12 @@ async function initPage(): Promise<void> {
|
||||
const incompatibleOptions = [wkConfig, serverName, defaultHsUrl].filter((i) => !!i);
|
||||
if (defaultHsUrl && (wkConfig || serverName)) {
|
||||
return renderConfigError(
|
||||
"Invalid configuration: a default_hs_url can't be specified along with default_server_name " +
|
||||
"or default_server_config",
|
||||
"Ungültige Konfiguration: default_hs_url kann nicht zusammen mit default_server_name " +
|
||||
"oder default_server_config angegeben werden",
|
||||
);
|
||||
}
|
||||
if (incompatibleOptions.length < 1) {
|
||||
return renderConfigError("Invalid configuration: no default server specified.");
|
||||
return renderConfigError("Ungültige Konfiguration: kein Standard-Server angegeben.");
|
||||
}
|
||||
|
||||
let hsUrl: string | undefined;
|
||||
@@ -100,7 +100,7 @@ async function initPage(): Promise<void> {
|
||||
}
|
||||
} else {
|
||||
logger.error(e);
|
||||
return renderConfigError("Unable to fetch homeserver configuration");
|
||||
return renderConfigError("Homeserver-Konfiguration konnte nicht geladen werden");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ async function initPage(): Promise<void> {
|
||||
}
|
||||
|
||||
if (!hsUrl) {
|
||||
return renderConfigError("Unable to locate homeserver");
|
||||
return renderConfigError("Homeserver konnte nicht gefunden werden");
|
||||
}
|
||||
|
||||
if (hsUrl && !hsUrl.endsWith("/")) hsUrl += "/";
|
||||
@@ -131,7 +131,7 @@ async function initPage(): Promise<void> {
|
||||
// Not part of updateMobilePage as the link is only shown on mobile_guide and not on mobile.element.io
|
||||
document.getElementById("back_to_element_button")!.onclick = onBackToElementClick;
|
||||
|
||||
updateMobilePage(metadata, deepLinkUrl, serverName ?? hsUrl);
|
||||
updateMobilePage(metadata, deepLinkUrl);
|
||||
}
|
||||
|
||||
void initPage();
|
||||
|
||||
@@ -38,12 +38,11 @@ export const mobileApps: Record<MobileAppVariant, MobileAppMetadata> = {
|
||||
isProApp: false,
|
||||
},
|
||||
[MobileAppVariant.X]: {
|
||||
name: "Element X",
|
||||
appleAppId: "id1631335820",
|
||||
appStoreUrl: "https://apps.apple.com/app/element-x-secure-chat-call/id1631335820",
|
||||
playStoreUrl: "https://play.google.com/store/apps/details?id=io.element.android.x",
|
||||
fDroidUrl: "https://f-droid.org/packages/io.element.android.x",
|
||||
deepLinkPath: "/element",
|
||||
name: "HealthChat",
|
||||
appleAppId: "id6743060078",
|
||||
appStoreUrl: "https://apps.apple.com/ch/app/healthchat/id6743060078",
|
||||
playStoreUrl: "https://play.google.com/store/apps/details?id=ch.healthchat.element",
|
||||
deepLinkPath: "",
|
||||
usesLegacyDeepLink: false,
|
||||
isProApp: false,
|
||||
},
|
||||
@@ -58,18 +57,17 @@ export const mobileApps: Record<MobileAppVariant, MobileAppMetadata> = {
|
||||
},
|
||||
};
|
||||
|
||||
export function updateMobilePage(metadata: MobileAppMetadata, deepLinkUrl: string, server: string | undefined): void {
|
||||
export function updateMobilePage(metadata: MobileAppMetadata, deepLinkUrl: string): void {
|
||||
const appleMeta = document.querySelector('meta[name="apple-itunes-app"]') as Element;
|
||||
appleMeta.setAttribute("content", `app-id=${metadata.appleAppId}`);
|
||||
|
||||
if (server) {
|
||||
(document.getElementById("header_title") as HTMLHeadingElement).innerText = `Join ${server} on Element`;
|
||||
}
|
||||
(document.getElementById("header_title") as HTMLHeadingElement).innerText = `${metadata.name} auf dem Smartphone`;
|
||||
(document.getElementById("app_store_link") as HTMLAnchorElement).href = metadata.appStoreUrl;
|
||||
(document.getElementById("play_store_link") as HTMLAnchorElement).href = metadata.playStoreUrl;
|
||||
|
||||
if (metadata.fDroidUrl) {
|
||||
(document.getElementById("f_droid_link") as HTMLAnchorElement).href = metadata.fDroidUrl;
|
||||
document.getElementById("f_droid_section")!.style.display = "";
|
||||
} else {
|
||||
document.getElementById("f_droid_section")!.style.display = "none";
|
||||
}
|
||||
@@ -77,11 +75,12 @@ export function updateMobilePage(metadata: MobileAppMetadata, deepLinkUrl: strin
|
||||
const step1Heading = document.getElementById("step1_heading")!;
|
||||
step1Heading.innerHTML = step1Heading!.innerHTML.replace("Element", metadata.name);
|
||||
|
||||
// Step 2 is only shown on the mobile guide, not on mobile.element.io
|
||||
if (document.getElementById("step2_container")) {
|
||||
// Step 2 is only shown on the mobile guide, not on mobile.element.io,
|
||||
// and only for apps that offer a sign-in deep link
|
||||
if (document.getElementById("step2_container") && (metadata.deepLinkPath || metadata.usesLegacyDeepLink)) {
|
||||
document.getElementById("step2_container")!.style.display = "block";
|
||||
if (metadata.isProApp) {
|
||||
document.getElementById("step2_description")!.innerHTML = "Use your work email to join";
|
||||
document.getElementById("step2_description")!.innerHTML = "Mit der Arbeits-E-Mail-Adresse anmelden";
|
||||
}
|
||||
(document.getElementById("deep_link_button") as HTMLAnchorElement).href = deepLinkUrl;
|
||||
}
|
||||
|
||||
@@ -200,8 +200,7 @@ describe("<UserSettingsDialog />", () => {
|
||||
expect(screen.getByRole("heading", { level: 1 })).toHaveTextContent("Ignored Users");
|
||||
});
|
||||
|
||||
// HealthChat disables the Help tab "for now" (UserSettingsDialog.tsx). Restore when re-enabled.
|
||||
it.skip("renders with help tab selected", () => {
|
||||
it("renders with help tab selected", () => {
|
||||
const { container } = render(getComponent({ initialTabId: UserTab.Help }));
|
||||
|
||||
expect(getActiveTabLabel(container)).toEqual("Help & About");
|
||||
|
||||
+29
@@ -219,5 +219,34 @@ NodeList [
|
||||
Encryption
|
||||
</span>
|
||||
</li>,
|
||||
<li
|
||||
aria-controls="mx_tabpanel_USER_HELP_TAB"
|
||||
aria-selected="false"
|
||||
class="mx_AccessibleButton mx_TabbedView_tabLabel"
|
||||
data-testid="settings-tab-USER_HELP_TAB"
|
||||
role="tab"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 8a1.5 1.5 0 0 0-1.5 1.5 1 1 0 1 1-2 0 3.5 3.5 0 1 1 6.01 2.439q-.183.188-.352.355c-.287.288-.54.54-.76.824-.293.375-.398.651-.398.882a1 1 0 1 1-2 0c0-.874.407-1.58.819-2.11.305-.392.688-.775 1-1.085l.257-.26A1.5 1.5 0 0 0 12 8m1 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0"
|
||||
/>
|
||||
<path
|
||||
d="M8.1 21.213A9.7 9.7 0 0 0 12 22a9.7 9.7 0 0 0 3.9-.788 10.1 10.1 0 0 0 3.175-2.137q1.35-1.35 2.137-3.175A9.7 9.7 0 0 0 22 12a9.7 9.7 0 0 0-.788-3.9 10.1 10.1 0 0 0-2.137-3.175q-1.35-1.35-3.175-2.137A9.7 9.7 0 0 0 12 2a9.7 9.7 0 0 0-3.9.788 10.1 10.1 0 0 0-3.175 2.137Q3.575 6.275 2.788 8.1A9.7 9.7 0 0 0 2 12q0 2.075.788 3.9a10.1 10.1 0 0 0 2.137 3.175q1.35 1.35 3.175 2.137m9.575-3.538Q15.35 20 12 20t-5.675-2.325T4 12t2.325-5.675T12 4t5.675 2.325T20 12t-2.325 5.675"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="mx_TabbedView_tabLabel_text"
|
||||
id="mx_tabpanel_USER_HELP_TAB_label"
|
||||
>
|
||||
Help & About
|
||||
</span>
|
||||
</li>,
|
||||
]
|
||||
`;
|
||||
|
||||
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import MatrixToPermalinkConstructor from "../../../../src/utils/permalinks/MatrixToPermalinkConstructor";
|
||||
import { PermalinkParts } from "../../../../src/utils/permalinks/PermalinkConstructor";
|
||||
import SdkConfig from "../../../../src/SdkConfig";
|
||||
|
||||
describe("MatrixToPermalinkConstructor", () => {
|
||||
const peramlinkConstructor = new MatrixToPermalinkConstructor();
|
||||
@@ -49,4 +50,32 @@ describe("MatrixToPermalinkConstructor", () => {
|
||||
).toEqual("https://matrix.to/#/!myroom:example.com/$event4?via=one.example.com&via=two.example.com");
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a custom matrix_to_url config", () => {
|
||||
beforeEach(() => {
|
||||
SdkConfig.add({ matrix_to_url: "https://to.healthchat.ch" });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
SdkConfig.reset();
|
||||
});
|
||||
|
||||
it("generates links against the configured host", () => {
|
||||
const constructor = new MatrixToPermalinkConstructor();
|
||||
expect(constructor.forUser("@user:example.com")).toEqual("https://to.healthchat.ch/#/@user:example.com");
|
||||
expect(constructor.forRoom("!myroom:example.com", [])).toEqual(
|
||||
"https://to.healthchat.ch/#/!myroom:example.com",
|
||||
);
|
||||
});
|
||||
|
||||
it("parses links from the configured host and rejects matrix.to links", () => {
|
||||
const constructor = new MatrixToPermalinkConstructor();
|
||||
expect(constructor.parsePermalink("https://to.healthchat.ch/#/@user:example.com")).toEqual(
|
||||
new PermalinkParts(null, null, "@user:example.com", null),
|
||||
);
|
||||
expect(() => constructor.parsePermalink("https://matrix.to/#/@user:example.com")).toThrow(
|
||||
new Error("Does not appear to be a permalink"),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -728,6 +728,18 @@ export default (env: string, argv: Record<string, any>): webpack.Configuration =
|
||||
context: path.join(getPackageRoot("@element-hq/element-call-embedded"), "dist"),
|
||||
to: path.join(__dirname, "webapp", "widgets", "element-call"),
|
||||
},
|
||||
// HealthChat: overwrite the embedded Element Call config with one that carries a
|
||||
// LiveKit fallback. Element Call fetches https://healthchat.ch/.well-known/matrix/client
|
||||
// itself from the widget origin; over IPv4 that host is served by Wix, which answers
|
||||
// a 301 to matrix.healthchat.ch without an Access-Control-Allow-Origin header, so
|
||||
// the fetch fails CORS on IPv4-only networks and Element Call falls back to this
|
||||
// file. Without the livekit block it errors with MISSING_MATRIX_RTC_TRANSPORT.
|
||||
// Keep the matrix_rtc_session timers in sync with what the package ships.
|
||||
{
|
||||
from: "res/element-call-config.json",
|
||||
to: path.join(__dirname, "webapp", "widgets", "element-call", "config.json"),
|
||||
force: true,
|
||||
},
|
||||
// Mobile guide assets
|
||||
{
|
||||
from: "assets/**",
|
||||
|
||||
@@ -125,6 +125,10 @@ complete re-branding/private labeling, a more personalised experience can be ach
|
||||
3. `brand`: Optional name for the app. Defaults to `Element`. This is used throughout the application in various strings/locations.
|
||||
4. `permalink_prefix`: An optional URL pointing to an Element Web deployment. For example, `https://app.element.io`. This will
|
||||
change all permalinks (via the "Share" menus) to point at the Element Web deployment rather than `matrix.to`.
|
||||
4a. `matrix_to_url`: An optional base URL of a matrix.to-compatible resolver to use for Share links and QR codes instead of
|
||||
the public `https://matrix.to`. Unlike `permalink_prefix` (which points at an Element Web deployment and uses Element's
|
||||
`/#/room/…` URL format), this keeps the matrix.to URL format (`/#/<entity>`), so it must point at a matrix.to deployment or
|
||||
fork. For example, `https://to.example.com`.
|
||||
5. `desktop_builds`: Optional. Where the desktop builds for the application are, if available. This is explained in more detail
|
||||
down below.
|
||||
6. `mobile_builds`: Optional. Like `desktop_builds`, except for the mobile apps. Also described in more detail down below.
|
||||
|
||||
Generated
+77
-356
@@ -422,8 +422,8 @@ importers:
|
||||
specifier: 'catalog:'
|
||||
version: 4.1.7(@vitest/browser@4.1.7)(vitest@4.1.7)
|
||||
app-builder-lib:
|
||||
specifier: 26.11.1
|
||||
version: 26.11.1(dmg-builder@26.11.1)(electron-builder-squirrel-windows@26.11.1)
|
||||
specifier: 26.16.1
|
||||
version: 26.16.1(dmg-builder@26.16.1)(electron-builder-squirrel-windows@26.16.1)
|
||||
chokidar:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
@@ -434,11 +434,11 @@ importers:
|
||||
specifier: 42.2.0
|
||||
version: 42.2.0
|
||||
electron-builder:
|
||||
specifier: 26.11.1
|
||||
version: 26.11.1(electron-builder-squirrel-windows@26.11.1)
|
||||
specifier: 26.16.1
|
||||
version: 26.16.1(electron-builder-squirrel-windows@26.16.1)
|
||||
electron-builder-squirrel-windows:
|
||||
specifier: 26.11.1
|
||||
version: 26.11.1(dmg-builder@26.11.1)
|
||||
specifier: 26.16.1
|
||||
version: 26.16.1(dmg-builder@26.16.1)
|
||||
electron-devtools-installer:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
@@ -778,7 +778,7 @@ importers:
|
||||
version: 1.2.7(html-webpack-plugin@5.6.7(webpack@5.107.1))(webpack@5.107.1)
|
||||
'@sentry/webpack-plugin':
|
||||
specifier: ^5.0.0
|
||||
version: 5.3.0(encoding@0.1.13)(webpack@5.107.1)
|
||||
version: 5.3.0(webpack@5.107.1)
|
||||
'@stylistic/eslint-plugin':
|
||||
specifier: ^5.0.0
|
||||
version: 5.10.0(eslint@8.57.1)
|
||||
@@ -1416,9 +1416,6 @@ importers:
|
||||
|
||||
packages:
|
||||
|
||||
7zip-bin@5.2.0:
|
||||
resolution: {integrity: sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==}
|
||||
|
||||
'@action-validator/cli@0.6.0':
|
||||
resolution: {integrity: sha512-Z8TYOK4GqUIpI0UuspUJPB6dhr0niTumhwI5iiZVqFRXm4u05bZawnFKltpvoFUfJg9mHbbIBlleqsRJAgl53Q==}
|
||||
hasBin: true
|
||||
@@ -2599,10 +2596,6 @@ packages:
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
'@develar/schema-utils@2.6.5':
|
||||
resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==}
|
||||
engines: {node: '>= 8.9.0'}
|
||||
|
||||
'@discoveryjs/json-ext@0.6.3':
|
||||
resolution: {integrity: sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==}
|
||||
engines: {node: '>=14.17.0'}
|
||||
@@ -2691,8 +2684,8 @@ packages:
|
||||
engines: {node: '>=12.0.0'}
|
||||
hasBin: true
|
||||
|
||||
'@electron/rebuild@4.0.3':
|
||||
resolution: {integrity: sha512-u9vpTHRMkOYCs/1FLiSVAFZ7FbjsXK+bQuzviJZa+lG7BHZl1nz52/IcGvwa3sk80/fc3llutBkbCq10Vh8WQA==}
|
||||
'@electron/rebuild@4.2.0':
|
||||
resolution: {integrity: sha512-RKL/O+jGoXJMxrx/5771y1n0xTKmFuOYGO3gMmwypBM6rsH0kou0mswwdXA2JrhIkE4xyC7v9vGk0n6NPzgOxQ==}
|
||||
engines: {node: '>=22.12.0'}
|
||||
hasBin: true
|
||||
|
||||
@@ -3423,6 +3416,10 @@ packages:
|
||||
resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@noble/hashes@1.8.0':
|
||||
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
|
||||
engines: {node: ^14.21.3 || >=16}
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -3435,18 +3432,10 @@ packages:
|
||||
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
'@npmcli/agent@3.0.0':
|
||||
resolution: {integrity: sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
'@npmcli/agent@4.0.0':
|
||||
resolution: {integrity: sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
|
||||
'@npmcli/fs@4.0.0':
|
||||
resolution: {integrity: sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
'@npmcli/fs@5.0.0':
|
||||
resolution: {integrity: sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -5885,9 +5874,6 @@ packages:
|
||||
'@types/picomatch@4.0.2':
|
||||
resolution: {integrity: sha512-qHHxQ+P9PysNEGbALT8f8YOSHW0KJu6l2xU8DYY0fu/EmGxXdVnuTLvFUvBgPJMSqXq29SYHveejeAha+4AYgA==}
|
||||
|
||||
'@types/plist@3.0.5':
|
||||
resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==}
|
||||
|
||||
'@types/png-chunks-extract@1.0.2':
|
||||
resolution: {integrity: sha512-z6djfFIbrrddtunoMJBOPlyZrnmeuG1kkvHUNi2QfpOb+JMMLuLliHHTmMyRi7k7LiTAut0HbdGCF6ibDtQAHQ==}
|
||||
|
||||
@@ -5997,9 +5983,6 @@ packages:
|
||||
'@types/unist@3.0.3':
|
||||
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
|
||||
|
||||
'@types/verror@1.10.11':
|
||||
resolution: {integrity: sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==}
|
||||
|
||||
'@types/web-bluetooth@0.0.21':
|
||||
resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==}
|
||||
|
||||
@@ -6446,6 +6429,7 @@ packages:
|
||||
'@xmldom/xmldom@0.8.13':
|
||||
resolution: {integrity: sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
deprecated: this version has critical issues, please update to the latest version
|
||||
|
||||
'@xtuc/ieee754@1.2.0':
|
||||
resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
|
||||
@@ -6473,10 +6457,6 @@ packages:
|
||||
'@zxcvbn-ts/language-en@3.0.2':
|
||||
resolution: {integrity: sha512-Zp+zL+I6Un2Bj0tRXNs6VUBq3Djt+hwTwUz4dkt2qgsQz47U0/XthZ4ULrT/RxjwJRl5LwiaKOOZeOtmixHnjg==}
|
||||
|
||||
abbrev@3.0.1:
|
||||
resolution: {integrity: sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
abbrev@4.0.0:
|
||||
resolution: {integrity: sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -6621,15 +6601,12 @@ packages:
|
||||
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
app-builder-bin@5.0.0-alpha.12:
|
||||
resolution: {integrity: sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==}
|
||||
|
||||
app-builder-lib@26.11.1:
|
||||
resolution: {integrity: sha512-KCZm58CifmTGbzw9PZOyDEecwjY3jY9cQ4uBRIDxZYhaJqqsz0RQFkryoV+EPhjVlkPql7Jsg6SNUkz837Bkhw==}
|
||||
app-builder-lib@26.16.1:
|
||||
resolution: {integrity: sha512-FhaO6YOup01ZfQW0Z6gt3AyukJjv1gW4uFK47jTgwcHZKqyN/fSlK2LqPf9tAeZYLP2bRJLDzeOkRImsw2X4Pg==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
dmg-builder: 26.11.1
|
||||
electron-builder-squirrel-windows: 26.11.1
|
||||
dmg-builder: 26.16.1
|
||||
electron-builder-squirrel-windows: 26.16.1
|
||||
|
||||
applescript@1.0.0:
|
||||
resolution: {integrity: sha512-yvtNHdWvtbYEiIazXAdp/NY+BBb65/DAseqlNiJQjOx9DynuzOYDbVLBJvuc0ve0VL9x6B3OHF6eH52y9hCBtQ==}
|
||||
@@ -6704,10 +6681,6 @@ packages:
|
||||
resolution: {integrity: sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
assert-plus@1.0.0:
|
||||
resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
|
||||
engines: {node: '>=0.8'}
|
||||
|
||||
assert@2.1.0:
|
||||
resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==}
|
||||
|
||||
@@ -6771,6 +6744,9 @@ packages:
|
||||
await-lock@3.0.0:
|
||||
resolution: {integrity: sha512-eO6fLiSnrJrMdjWMNK8zbVRXPs2TKJg78iKZd9wDpN3na5tcoV6EoeiOlMgk2QaAQ1gIrK1YuMsJHXWqz89tSA==}
|
||||
|
||||
aws4@1.13.2:
|
||||
resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==}
|
||||
|
||||
axe-core@4.11.4:
|
||||
resolution: {integrity: sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -7077,12 +7053,12 @@ packages:
|
||||
resolution: {integrity: sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
|
||||
builder-util-runtime@9.6.1:
|
||||
resolution: {integrity: sha512-gnk+lN50T7TIRp4bHTVydSnWsNkYAxGiDDbed3U26Z82s1lr8em4E4fLs/EPfIEZIbfi4Zfo5NsdA9gHWbPmXg==}
|
||||
builder-util-runtime@9.7.0:
|
||||
resolution: {integrity: sha512-g/kR520giAFYkSXTzcmF3kqQq7wi8F6N6SzeDgZrqTBN+VHdmgWOyTdD1yD7AATDId/yXLvuP34CxW46/BwCdw==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
builder-util@26.11.1:
|
||||
resolution: {integrity: sha512-oWRbAjgN9RdVCLvNVN9ltZwaUkrH/FrH8wdggAwpz426PTdcbGEARp7J1HXad/QijURPxYL+BKykThaRjluPIQ==}
|
||||
builder-util@26.16.0:
|
||||
resolution: {integrity: sha512-RLyJhB7Si3YkzKR9ubQslWuXW3Vhs3CGe1i+SeixBZ0qTd1mk3XBmssvY22TlB6CS5blyko8Gu1JzpYk8UkYAg==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
builtin-modules@3.3.0:
|
||||
@@ -7108,10 +7084,6 @@ packages:
|
||||
resolution: {integrity: sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
||||
cacache@19.0.1:
|
||||
resolution: {integrity: sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
cacache@20.0.4:
|
||||
resolution: {integrity: sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -7257,10 +7229,6 @@ packages:
|
||||
resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
cli-truncate@2.1.0:
|
||||
resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
cli-truncate@5.2.0:
|
||||
resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==}
|
||||
engines: {node: '>=20'}
|
||||
@@ -7445,9 +7413,6 @@ packages:
|
||||
core-js@3.48.0:
|
||||
resolution: {integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==}
|
||||
|
||||
core-util-is@1.0.2:
|
||||
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
|
||||
|
||||
core-util-is@1.0.3:
|
||||
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
||||
|
||||
@@ -7499,9 +7464,6 @@ packages:
|
||||
resolution: {integrity: sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
crc@3.8.0:
|
||||
resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==}
|
||||
|
||||
create-ecdh@4.0.4:
|
||||
resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==}
|
||||
|
||||
@@ -8006,14 +7968,8 @@ packages:
|
||||
dir-compare@4.2.0:
|
||||
resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==}
|
||||
|
||||
dmg-builder@26.11.1:
|
||||
resolution: {integrity: sha512-uFE7wiNn/GJ/MCtHz9ZIYj8w+27WTKush6PX6a1rt7RWJ5Ua4WgK6PAgErSBQXk0Q8UM4YMTXUBNFhN1gR+1qw==}
|
||||
|
||||
dmg-license@1.0.11:
|
||||
resolution: {integrity: sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==}
|
||||
engines: {node: '>=8'}
|
||||
os: [darwin]
|
||||
hasBin: true
|
||||
dmg-builder@26.16.1:
|
||||
resolution: {integrity: sha512-pnI/3Qb24Uk+rMTgIUrsVUKosVgwmBUdF8Zeb8TexOSbpq8MWc7v6l+n+FrEqVkjNZwzBN+XpDS9ENgZ/rkWAw==}
|
||||
|
||||
dns-packet@5.6.1:
|
||||
resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==}
|
||||
@@ -8150,19 +8106,19 @@ packages:
|
||||
engines: {node: '>=0.12.18'}
|
||||
hasBin: true
|
||||
|
||||
electron-builder-squirrel-windows@26.11.1:
|
||||
resolution: {integrity: sha512-qWplLUSGhcjKClb1G8c9TOI5abYZGsIP7YlA6jSBLPFdSvN+teV30jFZsNgM1KYeMD6liqNZaRjySJ/zSq+X8A==}
|
||||
electron-builder-squirrel-windows@26.16.1:
|
||||
resolution: {integrity: sha512-w0y44wSaT1l6R7CAGmeHn4nHPfvzDyCAU1xJyi1w9SbPYJpYn76SmHDzqHf8Y7l91cPWTdPYBpGQtB2T5mJ08A==}
|
||||
|
||||
electron-builder@26.11.1:
|
||||
resolution: {integrity: sha512-CMG8PQAnUBWIx9THpwWysrHfJQs9Q1E1VDayK+ZkNqvih+ao8mywMP5v2ohLkzlg1ZeVyvkQP6oICJGzyeCAUQ==}
|
||||
electron-builder@26.16.1:
|
||||
resolution: {integrity: sha512-LrLK65QX5PUYYODXqp23FKrV7CILTtVY7mrJckNknO9jLNSMiqFkKbSMiDRw4CjOADMPVDdWLxY4mezOZWswxg==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
hasBin: true
|
||||
|
||||
electron-devtools-installer@4.0.0:
|
||||
resolution: {integrity: sha512-9Tntu/jtfSn0n6N/ZI6IdvRqXpDyLQiDuuIbsBI+dL+1Ef7C8J2JwByw58P3TJiNeuqyV3ZkphpNWuZK5iSY2w==}
|
||||
|
||||
electron-publish@26.11.1:
|
||||
resolution: {integrity: sha512-aMugkYS7QZtS/PjbyOSh0MlymxoWppj7+lEcqmsO1jM6igedcgAdFtmWms3g/DdMPpCZDVKxzkC4a3UK6HGlmA==}
|
||||
electron-publish@26.16.0:
|
||||
resolution: {integrity: sha512-Vt3KzQIiw9BImvNOYtndg9Mjki+tl4+1sQiC/+G5j8khWaENOJFWodiB+sUl6yyHwtd37avehskdtPw7f8y/+Q==}
|
||||
|
||||
electron-store@11.0.2:
|
||||
resolution: {integrity: sha512-4VkNRdN+BImL2KcCi41WvAYbh6zLX5AUTi4so68yPqiItjbgTjqpEnGAqasgnG+lB6GuAyUltKwVopp6Uv+gwQ==}
|
||||
@@ -8227,9 +8183,6 @@ packages:
|
||||
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
encoding@0.1.13:
|
||||
resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
|
||||
|
||||
end-of-stream@1.4.5:
|
||||
resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
|
||||
|
||||
@@ -8644,10 +8597,6 @@ packages:
|
||||
engines: {node: '>= 10.17.0'}
|
||||
hasBin: true
|
||||
|
||||
extsprintf@1.4.1:
|
||||
resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==}
|
||||
engines: {'0': node >=0.6.0}
|
||||
|
||||
fake-indexeddb@6.2.5:
|
||||
resolution: {integrity: sha512-CGnyrvbhPlWYMngksqrSSUT1BAVP49dZocrHuK0SvtR0D5TMs5wP0o3j7jexDJW01KSadjBp1M/71o/KR3nD1w==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -9258,11 +9207,6 @@ packages:
|
||||
resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==}
|
||||
engines: {node: '>=10.18'}
|
||||
|
||||
iconv-corefoundation@1.1.7:
|
||||
resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==}
|
||||
engines: {node: ^8.11.2 || >=10}
|
||||
os: [darwin]
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -9927,6 +9871,7 @@ packages:
|
||||
|
||||
jsrsasign@11.1.3:
|
||||
resolution: {integrity: sha512-nPnK5D/4lv0Dwr7TlzrKtAd8JlLZwFTqTUUB3NQCbtdobcRcohGFxjbPySDVh74iWUudcCsapYT6OxoyhJLhhA==}
|
||||
deprecated: This package is no longer maintained.
|
||||
|
||||
jsx-ast-utils@3.3.5:
|
||||
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
|
||||
@@ -10231,10 +10176,6 @@ packages:
|
||||
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
make-fetch-happen@14.0.3:
|
||||
resolution: {integrity: sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
make-fetch-happen@15.0.5:
|
||||
resolution: {integrity: sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -10472,10 +10413,6 @@ packages:
|
||||
resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
minipass-fetch@4.0.1:
|
||||
resolution: {integrity: sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
minipass-fetch@5.0.2:
|
||||
resolution: {integrity: sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -10488,10 +10425,6 @@ packages:
|
||||
resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
minipass-sized@1.0.3:
|
||||
resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
minipass-sized@2.0.0:
|
||||
resolution: {integrity: sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -10601,9 +10534,6 @@ packages:
|
||||
resolution: {integrity: sha512-Erq5w/t3syw3s4sDsUaX4QttIdBPsGKTT1DTRsCkTonGggczhlDKm/wDX3o+HPJpQ41EjXCbcmXf0tgr5YZJXw==}
|
||||
engines: {node: '>=22.12.0'}
|
||||
|
||||
node-addon-api@1.7.2:
|
||||
resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==}
|
||||
|
||||
node-api-version@0.2.1:
|
||||
resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==}
|
||||
|
||||
@@ -10616,11 +10546,6 @@ packages:
|
||||
encoding:
|
||||
optional: true
|
||||
|
||||
node-gyp@11.5.0:
|
||||
resolution: {integrity: sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
hasBin: true
|
||||
|
||||
node-gyp@12.2.0:
|
||||
resolution: {integrity: sha512-q23WdzrQv48KozXlr0U1v9dwO/k59NHeSzn6loGcasyf0UnSrtzs8kRxM+mfwJSf0DkX0s43hcqgnSO4/VNthQ==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -10639,11 +10564,6 @@ packages:
|
||||
non-layered-tidy-tree-layout@2.0.2:
|
||||
resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==}
|
||||
|
||||
nopt@8.1.0:
|
||||
resolution: {integrity: sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
hasBin: true
|
||||
|
||||
nopt@9.0.0:
|
||||
resolution: {integrity: sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -11552,10 +11472,6 @@ packages:
|
||||
resolution: {integrity: sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==}
|
||||
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
|
||||
|
||||
proc-log@5.0.0:
|
||||
resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
proc-log@6.1.0:
|
||||
resolution: {integrity: sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -12302,10 +12218,6 @@ packages:
|
||||
resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
slice-ansi@3.0.0:
|
||||
resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
slice-ansi@4.0.0:
|
||||
resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -12411,10 +12323,6 @@ packages:
|
||||
ssim.js@3.5.0:
|
||||
resolution: {integrity: sha512-Aj6Jl2z6oDmgYFFbQqK7fght19bXdOxY7Tj03nF+03M9gCBAjeIiO8/PlEGMfKDwYpw4q6iBqVq2YuREorGg/g==}
|
||||
|
||||
ssri@12.0.0:
|
||||
resolution: {integrity: sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
ssri@13.0.1:
|
||||
resolution: {integrity: sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ==}
|
||||
engines: {node: ^20.17.0 || >=22.9.0}
|
||||
@@ -13117,14 +13025,6 @@ packages:
|
||||
resolution: {integrity: sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
unique-filename@4.0.0:
|
||||
resolution: {integrity: sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
unique-slug@5.0.0:
|
||||
resolution: {integrity: sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
unist-util-is@6.0.1:
|
||||
resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
|
||||
|
||||
@@ -13299,10 +13199,6 @@ packages:
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc
|
||||
|
||||
verror@1.10.1:
|
||||
resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==}
|
||||
engines: {node: '>=0.6.0'}
|
||||
|
||||
vfile-message@4.0.3:
|
||||
resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
|
||||
|
||||
@@ -13827,8 +13723,6 @@ packages:
|
||||
|
||||
snapshots:
|
||||
|
||||
7zip-bin@5.2.0: {}
|
||||
|
||||
'@action-validator/cli@0.6.0(@action-validator/core@0.6.0)':
|
||||
dependencies:
|
||||
'@action-validator/core': 0.6.0
|
||||
@@ -15239,11 +15133,6 @@ snapshots:
|
||||
dependencies:
|
||||
postcss: 8.5.15
|
||||
|
||||
'@develar/schema-utils@2.6.5':
|
||||
dependencies:
|
||||
ajv: 6.15.0
|
||||
ajv-keywords: 3.5.2(ajv@6.15.0)
|
||||
|
||||
'@discoveryjs/json-ext@0.6.3': {}
|
||||
|
||||
'@discoveryjs/json-ext@1.0.0': {}
|
||||
@@ -15378,21 +15267,14 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@electron/rebuild@4.0.3':
|
||||
'@electron/rebuild@4.2.0':
|
||||
dependencies:
|
||||
'@malept/cross-spawn-promise': 2.0.0
|
||||
debug: 4.4.3
|
||||
detect-libc: 2.1.2
|
||||
got: 11.8.6
|
||||
graceful-fs: 4.2.11
|
||||
node-abi: 4.31.0
|
||||
node-api-version: 0.2.1
|
||||
node-gyp: 11.5.0
|
||||
ora: 5.3.0
|
||||
node-gyp: 12.2.0
|
||||
read-binary-file-arch: 1.0.6
|
||||
semver: 7.8.1
|
||||
tar: 7.5.15
|
||||
yargs: 17.7.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -16257,6 +16139,8 @@ snapshots:
|
||||
|
||||
'@noble/hashes@1.4.0': {}
|
||||
|
||||
'@noble/hashes@1.8.0': {}
|
||||
|
||||
'@nodelib/fs.scandir@2.1.5':
|
||||
dependencies:
|
||||
'@nodelib/fs.stat': 2.0.5
|
||||
@@ -16269,16 +16153,6 @@ snapshots:
|
||||
'@nodelib/fs.scandir': 2.1.5
|
||||
fastq: 1.20.1
|
||||
|
||||
'@npmcli/agent@3.0.0':
|
||||
dependencies:
|
||||
agent-base: 7.1.4
|
||||
http-proxy-agent: 7.0.2
|
||||
https-proxy-agent: 7.0.6
|
||||
lru-cache: 10.4.3
|
||||
socks-proxy-agent: 8.0.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@npmcli/agent@4.0.0':
|
||||
dependencies:
|
||||
agent-base: 7.1.4
|
||||
@@ -16289,10 +16163,6 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@npmcli/fs@4.0.0':
|
||||
dependencies:
|
||||
semver: 7.8.1
|
||||
|
||||
'@npmcli/fs@5.0.0':
|
||||
dependencies:
|
||||
semver: 7.8.1
|
||||
@@ -17820,11 +17690,11 @@ snapshots:
|
||||
'@sentry-internal/replay-canvas': 10.53.1
|
||||
'@sentry/core': 10.53.1
|
||||
|
||||
'@sentry/bundler-plugin-core@5.3.0(encoding@0.1.13)':
|
||||
'@sentry/bundler-plugin-core@5.3.0':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@sentry/babel-plugin-component-annotate': 5.3.0
|
||||
'@sentry/cli': 2.58.6(encoding@0.1.13)
|
||||
'@sentry/cli': 2.58.6
|
||||
dotenv: 16.6.1
|
||||
find-up: 5.0.0
|
||||
glob: 13.0.6
|
||||
@@ -17857,10 +17727,10 @@ snapshots:
|
||||
'@sentry/cli-win32-x64@2.58.6':
|
||||
optional: true
|
||||
|
||||
'@sentry/cli@2.58.6(encoding@0.1.13)':
|
||||
'@sentry/cli@2.58.6':
|
||||
dependencies:
|
||||
https-proxy-agent: 5.0.1
|
||||
node-fetch: 2.7.0(encoding@0.1.13)
|
||||
node-fetch: 2.7.0
|
||||
progress: 2.0.3
|
||||
proxy-from-env: 1.1.0
|
||||
which: 2.0.2
|
||||
@@ -17947,9 +17817,9 @@ snapshots:
|
||||
'@opentelemetry/semantic-conventions': 1.40.0
|
||||
'@sentry/core': 10.50.0
|
||||
|
||||
'@sentry/webpack-plugin@5.3.0(encoding@0.1.13)(webpack@5.107.1)':
|
||||
'@sentry/webpack-plugin@5.3.0(webpack@5.107.1)':
|
||||
dependencies:
|
||||
'@sentry/bundler-plugin-core': 5.3.0(encoding@0.1.13)
|
||||
'@sentry/bundler-plugin-core': 5.3.0
|
||||
webpack: 5.107.1(lightningcss@1.32.0)(postcss@8.5.15)(webpack-cli@7.0.2)
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
@@ -18737,12 +18607,6 @@ snapshots:
|
||||
|
||||
'@types/picomatch@4.0.2': {}
|
||||
|
||||
'@types/plist@3.0.5':
|
||||
dependencies:
|
||||
'@types/node': 18.19.130
|
||||
xmlbuilder: 15.1.1
|
||||
optional: true
|
||||
|
||||
'@types/png-chunks-extract@1.0.2': {}
|
||||
|
||||
'@types/postcss-import@14.0.3':
|
||||
@@ -18864,9 +18728,6 @@ snapshots:
|
||||
|
||||
'@types/unist@3.0.3': {}
|
||||
|
||||
'@types/verror@1.10.11':
|
||||
optional: true
|
||||
|
||||
'@types/web-bluetooth@0.0.21': {}
|
||||
|
||||
'@types/ws@8.18.1':
|
||||
@@ -19413,8 +19274,6 @@ snapshots:
|
||||
|
||||
'@zxcvbn-ts/language-en@3.0.2': {}
|
||||
|
||||
abbrev@3.0.1: {}
|
||||
|
||||
abbrev@4.0.0: {}
|
||||
|
||||
abort-controller@3.0.0:
|
||||
@@ -19553,32 +19412,33 @@ snapshots:
|
||||
normalize-path: 3.0.0
|
||||
picomatch: 2.3.2
|
||||
|
||||
app-builder-bin@5.0.0-alpha.12: {}
|
||||
|
||||
app-builder-lib@26.11.1(dmg-builder@26.11.1)(electron-builder-squirrel-windows@26.11.1):
|
||||
app-builder-lib@26.16.1(dmg-builder@26.16.1)(electron-builder-squirrel-windows@26.16.1):
|
||||
dependencies:
|
||||
'@develar/schema-utils': 2.6.5
|
||||
'@electron/asar': 3.4.1
|
||||
'@electron/fuses': 1.8.0
|
||||
'@electron/get': 3.1.0
|
||||
'@electron/notarize': 2.5.0
|
||||
'@electron/osx-sign': 1.3.3
|
||||
'@electron/rebuild': 4.0.3
|
||||
'@electron/rebuild': 4.2.0
|
||||
'@electron/universal': 2.0.3
|
||||
'@malept/flatpak-bundler': 0.4.0
|
||||
'@noble/hashes': 1.8.0
|
||||
'@peculiar/webcrypto': 1.7.1
|
||||
'@types/fs-extra': 9.0.13
|
||||
ajv: 8.20.0
|
||||
asn1js: 3.0.10
|
||||
async-exit-hook: 2.0.1
|
||||
builder-util: 26.11.1
|
||||
builder-util-runtime: 9.6.1
|
||||
builder-util: 26.16.0
|
||||
builder-util-runtime: 9.7.0
|
||||
chromium-pickle-js: 0.2.0
|
||||
ci-info: 4.3.1
|
||||
debug: 4.4.3
|
||||
dmg-builder: 26.11.1(electron-builder-squirrel-windows@26.11.1)
|
||||
dmg-builder: 26.16.1(electron-builder-squirrel-windows@26.16.1)
|
||||
dotenv: 16.6.1
|
||||
dotenv-expand: 11.0.7
|
||||
ejs: 3.1.10
|
||||
electron-builder-squirrel-windows: 26.11.1(dmg-builder@26.11.1)
|
||||
electron-publish: 26.11.1
|
||||
electron-builder-squirrel-windows: 26.16.1(dmg-builder@26.16.1)
|
||||
electron-publish: 26.16.0
|
||||
fs-extra: 10.1.0
|
||||
hosted-git-info: 4.1.0
|
||||
isbinaryfile: 5.0.7
|
||||
@@ -19587,6 +19447,7 @@ snapshots:
|
||||
json5: 2.2.3
|
||||
lazy-val: 1.0.5
|
||||
minimatch: 10.2.5
|
||||
pkijs: 3.4.0
|
||||
plist: 3.1.0(patch_hash=7a3c35087f0ab2a8efbac9e2899990f07d61e2b3e41d8d962ef0bdb0786e1af7)
|
||||
proper-lockfile: 4.1.2
|
||||
resedit: 1.7.2
|
||||
@@ -19726,9 +19587,6 @@ snapshots:
|
||||
pvutils: 1.1.5
|
||||
tslib: 2.8.1
|
||||
|
||||
assert-plus@1.0.0:
|
||||
optional: true
|
||||
|
||||
assert@2.1.0:
|
||||
dependencies:
|
||||
call-bind: 1.0.8
|
||||
@@ -19793,6 +19651,8 @@ snapshots:
|
||||
|
||||
await-lock@3.0.0(patch_hash=b767a571946a4f8710ac54b1a7bec8a7c1570f9b85d75922392fae20d0578964): {}
|
||||
|
||||
aws4@1.13.2: {}
|
||||
|
||||
axe-core@4.11.4: {}
|
||||
|
||||
axios@1.15.2:
|
||||
@@ -20174,19 +20034,17 @@ snapshots:
|
||||
buildcheck@0.0.7:
|
||||
optional: true
|
||||
|
||||
builder-util-runtime@9.6.1:
|
||||
builder-util-runtime@9.7.0:
|
||||
dependencies:
|
||||
debug: 4.4.3
|
||||
sax: 1.6.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
builder-util@26.11.1:
|
||||
builder-util@26.16.0:
|
||||
dependencies:
|
||||
7zip-bin: 5.2.0
|
||||
'@types/debug': 4.1.13
|
||||
app-builder-bin: 5.0.0-alpha.12
|
||||
builder-util-runtime: 9.6.1
|
||||
builder-util-runtime: 9.7.0
|
||||
chalk: 4.1.2
|
||||
cross-spawn: 7.0.6
|
||||
debug: 4.4.3
|
||||
@@ -20216,21 +20074,6 @@ snapshots:
|
||||
|
||||
bytestreamjs@2.0.1: {}
|
||||
|
||||
cacache@19.0.1:
|
||||
dependencies:
|
||||
'@npmcli/fs': 4.0.0
|
||||
fs-minipass: 3.0.3
|
||||
glob: 10.5.0
|
||||
lru-cache: 10.4.3
|
||||
minipass: 7.1.3
|
||||
minipass-collect: 2.0.1
|
||||
minipass-flush: 1.0.5
|
||||
minipass-pipeline: 1.2.4
|
||||
p-map: 7.0.4
|
||||
ssri: 12.0.0
|
||||
tar: 7.5.15
|
||||
unique-filename: 4.0.0
|
||||
|
||||
cacache@20.0.4:
|
||||
dependencies:
|
||||
'@npmcli/fs': 5.0.0
|
||||
@@ -20386,12 +20229,6 @@ snapshots:
|
||||
|
||||
cli-spinners@2.6.1: {}
|
||||
|
||||
cli-truncate@2.1.0:
|
||||
dependencies:
|
||||
slice-ansi: 3.0.0
|
||||
string-width: 4.2.3
|
||||
optional: true
|
||||
|
||||
cli-truncate@5.2.0:
|
||||
dependencies:
|
||||
slice-ansi: 8.0.0
|
||||
@@ -20564,9 +20401,6 @@ snapshots:
|
||||
|
||||
core-js@3.48.0: {}
|
||||
|
||||
core-util-is@1.0.2:
|
||||
optional: true
|
||||
|
||||
core-util-is@1.0.3: {}
|
||||
|
||||
cose-base@1.0.3:
|
||||
@@ -20626,11 +20460,6 @@ snapshots:
|
||||
crc-32: 1.2.2
|
||||
readable-stream: 4.7.0
|
||||
|
||||
crc@3.8.0:
|
||||
dependencies:
|
||||
buffer: 5.7.1
|
||||
optional: true
|
||||
|
||||
create-ecdh@4.0.4:
|
||||
dependencies:
|
||||
bn.js: 4.12.3
|
||||
@@ -21165,31 +20994,16 @@ snapshots:
|
||||
minimatch: 3.1.5
|
||||
p-limit: 3.1.0
|
||||
|
||||
dmg-builder@26.11.1(electron-builder-squirrel-windows@26.11.1):
|
||||
dmg-builder@26.16.1(electron-builder-squirrel-windows@26.16.1):
|
||||
dependencies:
|
||||
app-builder-lib: 26.11.1(dmg-builder@26.11.1)(electron-builder-squirrel-windows@26.11.1)
|
||||
builder-util: 26.11.1
|
||||
app-builder-lib: 26.16.1(dmg-builder@26.16.1)(electron-builder-squirrel-windows@26.16.1)
|
||||
builder-util: 26.16.0
|
||||
fs-extra: 10.1.0
|
||||
iconv-lite: 0.6.3
|
||||
js-yaml: 4.1.1
|
||||
optionalDependencies:
|
||||
dmg-license: 1.0.11
|
||||
transitivePeerDependencies:
|
||||
- electron-builder-squirrel-windows
|
||||
- supports-color
|
||||
|
||||
dmg-license@1.0.11:
|
||||
dependencies:
|
||||
'@types/plist': 3.0.5
|
||||
'@types/verror': 1.10.11
|
||||
ajv: 6.15.0
|
||||
crc: 3.8.0
|
||||
iconv-corefoundation: 1.1.7
|
||||
plist: 3.1.0(patch_hash=7a3c35087f0ab2a8efbac9e2899990f07d61e2b3e41d8d962ef0bdb0786e1af7)
|
||||
smart-buffer: 4.2.0
|
||||
verror: 1.10.1
|
||||
optional: true
|
||||
|
||||
dns-packet@5.6.1:
|
||||
dependencies:
|
||||
'@leichtgewicht/ip-codec': 2.0.5
|
||||
@@ -21342,23 +21156,23 @@ snapshots:
|
||||
|
||||
ejs@5.0.1: {}
|
||||
|
||||
electron-builder-squirrel-windows@26.11.1(dmg-builder@26.11.1):
|
||||
electron-builder-squirrel-windows@26.16.1(dmg-builder@26.16.1):
|
||||
dependencies:
|
||||
app-builder-lib: 26.11.1(dmg-builder@26.11.1)(electron-builder-squirrel-windows@26.11.1)
|
||||
builder-util: 26.11.1
|
||||
app-builder-lib: 26.16.1(dmg-builder@26.16.1)(electron-builder-squirrel-windows@26.16.1)
|
||||
builder-util: 26.16.0
|
||||
electron-winstaller: 5.4.0
|
||||
transitivePeerDependencies:
|
||||
- dmg-builder
|
||||
- supports-color
|
||||
|
||||
electron-builder@26.11.1(electron-builder-squirrel-windows@26.11.1):
|
||||
electron-builder@26.16.1(electron-builder-squirrel-windows@26.16.1):
|
||||
dependencies:
|
||||
app-builder-lib: 26.11.1(dmg-builder@26.11.1)(electron-builder-squirrel-windows@26.11.1)
|
||||
builder-util: 26.11.1
|
||||
builder-util-runtime: 9.6.1
|
||||
app-builder-lib: 26.16.1(dmg-builder@26.16.1)(electron-builder-squirrel-windows@26.16.1)
|
||||
builder-util: 26.16.0
|
||||
builder-util-runtime: 9.7.0
|
||||
chalk: 4.1.2
|
||||
ci-info: 4.4.0
|
||||
dmg-builder: 26.11.1(electron-builder-squirrel-windows@26.11.1)
|
||||
dmg-builder: 26.16.1(electron-builder-squirrel-windows@26.16.1)
|
||||
fs-extra: 10.1.0
|
||||
lazy-val: 1.0.5
|
||||
simple-update-notifier: 2.0.0
|
||||
@@ -21371,11 +21185,12 @@ snapshots:
|
||||
dependencies:
|
||||
unzip-crx-3: 0.2.0
|
||||
|
||||
electron-publish@26.11.1:
|
||||
electron-publish@26.16.0:
|
||||
dependencies:
|
||||
'@types/fs-extra': 9.0.13
|
||||
builder-util: 26.11.1
|
||||
builder-util-runtime: 9.6.1
|
||||
aws4: 1.13.2
|
||||
builder-util: 26.16.0
|
||||
builder-util-runtime: 9.7.0
|
||||
chalk: 4.1.2
|
||||
form-data: 4.0.5
|
||||
fs-extra: 10.1.0
|
||||
@@ -21450,11 +21265,6 @@ snapshots:
|
||||
|
||||
encodeurl@2.0.0: {}
|
||||
|
||||
encoding@0.1.13:
|
||||
dependencies:
|
||||
iconv-lite: 0.6.3
|
||||
optional: true
|
||||
|
||||
end-of-stream@1.4.5:
|
||||
dependencies:
|
||||
once: 1.4.0
|
||||
@@ -22098,9 +21908,6 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
extsprintf@1.4.1:
|
||||
optional: true
|
||||
|
||||
fake-indexeddb@6.2.5: {}
|
||||
|
||||
fast-content-type-parse@3.0.0: {}
|
||||
@@ -22775,12 +22582,6 @@ snapshots:
|
||||
|
||||
hyperdyperid@1.2.0: {}
|
||||
|
||||
iconv-corefoundation@1.1.7:
|
||||
dependencies:
|
||||
cli-truncate: 2.1.0
|
||||
node-addon-api: 1.7.2
|
||||
optional: true
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
@@ -23872,22 +23673,6 @@ snapshots:
|
||||
dependencies:
|
||||
semver: 7.8.1
|
||||
|
||||
make-fetch-happen@14.0.3:
|
||||
dependencies:
|
||||
'@npmcli/agent': 3.0.0
|
||||
cacache: 19.0.1
|
||||
http-cache-semantics: 4.2.0
|
||||
minipass: 7.1.3
|
||||
minipass-fetch: 4.0.1
|
||||
minipass-flush: 1.0.5
|
||||
minipass-pipeline: 1.2.4
|
||||
negotiator: 1.0.0
|
||||
proc-log: 5.0.0
|
||||
promise-retry: 2.0.1
|
||||
ssri: 12.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
make-fetch-happen@15.0.5:
|
||||
dependencies:
|
||||
'@gar/promise-retry': 1.0.3
|
||||
@@ -24176,14 +23961,6 @@ snapshots:
|
||||
dependencies:
|
||||
minipass: 7.1.3
|
||||
|
||||
minipass-fetch@4.0.1:
|
||||
dependencies:
|
||||
minipass: 7.1.3
|
||||
minipass-sized: 1.0.3
|
||||
minizlib: 3.1.0
|
||||
optionalDependencies:
|
||||
encoding: 0.1.13
|
||||
|
||||
minipass-fetch@5.0.2:
|
||||
dependencies:
|
||||
minipass: 7.1.3
|
||||
@@ -24200,10 +23977,6 @@ snapshots:
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
|
||||
minipass-sized@1.0.3:
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
|
||||
minipass-sized@2.0.0:
|
||||
dependencies:
|
||||
minipass: 7.1.3
|
||||
@@ -24298,33 +24071,13 @@ snapshots:
|
||||
dependencies:
|
||||
semver: 7.8.1
|
||||
|
||||
node-addon-api@1.7.2:
|
||||
optional: true
|
||||
|
||||
node-api-version@0.2.1:
|
||||
dependencies:
|
||||
semver: 7.8.1
|
||||
|
||||
node-fetch@2.7.0(encoding@0.1.13):
|
||||
node-fetch@2.7.0:
|
||||
dependencies:
|
||||
whatwg-url: 5.0.0
|
||||
optionalDependencies:
|
||||
encoding: 0.1.13
|
||||
|
||||
node-gyp@11.5.0:
|
||||
dependencies:
|
||||
env-paths: 2.2.1
|
||||
exponential-backoff: 3.1.3
|
||||
graceful-fs: 4.2.11
|
||||
make-fetch-happen: 14.0.3
|
||||
nopt: 8.1.0
|
||||
proc-log: 5.0.0
|
||||
semver: 7.8.1
|
||||
tar: 7.5.15
|
||||
tinyglobby: 0.2.16
|
||||
which: 5.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
node-gyp@12.2.0:
|
||||
dependencies:
|
||||
@@ -24378,10 +24131,6 @@ snapshots:
|
||||
non-layered-tidy-tree-layout@2.0.2:
|
||||
optional: true
|
||||
|
||||
nopt@8.1.0:
|
||||
dependencies:
|
||||
abbrev: 3.0.1
|
||||
|
||||
nopt@9.0.0:
|
||||
dependencies:
|
||||
abbrev: 4.0.0
|
||||
@@ -25601,8 +25350,6 @@ snapshots:
|
||||
react-is-18: react-is@18.3.1
|
||||
react-is-19: react-is@19.2.6
|
||||
|
||||
proc-log@5.0.0: {}
|
||||
|
||||
proc-log@6.1.0: {}
|
||||
|
||||
process-nextick-args@2.0.1: {}
|
||||
@@ -26512,13 +26259,6 @@ snapshots:
|
||||
|
||||
slash@5.1.0: {}
|
||||
|
||||
slice-ansi@3.0.0:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
astral-regex: 2.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
optional: true
|
||||
|
||||
slice-ansi@4.0.0:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
@@ -26653,10 +26393,6 @@ snapshots:
|
||||
|
||||
ssim.js@3.5.0: {}
|
||||
|
||||
ssri@12.0.0:
|
||||
dependencies:
|
||||
minipass: 7.1.3
|
||||
|
||||
ssri@13.0.1:
|
||||
dependencies:
|
||||
minipass: 7.1.3
|
||||
@@ -27466,14 +27202,6 @@ snapshots:
|
||||
|
||||
unicorn-magic@0.4.0: {}
|
||||
|
||||
unique-filename@4.0.0:
|
||||
dependencies:
|
||||
unique-slug: 5.0.0
|
||||
|
||||
unique-slug@5.0.0:
|
||||
dependencies:
|
||||
imurmurhash: 0.1.4
|
||||
|
||||
unist-util-is@6.0.1:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
@@ -27662,13 +27390,6 @@ snapshots:
|
||||
- '@types/react'
|
||||
- '@types/react-dom'
|
||||
|
||||
verror@1.10.1:
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
core-util-is: 1.0.2
|
||||
extsprintf: 1.4.1
|
||||
optional: true
|
||||
|
||||
vfile-message@4.0.3:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
Reference in New Issue
Block a user