Compare commits

..
42 Commits
Author SHA1 Message Date
Thore CimbalandClaude Fable 5 c0774b5f58 desktop: Icons zentriert + About-Attribution im Web-Client (ThreadNet-Web#10)
Zwei Haelften desselben Issues, bewusst in einem Commit, weil sie zusammen
gebaut und ausgeliefert werden.

Desktop-Icons: build/icon.png war byte-identisch mit dem alten, unzentrierten
Web-Icon - das Motiv klebte an der Oberkante (Rand oben 3 %, unten 40 %). macOS
und Windows zeigten also dasselbe schiefe Bild wie der Browser-Tab. Alle vier
Artefakte aus der jetzt zentrierten Quelle neu erzeugt: icon.png, icon.ico
(sieben Groessen von 16 bis 256), das Layer-Asset des macOS-Icon-Composers und
icon.icns ueber iconutil (10 Einzelbilder, 16-512 plus @2x). Alle vier gehen auf
dieselbe Datei zurueck, sie koennen also nicht mehr auseinanderlaufen.

About-Attribution: 'ThreadNet - powered by Element' steht jetzt in Einstellungen
-> Hilfe & Info direkt unter der Client-Version, mit Link auf element.io. Das
war der eigentliche Zweck des Issues - bisher stand die Zeile nur in der
Build-Beschreibung des Desktop-Pakets und war im Client nirgends sichtbar.

Zwei bewusste Entscheidungen dabei, beide im Code kommentiert:

- NICHT in getVersionTextToCopy aufgenommen. Der Text dort landet in
  Fehlerberichten; die Herkunft des Forks ist da nur Rauschen.
- Ohne _t(). Ein Markenhinweis wird nicht uebersetzt, und jeder zusaetzliche
  i18n-Schluessel ist Reibung beim naechsten Upstream-Merge - genau das, was das
  Issue mit 'chirurgisch halten' meint.

Das Stylesheet nutzt nur Variablen, die im Projekt bereits verbreitet sind
(--cpd-space-2x in 43, --cpd-color-text-secondary in 28,
--cpd-font-body-sm-regular in 22 Dateien) - kein Blindflug mit erfundenen Tokens.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-06 12:00:00 +00:00
Thore CimbalandClaude Fable 5 4fdad89fa6 web: Icons zentriert, theme_color auf die Markenfarbe (ThreadNet-Web#10)
Die Web-Icons trugen bereits die ThreadNet-Marke - anders als im Issue vermerkt.
Sie waren aber falsch zugeschnitten: Rand oben 3 %, unten 40 %, das Motiv klebte
an der Oberkante. In runden und quadratischen Icon-Slots sitzt es dadurch
sichtbar zu hoch.

Alle sieben Groessen aus dem 1024er neu erzeugt: auf die Motiv-Bounding-Box
beschnitten und bei gleicher Groesse (81 % der Kante) mittig gesetzt - jetzt
21 % Rand oben wie unten. resize() statt thumbnail(), sonst waere nur verkleinert
worden.

theme_color stand auf #76CFA6, Elements Mintgruen. Die Marke ist #ed4f4c
(dominante Farbe des Motivs gemessen, nicht geschaetzt) - das Gruen war ein
Upstream-Rest und faerbte die Browser-/PWA-Leiste falsch ein.

config.sample.json: brand von Element auf aXion1337.Chat, damit die Vorlage
zeigt, was Prod tatsaechlich setzt.

Nicht angefasst: der Favicon-Snapshot-Test - er prueft Canvas-Operationen
(clearRect, Dimensionen), nicht den Bildinhalt, und bleibt gruen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-06 12:00:00 +00:00
Thore CimbalandClaude Fable 5 80fcf6c227 desktop: Themes mit dem Web-Stand gleichgezogen
Die zehn theme-factory-Themes sind jetzt in beiden Configs identisch (gitops
c47b0a3 + Nachfolger). Ohne das haetten Desktop-Clients weiter meine alte
Interpretation der Paletten gezeigt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-02 12:00:00 +00:00
Thore CimbalandClaude Fable 5 f4995e5882 rebrand: auch 'name' auf threadnet-desktop - Linux-Pakete hiessen sonst weiter Element
electron-builder leitet unterschiedliche Dinge aus zwei Feldern ab: productName
bestimmt den App-Namen (macOS .app, Windows Setup.exe), 'name' dagegen den
Linux-Paketnamen, das Binary und den /opt-Pfad. Nach dem Rebrand hiess die App
ueberall ThreadNet - ausser bei .deb und .tar.gz.

Nebenwirkung bewusst in Kauf genommen: apt sieht ein neues Paket, ein
Upgrade-Pfad von element-desktop existiert nicht. Bei einem Rebrand ist das
erwartbar; die appId bleibt unveraendert, damit lokale Daten erhalten bleiben.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-02 12:00:00 +00:00
Thore CimbalandClaude Fable 5 e21a895390 ci: VARIANT_PATH in beiden Desktop-Jobs - Pakete hiessen weiter element-desktop
Der Rebrand-Commit legte apps/desktop/axion1337/build.json an, aber electron-builder
nutzt eine Variante nur, wenn VARIANT_PATH gesetzt ist. Lokal hatte ich sie per
Umgebungsvariable gesetzt, in der CI fehlte sie - deshalb trugen die Linux- und
Windows-Pakete aus Pipeline 147 weiter den Namen 'element-desktop' bzw.
'Element Setup', obwohl die Icons bereits neu waren.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-02 12:00:00 +00:00
Thore CimbalandClaude Fable 5 c51b68194a rebrand: alle Icons ersetzt - Windows-.ico und Web-Icons fehlten noch
Gestern wurden nur icon.png und icon.icns getauscht; Windows (.ico) und der
Web-Client (res/vector-icons/, manifest.json) trugen weiter das Element-Icon.

Dazu ein echter Fehler behoben: die Icons wurden mit PIL.thumbnail() erzeugt -
das skaliert NUR nach unten. Das 277px-Motiv wurde in 1024er-Icons daher nie
vergroessert und fuellte ueberall bloss 54% x 38% der Flaeche. Jetzt mit resize()
aus dem 1024er-Original: 81% Breite statt 54%.

Ersetzt: web/res/vector-icons/{24,120,144,152,180,512,1024}.png, manifest.json
(name/short_name -> ThreadNet), desktop/build/icon.{png,ico,icns}.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-02 12:00:00 +00:00
Thore CimbalandClaude Fable 5 6b0261d66c rebrand: Desktop-Client heisst ThreadNet und traegt die eigene Marke
Erster Schritt aus ThreadNet-Web#10 - der Client hiess bisher 'Element' und
zeigte dessen Icon.

- apps/desktop/axion1337/build.json: eigene Build-Variante (VARIANT_PATH), damit
  element.io/release/build.json unangetastet bleibt und Upstream-Merges nicht
  reiben. productName 'ThreadNet', Beschreibung 'ThreadNet - powered by Element'
  als faire Attribution (Element Web ist AGPL, dies ist ein Fork davon).
- appId bleibt bewusst 'im.riot.app': bestehende Installationen behalten ihre
  lokalen Daten. Ein appId-Wechsel waere ein Datenschnitt und gehoert in die
  Rebranding-Runde, nicht in einen Icon-Commit.
- build/icon.png + icon.icns: ThreadNet-Bildmarke, transparenter Rand entfernt
  (das Motiv fuellte im Original nur 54% x 38% - direkt skaliert verschwindet es).

Verifiziert im Build: CFBundleName/CFBundleDisplayName = ThreadNet, eigenes
Icon, alle 17 Themes im webapp.asar.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-02 12:00:00 +00:00
Thore CimbalandClaude Fable 5 6e021ee853 desktop: dieselben 17 Themes wie im Web-Client
Die Desktop-Apps laden ihre eigene config.json und haetten die elf neuen Themes
sonst nicht (aXion1337 Light + zehn Paletten). Aus der bereits deployten
Web-Konfiguration uebernommen, damit beide Clients identisch sind.

Chirurgisch eingefuegt (Lehre vom 2026-08-01, als ein Re-Dump dieser Datei 441
Zeilen umformatierte): 0 entfernte / 427 neue Zeilen, JSON validiert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-02 12:00:00 +00:00
Thore CimbalandClaude Fable 5 5a8c42b5e9 desktop: Rageshake-Entfernung auf Minimal-Diff korrigiert (Formatierung des Vorgaengers wiederhergestellt)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-01 12:00:00 +00:00
Thore CimbalandClaude Fable 5 5505b9cfc1 desktop: Rageshake-Endpoint entfernt - keine Bug-Reports+Logs an element.io
Entscheidung sorb 2026-08-01: Bug-Melden-Funktion entfaellt vorerst;
eigener Rageshake oder Alternative (z.B. Zammad) als [LOW]-Issue notiert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-01 12:00:00 +00:00
Thore CimbalandClaude Fable 5 a2bfaaec8f ci: woechentlicher Trivy-CVE-Scan des Prod-Web-Images (gitops#31)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-01 12:00:00 +00:00
Thore CimbalandClaude Fable 5 b656eefdc7 ci: Cache-Layout fuer app-builder-Artefakte korrigiert (gedoppelter Schluessel)
Aus artifactDownloader.go + binDownload.js verifiziert: Schluessel ist
<release>-<release>, Unterverzeichnis = Namensteil vor dem ersten
Bindestrich (nsis-resources daher unter nsis\). Job 431 traf winCodeSign
im Cache, scheiterte aber am nsis-Miss mit einfachem Namen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-07-31 12:00:00 +00:00
Thore CimbalandClaude Fable 5 a55adfdd65 ci: alle app-builder-GitHub-Downloads resumefaehig vorladen
winCodeSign starb an denselben CDN-Resets wie zuvor die Electron-Binary
(Job 424); Prefetch-Skript konsolidiert Electron-Zip + winCodeSign +
NSIS-Pakete mit curl -C - in die persistenten Caches (ELECTRON_CACHE,
ELECTRON_BUILDER_CACHE).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-07-31 12:00:00 +00:00
Thore CimbalandClaude Fable 5 cf66ff018d ci: Electron-Binary resumefaehig vorladen (ELECTRON_CACHE)
GitHub-CDN brach den ~120-MB-Download zweimal mitten im Transfer ab
(Jobs 415/416, wsarecv: connection forcibly closed); app-builder kann
nicht fortsetzen. curl -C - in Schleife + persistenter Cache im Gast.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-07-31 12:00:00 +00:00
Thore CimbalandClaude Fable 5 97e18bbf2f ci: Windows-Provisionierung um Rust/Perl/Python/NASM-PATH ergaenzt
hak/matrix-seshat/check.ts verlangt auf Windows rustc, perl, patch, nasm,
nmake und python - Job 399 scheiterte an fehlendem rustc. Rust landet
maschinenweit unter C:\Rust (SYSTEM-Dienst sieht kein Benutzerprofil),
Strawberry Perl deckt perl+patch ab, NASM-PATH wie im Upstream-Workflow
explizit nachgezogen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-07-31 12:00:00 +00:00
Thore Cimbal c401f54e4d ci: windows_provision Dienst-Neustart via Scheduled Task (Race mit Job-Cleanup, siehe #5) 2026-07-31 12:00:00 +00:00
Thore Cimbal 1eb4968968 ci: desktop_linux nutzt das Build-Image aus der Lab-Registry (OVERMIND-01 abgeschlossen) 2026-07-31 12:00:00 +00:00
Thore CimbalandClaude Fable 5 a8767583da ci: verbliebene GitHub-Workflow-Dateien entfernt (CFGMON-11)
Vollstaendig durch .gitlab-ci.yml ersetzt (Linux verifiziert gruen, Windows
in Arbeit); Gitea Actions ist fuer dieses Repo deaktiviert, auf GitHub lag
das Repo nie. Die Dateien bleiben als Uebersetzungsreferenz in der
Git-Historie erhalten.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 12:00:00 +00:00
Thore Cimbal 0d0c1659c6 ci: desktop_image in die Lab-Registry (OVERMIND-01, CI_JOB_TOKEN statt rohana-Secret) 2026-07-31 12:00:00 +00:00
Thore Cimbal 624274f5f0 ci: windows_provision - core.longpaths + LongPathsEnabled (MAX_PATH-Fix fuer Checkout) 2026-07-31 12:00:00 +00:00
Thore CimbalandClaude Fable 5 9e2f49b3dd ci: schlankes Trigger-Schema - Pushes pruefen, Tags releasen
web laeuft nur noch bei build-relevanten Pfadaenderungen (Doku-Commits
kosten nichts) und immer bei v*-Tags. docker_web und desktop_linux bauen
nur noch bei Release-Tags (Image-Tag = Git-Tag statt sha), desktop_linux
bleibt auf main manuell triggerbar. Windows-/VM-Jobs sind auf main und
Tags manuell verfuegbar. Hintergrund: Deploy ist ohnehin ein bewusster
Tag-Bump im gitops-Repo - Artefakte pro Doku-Commit waren reine
Runner-Verschwendung.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 12:00:00 +00:00
Thore Cimbal a414bb8585 ci: windows_provision ohne Checkout (GIT_STRATEGY none) - Henne-Ei mit fehlendem git 2026-07-31 12:00:00 +00:00
Thore Cimbal 8465457a48 ci: windows_provision-Job - idempotente Gast-Werkzeuge via Runner (Runbook-Fix: choco einzeln statt Mehrfachpaket mit --version) 2026-07-31 12:00:00 +00:00
Thore Cimbal 252b16ca71 docs: Repo-Topologie - git.lab kanonisch, rohana als Push-Mirror 2026-07-31 12:00:00 +00:00
Thore CimbalandClaude Fable 5 0d0255cb7f ci: Windows-Strecke - VM-Start/Stop-Jobs + desktop_windows (Issue #5)
start/stop_windows_vm steuern die On-Demand-Build-VM vom Linux-Runner aus
(Docker-Socket). desktop_windows (tags: windows, manuell, unsigniert/nsis)
uebersetzt den x64-Pfad des Upstream-Workflows: frozen-lockfile, webapp +
axion-config vor dem asar, VS-DevShell + build:native mit MSVC-Target.
Wartet in der Queue bis der Windows-Runner (lab-windows-1) online ist.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 12:00:00 +00:00
Thore Cimbal bc0769809d ci: desktop_linux automatisch auf main nach erstem gruenen Lauf 2026-07-31 12:00:00 +00:00
Thore CimbalandClaude Fable 5 e21e101004 ci: GitLab pipeline (web build, rohana image push, desktop linux)
First CI for the lab GitLab (git.lab): web job builds the webapp with the
lessons from the Gitea attempts baked in (frozen-lockfile instead of
layered.sh, 6GB node heap), docker_web pushes the canonical
apps/web/Dockerfile image to the rohana registry that Flux pulls from,
and two manual jobs cover the desktop path - a dockerbuild build-image
and the Electron Linux build replicating the manually verified flow.
Also tracks the production client config (apps/desktop/axion1337/) that
previously only existed inside the one-off manual desktop build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 8d46fb33d2 ci: use lockfile install instead of layered.sh, fix always-green gate
layered.sh clones a branch-matching upstream matrix-js-sdk - on this fork
that would override the deliberately pinned js-sdk from pnpm-lock.yaml
(issue #12) with upstream develop, and it also needs jq which the node:20
job container lacks (the actual CI failure). Plain frozen-lockfile install
matches the production docker build.

Also replace the contains(needs.*.result, ...) gate check with explicit
per-job checks: the object-filter syntax evaluated wrongly on Gitea/act,
letting build-complete report success while build_ew had failed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 71ac7c4346 ci: map runs-on to actual runner labels, trim jobs the runner can't serve
Root cause found for jobs never starting: runs were created all along
(visible in the Actions UI), but every job requested ubuntu-24.04 while
builder-1 only offers ubuntu-latest, linux-build and win-wine - a label
mismatch means jobs queue forever, invisible via the /actions/tasks API
which only lists picked-up jobs.

Mapped build/prepare/gate jobs to ubuntu-latest and the Linux desktop
build to linux-build (electronuserland/builder image, amd64/static only -
the only variant buildable on the single x86 runner). Removed jobs the
runner cannot serve instead of letting them starve the queue: web+desktop
playwright tests (need Docker-in-job and display setup, tracked as
follow-up in issue #2) and the native-Windows desktop build (workflow
assumes signtool/MSVC/PowerShell; the win-wine label awaits a dedicated
wine-based workflow).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 12:00:00 +00:00
Thore Cimbal 8faade6c7b ci: test push after git-hook resync 2026-07-30 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 f2abae85dd ci: remove unused workflow_call trigger (Gitea Actions bug go-gitea/gitea#33238)
push + workflow_call in the same on: block doesn't reliably fire push
events on Gitea Actions 1.27 (reproducible upstream, closed as "not
planned" - https://github.com/go-gitea/gitea/issues/33238). Nothing in
this repo invokes build-and-test.yaml via workflow_call anymore after the
workflow cleanup, so removing the trigger is a safe, targeted fix rather
than a workaround.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 12:00:00 +00:00
Thore Cimbal 0f1d31021c ci: add trigger-test note to force a real push event 2026-07-30 12:00:00 +00:00
Thore Cimbal bd8298db39 ci: trigger first Actions run now that Actions is enabled for this repo 2026-07-30 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 77ffeb4514 ci: reduce workflows to fork-relevant CI, fix upstream checkouts (Issue #2)
Removed ~37 workflow files that are unmodified upstream tooling this fork
doesn't use (Netlify, SonarCloud, Localazy, release-drafter/backport,
GitHub issue-triage bots, npm-publish, Cloudflare Pages deploy, Docker
push to ghcr.io/element-hq). Enabling Actions for this repo would have
activated all of them simultaneously against a single-capacity shared
runner - most would just fail loudly and starve the one job slot shared
with other repos.

Kept build-and-test.yaml (the actual comprehensive build+test+desktop
workflow) and its build_desktop_*.yaml sub-workflows. Fixed: push trigger
now targets `main` (was `staging`/`master`, neither of which exist here -
push events never fired at all before), 4 checkout steps now check out
this fork instead of element-hq/element-web, and removed the macOS
desktop build job since the registered runner (builder-1) has no macOS
label and would queue forever instead of failing cleanly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 12:00:00 +00:00
Thore Cimbal 45fb329577 docs: add axion1337-fork.md documenting fork-specific changes vs upstream 2026-07-29 12:00:00 +00:00
Thore Cimbal 42285021cb feat: client-side ClamAV scanning for encrypted rooms (Issue #19)
Synapse's own check_media_file_for_spam module can never see E2EE
attachment content - only the client ever holds the decryption key.
Adds two hooks that call a self-hosted scan service
(https://axion1337.chat/_scan, deployed separately in the gitops repo):

- DecryptFile.ts: scans every decrypted attachment (image/audio/video/
  file all funnel through this one function via MediaEventHelper)
  before returning it as a Blob.
- ContentMessages.ts: scans plaintext before encryption/upload in
  uploadFile(), the shared function behind all attachment uploads
  (main file, thumbnails, voice messages), regardless of room
  encryption state.

New ContentScanRejectedError surfaces through the existing error-
rendering paths (MediaProcessingError, upload failure dialog) using
the same pattern as DecryptError/DownloadError/UploadFailedError.

Live-tested: EICAR blocked pre-upload in encrypted rooms and DMs;
receive-side hook also blocks EICAR sent by an unpatched client
(app.element.io), confirming it isn't just self-protection for our
own uploads. Fails open on scanner errors so an outage can't block
all uploads/downloads.
2026-07-29 12:00:00 +00:00
Thore Cimbal 44305556c3 fix: restore executable bit on remaining desktop/CI scripts
The earlier script-permission fix (5e3254d) only covered scripts
invoked by apps/web's own Dockerfile/CI at the time. Found 9 more
non-executable scripts (644 instead of 755) while building the
Electron desktop app via apps/desktop/dockerbuild - same root cause,
different invocation paths.
2026-07-29 12:00:00 +00:00
Thore Cimbal 306cca041c fix: pin matrix-js-sdk to a working commit, use our own Element Call fork
The floating github:matrix-org/matrix-js-sdk#develop reference was
resolved to a stale commit missing src/oidc/authorize.ts (breaking the
webpack build). Investigated moving to the current develop HEAD instead
(191908da) - turned out to be worse, not better: that commit renamed the
entire src/oidc/ module to src/oauth/ with a materially different API
(generateOidcAuthorizationUrl/completeAuthorizationCodeGrant/OidcError
don't exist under those names anymore). Rather than porting our OIDC
login code to the new API sight-unseen, pinned to d19cb751 - the last
develop commit before that rename, verified to have both the file at
the expected path and the exact exports apps/web imports.

Also switched the Element Call embedded widget dependency from
upstream's @element-hq/element-call-embedded to our own published fork
(@sorb/threadnet-call-embedded@0.19.2-threadnet.5) - a full rebuild was
otherwise silently bundling the unmodified upstream widget, discarding
every Element Call customization (Video-tab quality settings, German
translations, codec list fix).
2026-07-28 12:00:00 +00:00
Thore Cimbal 1822fe80f0 fix: restore executable bit on scripts invoked directly by Dockerfile/CI
apps/web/Dockerfile invokes scripts/docker-link-repos.sh and
scripts/docker-package.sh directly (no bash prefix) - without +x this
fails immediately on any fresh clone/full rebuild. The same bug also
affects fetchdep.sh, get-version-from-git.sh, layered.sh,
normalize-version.sh, and playwright-common/playwright-screenshots.sh,
all invoked directly the same way by this repo's own GitHub Actions
workflows (build.yml, tests.yml, static_analysis.yaml, docs.yml) - so
this was also silently breaking CI, not just Docker builds.
2026-07-28 12:00:00 +00:00
sorB 9c7ece2241 feat: call participants orientation vertical
Build Debian package / Build package (release) Has been cancelled
Build and Deploy / prepare (release) Has been cancelled
Deploy release / Deploy to Cloudflare Pages (release) Has been cancelled
Build and Deploy / Trigger Pro pipeline (release) Has been cancelled
Build and Deploy / Windows arm64 (release) Has been cancelled
Build and Deploy / Windows x64 (release) Has been cancelled
Build and Deploy / macOS (release) Has been cancelled
Build and Deploy / Linux amd64 (sqlcipher static) (release) Has been cancelled
Build and Deploy / Linux arm64 (sqlcipher static) (release) Has been cancelled
Build and Deploy / ${{ needs.prepare.outputs.deploy == 'true' && 'Deploy' || 'Deploy (dry-run)' }} (release) Has been cancelled
Build and Deploy / Deploy builds to ESS (release) Has been cancelled
Sync labels / sync-labels (push) Has been cancelled
Close stale issues & PRs / close (push) Has been cancelled
Build and Deploy / prepare (push) Has been cancelled
Build and Deploy / Trigger Pro pipeline (push) Has been cancelled
Build and Deploy / Windows arm64 (push) Has been cancelled
Build and Deploy / Windows x64 (push) Has been cancelled
Build and Deploy / macOS (push) Has been cancelled
Build and Deploy / Linux amd64 (sqlcipher static) (push) Has been cancelled
Build and Deploy / Linux arm64 (sqlcipher static) (push) Has been cancelled
Build and Deploy / ${{ needs.prepare.outputs.deploy == 'true' && 'Deploy' || 'Deploy (dry-run)' }} (push) Has been cancelled
Build and Deploy / Deploy builds to ESS (push) Has been cancelled
Localazy Download / download (push) Has been cancelled
Docker / Docker Buildx (push) Has been cancelled
Update Jitsi / update (push) Has been cancelled
2026-05-10 21:09:19 +02:00
sorB 3da363517f feat: show call participants in room list (Discord-style)
Docker / Docker Buildx (push) Has been cancelled
Build Debian package / Build package (release) Has been cancelled
Build and Deploy / prepare (release) Has been cancelled
Deploy release / Deploy to Cloudflare Pages (release) Has been cancelled
Build and Deploy / Trigger Pro pipeline (release) Has been cancelled
Build and Deploy / Windows arm64 (release) Has been cancelled
Build and Deploy / Windows x64 (release) Has been cancelled
Build and Deploy / macOS (release) Has been cancelled
Build and Deploy / Linux amd64 (sqlcipher static) (release) Has been cancelled
Build and Deploy / Linux arm64 (sqlcipher static) (release) Has been cancelled
Build and Deploy / ${{ needs.prepare.outputs.deploy == 'true' && 'Deploy' || 'Deploy (dry-run)' }} (release) Has been cancelled
Build and Deploy / Deploy builds to ESS (release) Has been cancelled
2026-05-10 14:25:35 +02:00
sorb b797925316 Initial commit 2026-05-10 11:31:35 +00:00
4892 changed files with 824115 additions and 13476 deletions
+24
View File
@@ -0,0 +1,24 @@
# Copyright 2024 New Vector Ltd.
# Copyright 2017 Aviral Dasgupta
#
# SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
# Please see LICENSE files in the repository root for full details.
root = true
[*]
charset=utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.{yml,yaml}]
indent_size = 4
[package.json]
indent_size = 4
[*.tsx.snap]
trim_trailing_whitespace = false
+3
View File
@@ -0,0 +1,3 @@
# prettier
526645c79160ab1ad4b4c3845de27d51263a405e
7921a6cbf86b035d2b0c1daecb4c24beaf5a5abc
+39
View File
@@ -0,0 +1,39 @@
* @element-hq/element-web-reviewers
/.github/workflows/** @element-hq/element-web-team
**/package.json @element-hq/element-web-team
/pnpm-lock.yaml @element-hq/element-web-team
/apps/web/src/SecurityManager.ts @element-hq/element-crypto-web-reviewers
/apps/web/test/unit-tests/SecurityManager-test.ts @element-hq/element-crypto-web-reviewers
/apps/web/src/async-components/views/dialogs/security/ @element-hq/element-crypto-web-reviewers
/apps/web/test/unit-tests/async-components/dialogs/security/ @element-hq/element-crypto-web-reviewers
/apps/web/src/components/views/dialogs/security/ @element-hq/element-crypto-web-reviewers
/apps/web/test/unit-tests/components/views/dialogs/security/ @element-hq/element-crypto-web-reviewers
/apps/web/src/stores/SetupEncryptionStore.ts @element-hq/element-crypto-web-reviewers
/apps/web/test/unit-tests/stores/SetupEncryptionStore-test.ts @element-hq/element-crypto-web-reviewers
/apps/web/src/components/views/settings/tabs/user/EncryptionUserSettingsTab.tsx @element-hq/element-crypto-web-reviewers
/apps/web/src/components/views/settings/encryption/ @element-hq/element-crypto-web-reviewers
/apps/web/test/unit-tests/components/views/settings/encryption/ @element-hq/element-crypto-web-reviewers
/apps/web/src/components/views/dialogs/devtools/Crypto.tsx @element-hq/element-crypto-web-reviewers
/apps/web/playwright/e2e/crypto/ @element-hq/element-crypto-web-reviewers
/apps/web/playwright/e2e/settings/encryption-user-tab/ @element-hq/element-crypto-web-reviewers
/packages/shared-components/src/crypto/ @element-hq/element-crypto-web-reviewers
/apps/web/src/models/Call.ts @element-hq/element-call-reviewers
/apps/web/src/call-types.ts @element-hq/element-call-reviewers
/apps/web/src/components/views/voip @element-hq/element-call-reviewers
/apps/web/playwright/e2e/voip/element-call.spec.ts @element-hq/element-call-reviewers
# Ignore translations as those will be updated by GHA for Localazy download
/apps/web/src/i18n/strings
/apps/desktop/src/i18n/strings
/packages/shared-components/src/i18n/strings
/apps/web/src/i18n/strings/en_EN.json @element-hq/element-web-reviewers
/apps/desktop/src/i18n/strings/en_EN.json @element-hq/element-web-reviewers
/packages/shared-components/src/i18n/strings/en_EN.json @element-hq/element-web-reviewers
# Ignore the synapse & mas plugins as this is updated by GHA for docker image updating
/apps/web/playwright/testcontainers/synapse.ts
/apps/web/playwright/testcontainers/mas.ts
+2
View File
@@ -0,0 +1,2 @@
patreon: matrixdotorg
liberapay: matrixdotorg
+76
View File
@@ -0,0 +1,76 @@
name: Bug report for the Element desktop app (not in a browser)
description: File a bug report if you are using the desktop Element application.
labels: [T-Defect, A-Electron]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please report security issues by email to security@matrix.org
- type: textarea
id: reproduction-steps
attributes:
label: Steps to reproduce
description: Please attach screenshots, videos or logs if you can.
placeholder: Tell us what you see!
value: |
1. Where are you starting? What can you see?
2. What do you click?
3. More steps…
validations:
required: true
- type: textarea
id: result
attributes:
label: Outcome
placeholder: Tell us what went wrong
value: |
#### What did you expect?
#### What happened instead?
validations:
required: true
- type: input
id: os
attributes:
label: Operating system
placeholder: Windows, macOS, Ubuntu, Arch Linux…
validations:
required: false
- type: input
id: version
attributes:
label: Application version
description: You can find the version information in Settings -> Help & About.
placeholder: e.g. Element version 1.7.34, olm version 3.2.3
validations:
required: false
- type: input
id: source
attributes:
label: How did you install the app?
description: Where did you install the app from? Please give a link or a description.
placeholder: e.g. From https://element.io/get-started
validations:
required: false
- type: input
id: homeserver
attributes:
label: Homeserver
description: |
Which server is your account registered on? If it is a local or non-public homeserver, please tell us what is the homeserver implementation (ex: Synapse/Dendrite/etc.) and the version.
placeholder: e.g. matrix.org or Synapse 1.50.0rc1
validations:
required: false
- type: dropdown
id: rageshake
attributes:
label: Will you send logs?
description: |
Did you know that you can send a /rageshake command from your application to submit logs for this issue? Trigger the defect, then type `/rageshake` into the message input area followed by a description of the problem and send the command. You will be able to add a link to this defect report and submit anonymous logs to the developers.
options:
- "Yes"
- "No"
validations:
required: true
+84
View File
@@ -0,0 +1,84 @@
name: Bug report for Element Web (in browser)
description: File a bug report if you are using Element in a web browser like Firefox, Chrome, Edge, and so on.
labels: [T-Defect]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please report security issues by email to security@matrix.org
- type: textarea
id: reproduction-steps
attributes:
label: Steps to reproduce
description: Please attach screenshots, videos or logs if you can.
placeholder: Tell us what you see!
value: |
1. Where are you starting? What can you see?
2. What do you click?
3. More steps…
validations:
required: true
- type: textarea
id: result
attributes:
label: Outcome
placeholder: Tell us what went wrong
value: |
#### What did you expect?
#### What happened instead?
validations:
required: true
- type: input
id: os
attributes:
label: Operating system
placeholder: Windows, macOS, Ubuntu, Arch Linux…
validations:
required: false
- type: input
id: browser
attributes:
label: Browser information
description: Which browser are you using? Which version?
placeholder: e.g. Chromium Version 92.0.4515.131
validations:
required: false
- type: input
id: webapp-url
attributes:
label: URL for webapp
description: Which URL are you using to access the webapp? If a private server, tell us what version of Element Web you are using.
placeholder: e.g. develop.element.io, app.element.io
validations:
required: false
- type: input
id: version
attributes:
label: Application version
description: You can find the version information in Settings -> Help & About.
placeholder: e.g. Element version 1.7.34, olm version 3.2.3
validations:
required: false
- type: input
id: homeserver
attributes:
label: Homeserver
description: |
Which server is your account registered on? If it is a local or non-public homeserver, please tell us what is the homeserver implementation (ex: Synapse/Dendrite/etc.) and the version.
placeholder: e.g. matrix.org or Synapse 1.50.0rc1
validations:
required: false
- type: dropdown
id: rageshake
attributes:
label: Will you send logs?
description: |
Did you know that you can send a /rageshake command from the web application to submit logs for this issue? Trigger the defect, then type `/rageshake` into the message input area followed by a description of the problem and send the command. You will be able to add a link to this defect report and submit anonymous logs to the developers.
options:
- "Yes"
- "No"
validations:
required: true
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Questions & support
url: https://matrix.to/#/#element-web:matrix.org
about: Please ask and answer questions here.
- name: Bug report for the Element flatpak app
url: https://github.com/flathub/im.riot.Riot/issues
about: Please file bugs with the Flatpak application on the respective repository.
+36
View File
@@ -0,0 +1,36 @@
name: Enhancement request
description: Do you have a suggestion or feature request?
labels: [T-Enhancement]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please [start a discussion here](https://github.com/element-hq/element-meta/discussions/new?category=ideas).
- type: textarea
id: usecase
attributes:
label: Your use case
description: What would you like to be able to do? Please feel welcome to include screenshots or mock ups.
placeholder: Tell us what you would like to do!
value: |
#### What would you like to do?
#### Why would you like to do it?
#### How would you like to achieve it?
validations:
required: true
- type: textarea
id: alternative
attributes:
label: Have you considered any alternatives?
placeholder: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: Additional context
placeholder: Is there anything else you'd like to add?
validations:
required: false
+9
View File
@@ -0,0 +1,9 @@
<!-- Thanks for submitting a PR! Please ensure the following requirements are met in order for us to review your PR -->
## Checklist
- [ ] I have read through [review guidelines](https://github.com/element-hq/element-web/blob/develop/docs/review.md) and [CONTRIBUTING.md](https://github.com/element-hq/element-web/blob/develop/CONTRIBUTING.md).
- [ ] Tests written for new code (and old code if feasible).
- [ ] New or updated `public`/`exported` symbols have accurate [TSDoc](https://tsdoc.org/) documentation.
- [ ] Linter and other CI checks pass.
- [ ] I have licensed the changes to Element by completing the [Contributor License Agreement (CLA)](https://cla-assistant.io/element-hq/element-web)
+35
View File
@@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGBzCCA++gAwIBAgIIaI6ivggL++4wDQYJKoZIhvcNAQELBQAwgZAxCzAJBgNV
BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE
CgwPU1NMIENvcnBvcmF0aW9uMUUwQwYDVQQDDDxTU0wuY29tIEVWIFJvb3QgQ2Vy
dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyIC0gRGV2ZWxvcG1lbnQwHhcNMTgw
MTE2MTIxNjM2WhcNNDMwMTE1MTIxNjM2WjCBkDELMAkGA1UEBhMCVVMxDjAMBgNV
BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9y
YXRpb24xRTBDBgNVBAMMPFNTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
dGhvcml0eSBSU0EgUjIgLSBEZXZlbG9wbWVudDCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAK/qcD65JCkueKp0+KXG2kAw8euDHuraLR3lJoUFz4ilGK1M
t+RjSuY6dHQw8ku7TnW9ejWoSFjCBSDx7tP/fzOwOxmBW6+F1NDuV/IaUtn3G2lk
CZglVk9z3n1HuWDN10xNiLoo5nzeIlvNAoDbXDGhI4Y6Z0qouAIS607JpJMWHOqZ
OUiiOuM11gI5Kz9GtVttXCjRmwlkU8WiJVIUuVedQAQt2FChrzNQewGFFi0uIau/
wFRclx6hd4JRIImC6VMJd9lcitWsqMcM94pD3fX2ozNgWX+MVlmcDYFSN9Sv8tG4
yCj4ONS8HZGzbxeyQXJhEJSi2FnBi0j6MD/d4DNFj0hCg9wz3fgVLDGCO0pNMO0Y
oXdrzfoj1/zEv0Ibgh7zKG2JHkPfapn3ExFI5d6xi66u5tPVI8cvLxqrgybRPs7Z
y1dQA7ew3LyTPAHoGtbTMvewtx1TkTtRxxhRRm0l58owqSVbSYrixFtosNobCERo
uiknaQqoY1ZDsdKsaqFoZDbntNRYhN3Ea4OPWVqDUU5ZPz9MTIRAi3MIq854yyQo
BjX9nv+kYa+Esr19pxUW0z7BWFhbXsMVpt0QMVyhwgzXvEreaZHFwHHaGb9d5x5P
VBDhsigMmtzBk9NlbCsy+uGXWHgZA/DVefueEq0sv38VoU30uYa5Tj0FLm09AgMB
AAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUI9PCucv3G9fRoTDu
ZQ4Hw6g4PkIwHQYDVR0OBBYEFCPTwrnL9xvX0aEw7mUOB8OoOD5CMA4GA1UdDwEB
/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAk43CCrC0Zbvi7YUsSePKi+KzvyQ9
mjKa5NBU/A5/sLeZS3R+wqCX7l5euYVDsUuNgNVD/QL9jNIonuHBrvKaxkmqxE1r
IcDEaUdjy2lQ0uqD7UDoS3ctrjGkPpUahrTdr3gaKcQBtUhn9v4Y2OBm6J1hDVwI
CIKcxIzRv6AUpApOtk+++m5tzDU48t8+GzrVl1hkspSYcumA+zuHllbPDL1ADdo5
kK/bBQtZrGqzPqKzeqaB1A5Wm0Igwf++7nyzdKNdjxtv907D9vg8EB4Swavuv/Ne
5/jbpI32pz0NIzzSl5ARAHuFhILsO/cEAlloDoTHzibHqFDIeU9/59HMUsJYMOtD
Ii0/LmQ6dBE4TeukCCLJwtkFYZ2eBgDjF/LHBB+z/UBs4milRgwx+Pe5UDUEjtGe
G/XMVnTSKZTy9jMaXJD5EmfP+Cfh8EEgFgjg4AmLUbEo9gXzPxyXSLgd8JGSsjg8
EV/Ri4Mmmt4XUwlSVvEOezxxDGd17gwbottCIC+rqPHonHkGmKpLMH80Bk0uOOCs
ui1oVwSifMyIcudgCcOfRLUf/f2j2NW7N7E7Vw/Zqfn+pqp/EG0KCqOM2vfJAc0s
u3rSrOJZGtB6txgtmTjoadxApWf4U/FCi3uArt6gS5MJqZjuiRNXs/K3SlSAqLGl
5UiG52ew+VdBHzE=
-----END CERTIFICATE-----
@@ -0,0 +1,40 @@
name: Upload release assets
description: Uploads assets to an existing release and optionally signs them
inputs:
tag:
description: GitHub release tag to fetch assets from.
required: true
out-file-path:
description: Path to where the webapp should be extracted to.
required: true
runs:
using: composite
steps:
- name: Download release tarball
uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1
with:
tag: ${{ inputs.tag }}
fileName: element-*.tar.gz*
out-file-path: ${{ runner.temp }}/download-verify-element-tarball
- name: Verify tarball
shell: bash
run: gpg --verify element-*.tar.gz.asc element-*.tar.gz
working-directory: ${{ runner.temp }}/download-verify-element-tarball
- name: Extract tarball
shell: bash
run: |
mkdir webapp
tar xvzf element-*.tar.gz -C webapp --strip-components=1
working-directory: ${{ runner.temp }}/download-verify-element-tarball
- name: Move webapp to out-file-path
shell: bash
run: mv ${{ runner.temp }}/download-verify-element-tarball/webapp "$OUT_PATH"
env:
OUT_PATH: ${{ inputs.out-file-path }}
- name: Clean up temp directory
shell: bash
run: rm -R ${{ runner.temp }}/download-verify-element-tarball
@@ -0,0 +1,49 @@
name: Setup playwright
description: Installs playwright browsers and sets up a cache
inputs:
needs-webkit:
description: Whether to install the additional dependencies for webkit
required: false
default: "false"
write-cache:
description: Whether to write the cache back
required: true
runs:
using: composite
steps:
- name: Calculate cache key
id: key
run: |
PW_VERSION=$(pnpm --silent -- playwright --version | awk '{print $2}')
echo "key=${PREFIX}-playwright-${PW_VERSION}" >> $GITHUB_OUTPUT
shell: bash
env:
PREFIX: ${{ runner.os }}-${{ runner.arch }}
- name: Cache playwright binaries
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
if: inputs.write-cache == 'true'
id: cache
with:
path: ~/.cache/ms-playwright
key: ${{ steps.key.outputs.key }}
# When running in merge queue only restore the cache, never write it
- name: Restore playwright binaries cache
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
if: inputs.write-cache != 'true'
id: cache-restore
with:
path: ~/.cache/ms-playwright
key: ${{ steps.key.outputs.key }}
- name: Install Playwright browsers
if: (steps.cache.outputs.cache-hit || steps.cache-restore.outputs.cache-hit) != 'true'
shell: bash
run: pnpm playwright install --with-deps
# Some WebKit dependencies seem to lay outside the cache and will need to be installed separately
- name: Install system dependencies for WebKit
if: inputs.needs-webkit == 'true' && (steps.cache.outputs.cache-hit || steps.cache-restore.outputs.cache-hit) == 'true'
shell: bash
run: pnpm playwright install-deps webkit
+16
View File
@@ -0,0 +1,16 @@
/*
! Access-Control-Allow-Origin
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
/version
Content-Type: text/plain
/apple-app-site-association
Content-Type: application/json
/.well-known/assetlinks.json
Content-Type: application/json
+310
View File
@@ -0,0 +1,310 @@
- name: "A-Aliases"
color: "bfd4f2"
- name: "A-Authentication"
color: "bfd4f2"
- name: "A-Autocomplete"
color: "bfd4f2"
- name: "A-Breadcrumbs"
color: "bfd4f2"
- name: "A-Bridge"
color: "bfd4f2"
- name: "A-Broadcast"
description: "Broadcast-style voice messages"
color: "bfd4f2"
- name: "A-Create-Room"
description: "Create room flow, user suggestions, etc."
color: "bfd4f2"
- name: "A-DevTools"
description: "/devtools, show hidden events, etc."
color: "bfd4f2"
- name: "A-Dialogs"
color: "bfd4f2"
- name: "A-Disambiguation"
color: "bfd4f2"
- name: "A-DM-Start"
description: "Creating a DM with another user"
color: "bfd4f2"
- name: "A-E2EE-Dehydration"
color: "8CC59A"
- name: "A-Electron"
color: "bfd4f2"
- name: "A-Element-Call"
description: "Group calls via Element Call"
color: "bfd4f2"
- name: "A-Element-R"
description: "Issues affecting the port of Element's crypto layer to Rust"
color: "bfd4f2"
- name: "A-ELS"
description: "Event List Summary (and Membership ELS, MELS)"
color: "bfd4f2"
- name: "A-Emotes"
color: "bfd4f2"
- name: "A-EMS"
description: "Issues related to EMS"
color: "bfd4f2"
- name: "A-Error-Message"
color: "bfd4f2"
- name: "A-Federation"
color: "bfd4f2"
- name: "A-Feedback-Reporting"
description: "Reporting process for bugs, debug logs (rageshakes), suggestions"
color: "bfd4f2"
- name: "A-File-Download"
color: "bfd4f2"
- name: "A-File-Panel"
color: "bfd4f2"
- name: "A-Identity-Server"
color: "bfd4f2"
- name: "A-Indexing"
description: "Indexing messages via Seshat"
color: "bfd4f2"
- name: "A-IRC-Layout"
color: "bfd4f2"
- name: "A-Jump-To-Date"
description: "Jump to date headers or slash command"
color: "bfd4f2"
- name: "A-Lazy-Loading"
color: "bfd4f2"
- name: "A-Light-Box"
description: "UI when viewing an image"
color: "bfd4f2"
- name: "A-Location-Sharing"
color: "bfd4f2"
- name: "A-Logout"
description: "Logout, sign out, etc."
color: "bfd4f2"
- name: "A-Maths"
description: "Render LaTeX maths in messages"
color: "bfd4f2"
- name: "A-Memory"
description: "Memory leaks, leak hunting tools"
color: "bfd4f2"
- name: "A-Message-Forwarding"
color: "bfd4f2"
- name: "A-Message-Pinning"
color: "bfd4f2"
- name: "A-Message-Previews"
color: "bfd4f2"
- name: "A-Message-Starring"
description: "Saving favourite messages for later"
color: "bfd4f2"
- name: "A-Modules"
description: "Module system related"
color: "bfd4f2"
- name: "A-New-Search-Experience"
description: "The new search dialog available in Labs"
color: "bfd4f2"
- name: "A-Packaging"
description: "Packaging, signing, releasing"
color: "bfd4f2"
- name: "A-Peeking"
color: "bfd4f2"
- name: "A-Picture-in-Picture"
color: "bfd4f2"
- name: "A-Power-Levels"
description: "The permissions that users have in rooms and spaces"
color: "bfd4f2"
- name: "A-Replies"
description: "reply"
color: "bfd4f2"
- name: "A-Session-Mgmt"
description: "Session / device names, management UI, etc."
color: "bfd4f2"
- name: "A-Share"
color: "bfd4f2"
- name: "A-Shortcuts"
description: "Keyboard shortcuts"
color: "bfd4f2"
- name: "A-Sliding-Sync"
description: "Also known as Sync v3 - https://github.com/matrix-org/sliding-sync"
color: "bfd4f2"
- name: "A-Soft-Logout"
description: "https://github.com/element-hq/element-web/issues/10224"
color: "bfd4f2"
- name: "A-Spaces-Settings"
color: "bfd4f2"
- name: "A-SSO"
color: "bfd4f2"
- name: "A-Status-Bar"
description: "Unsent messages warning and 'Connectivity to the server has been lost'"
color: "bfd4f2"
- name: "A-Storage"
description: "Storage layer of the app, including IndexedDB, local storage, etc."
color: "bfd4f2"
- name: "A-Technical-Debt"
color: "bfd4f2"
- name: "A-Testing"
description: "Testing, code coverage, etc."
color: "bfd4f2"
- name: "A-Themes-Custom"
description: "Custom theme variables or support"
color: "bfd4f2"
- name: "A-Themes-Official"
description: "Official themes (light, dark)"
color: "bfd4f2"
- name: "A-Theming"
color: "bfd4f2"
- name: "A-Timeline-Jumpy-Scroll"
description: "Stable timeline dream ✨"
color: "bfd4f2"
- name: "A-Timesheet-1"
description: "Log any time spent on this into the A-Timesheet-1 project"
color: "5319E7"
- name: "A-Toast"
color: "bfd4f2"
- name: "A-Tooltips"
description: "Anything related to tooltips"
color: "bfd4f2"
- name: "A-UI-Customisation"
description: "UIFeatures etc. for customising entire parts of the UI"
color: "bfd4f2"
- name: "A-URL-Previews"
color: "bfd4f2"
- name: "A-User-Menu"
description: "The top left main menu with the user's name and avatar"
color: "bfd4f2"
- name: "A-User-Search"
description: "The start DM or invite to room dialogs (things dealing with `/user_directory/search`)"
color: "bfd4f2"
- name: "A-Video-Rooms"
description: "Persistent group calls"
color: "bfd4f2"
- name: "A-Voice-Messages"
color: "bfd4f2"
- name: "A-Welcome-Page"
color: "bfd4f2"
- name: "A-Install"
color: "72A447"
- name: "A-Seshat"
color: "8262BE"
- name: "A-Update"
color: "17BE67"
- name: "backport staging"
description: "Label to automatically backport PR to staging branch"
color: "B60205"
- name: "Dependencies"
description: "Pull requests that update a dependency file"
color: "0366d6"
- name: "Hacktoberfest"
description: "Issues which are suitable for Hacktoberfest PRs: https://hacktoberfest.digitalocean.com/"
color: "ff7518"
- name: "P4"
description: "[OBSOLETE LABEL] Interesting — Not yet scheduled, will accept patches"
color: "d1e5f0"
- name: "spam"
color: "B60205"
- name: "Sponsored"
color: "ffc8f4"
- name: "T-Deprecation"
description: "A pull request that makes something deprecated"
color: "98e6ae"
- name: "T-Other"
description: "Questions, user support, anything else"
color: "98e6ae"
- name: "Team: App"
color: "FFA500"
- name: "X-Blocked"
color: "ff7979"
- name: "X-Cannot-Reproduce"
color: "ff7979"
- name: "X-Command"
description: "Created using the !github command"
color: "ff7979"
- name: "X-Community-Supported-Platform"
description: "This issue occurs in a platform not directly supported by us, but by a community project elsewhere"
color: "ff7979"
- name: "X-Upcoming-Release-Blocker"
description: "This does not affect the current release cycle but will affect the next one"
color: "e99695"
- name: "X-Run-All-Tests"
description: "When applied to PRs, it'll run the full gamut of end-to-end tests on the PR"
color: "ff7979"
- name: "Z-Actions"
color: "ededed"
- name: "Z-Cache-Confusion"
description: "Related to internal cache (clearing helps / causes the issue)"
color: "ededed"
- name: "Z-Community-PR"
description: "Issue is solved by a community member's PR"
color: "ededed"
- name: "Z-Element-R-Blocker"
description: "A blocker for enabling Element R by default"
color: "ededed"
- name: "Z-Experimental"
color: "ededed"
- name: "Z-Fixed by Element Call"
description: "Issues which can be closed when we move to Element Call"
color: "ededed"
- name: "Z-Fixed-By-OIDC"
description: "Issues which can be closed when we move to OIDC"
color: "ededed"
- name: "Z-Flaky-Test"
description: "A test is raising false alarms"
color: "ededed"
- name: "Z-Flaky-Test-Chrome"
description: "Flaky playwright test in Chrome"
color: "ededed"
- name: "Z-Flaky-Test-Firefox"
description: "Flaky playwright test in Firefox"
color: "ededed"
- name: "Z-Flaky-Test-Webkit"
description: "Flaky playwright test in Webkit"
color: "ededed"
- name: "Z-Flaky-Jest-Test"
description: "A Jest test is raising false alarms"
color: "ededed"
- name: "Z-FOSDEM"
description: "Issues in chat.fosdem.org"
color: "ededed"
- name: "Z-Gitter"
description: "Issues relating to or coming out of the Gitter migration, feature parity, etc"
color: "ededed"
- name: "Z-Legacy-Crypto"
description: "Issues affecting the legacy crypto stack"
color: "EEEEEE"
- name: "Z-Maximised-Widgets"
color: "ededed"
- name: "Z-Papercuts"
description: "Visible. Impactful. Predictable to action."
color: "ededed"
- name: "Z-Power-Users"
color: "ededed"
- name: "Z-Rageshake"
description: "Has attached rageshake (not for log submission process)"
color: "ededed"
- name: "Z-RICE"
color: "ededed"
- name: "Z-Soft-Crash"
description: "React soft crash caught by an error boundary"
color: "ededed"
- name: "Z-Spec-Compliance"
description: "An area where Element doesn't correctly implement the spec"
color: "ededed"
- name: "Z-t3chguy"
color: "ededed"
- name: "Z-Flaky-Test-Disabled"
description: "The flaking test has been disabled"
color: "ededed"
- name: "Z-Skip-Coverage"
description: "Skip SonarQube coverage for this PR"
color: "ededed"
- name: "Z-Arch"
color: "D601BE"
- name: "Z-ARM"
color: "5DEC5B"
- name: "Z-Flatpak"
color: "0CA856"
- name: "Z-Linux"
color: "7B4A9C"
- name: "Z-macOS"
color: "500605"
- name: "Z-Official"
color: "1D2B20"
- name: "Z-Snap"
color: "29CD95"
- name: "Z-Suse"
color: "79D07B"
- name: "Z-Wayland"
color: "94C519"
- name: "Z-Windows"
color: "0632DE"
+3
View File
@@ -0,0 +1,3 @@
_extends: matrix-org/matrix-js-sdk
version-resolver:
default: patch
+46
View File
@@ -0,0 +1,46 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["github>matrix-org/renovate-config-element-web"],
"postUpdateOptions": ["pnpmDedupe"],
"stopUpdatingLabel": "X-Blocked",
"packageRules": [
{
"description": "Group all testcontainers docker digests",
"groupName": "testcontainers docker digests",
"groupSlug": "testcontainers-docker",
"matchDepTypes": ["testcontainers-docker"],
"matchPackageNames": ["*"]
},
{
"description": "Separate updates to overrides from other groups",
"matchDepTypes": ["pnpm.overrides"],
"groupSlug": null
},
{
"description": "Disable any major updates to overrides as this almost always is wrong",
"matchDepTypes": ["pnpm.overrides"],
"matchUpdateTypes": ["major"],
"enabled": false
}
],
"customManagers": [
{
"description": "Update testcontainers docker digests",
"customType": "regex",
"datasourceTemplate": "docker",
"versioningTemplate": "loose",
"managerFilePatterns": ["**/testcontainers/*.ts"],
"matchStrings": ["\\s+\"(?<depName>[^@]+):(?<currentValue>[^@]+)@(?<currentDigest>sha256:[a-f0-9]+)\""],
"depTypeTemplate": "testcontainers-docker"
},
{
"description": "Update element-desktop hakDependencies",
"customType": "jsonata",
"managerFilePatterns": ["/(^|/)package\\.json$/"],
"fileFormat": "json",
"matchStrings": ["hakDependencies.$each(function($v, $k) { { 'packageName': $k, 'currentValue': $v } })"],
"datasourceTemplate": "npm",
"depTypeTemplate": "hak"
}
]
}
+40 -8
View File
@@ -1,12 +1,44 @@
/build
/cert.pem
/karma-reports
/dist
/key.pem
/lib
/node_modules
/packages/
/vector/bundle.*
/vector/components.css
/vector/emojione/
/vector/config.json
/vector/olm.js
node_modules
/.npmrc
/*.log
package-lock.json
.DS_Store
**/.idea
/webpack-stats.json
/.tmp
.vscode
.vscode/
.env
.env.*
coverage
/index.html
# version file and tarball created by `npm pack` / `yarn pack`
/git-revision.txt
jest-sonar.xml
*storybook.log
storybook-static
/packages/shared-components/node_modules
/packages/shared-components/dist
/packages/shared-components/src/i18nKeys.d.ts
/packages/shared-components/.vitest-attachments
# TSC incremental compilation information
*.tsbuildinfo
/.link-config
.nx/cache
.nx/workspace-data
.pnpm-store
# vitepress
/docs/.vitepress/dist
/docs/.vitepress/cache
+274
View File
@@ -0,0 +1,274 @@
# GitLab-CI fuer den ThreadNet-Web-Fork (Lab-GitLab: git.lab).
# Ersetzt die frueheren GitHub/Gitea-Actions-Workflows - Hintergrund: docs/axion1337-fork.md.
#
# Erkenntnisse aus den Gitea-CI-Versuchen (2026-07-30), hier eingeflossen:
# - kein scripts/layered.sh: wuerde den gepinnten matrix-js-sdk-Stand aus pnpm-lock.yaml
# mit Upstream-develop ueberschreiben (und braucht jq) -> frozen-lockfile-Install
# - webpack braucht ~4 GB Heap -> NODE_OPTIONS
# - Desktop-Build laeuft im dockerbuild-Image (rust:bullseye + node, glibc-2.31-Ziel)
stages:
- build
- package
# --- Windows-Runner-VM-Steuerung (Issue #5) ---------------------------------
# Die Windows-Build-VM (dockur/windows-Fork, siehe git.lab/axion1337.chat/vendor/windows,
# Runbook: docs/axion-runner.md dort) laeuft on-demand auf Overmind. Diese beiden Jobs
# starten/stoppen sie vom Linux-Runner aus ueber den Docker-Socket - der
# desktop_windows-Job wartet danach einfach in der Queue, bis der Runner online ist.
start_windows_vm:
stage: build
image: docker:27-cli
rules:
- if: $CI_COMMIT_TAG =~ /^v/
when: manual
allow_failure: true
- if: $CI_COMMIT_BRANCH == "main"
when: manual
allow_failure: true
script:
- docker start windows-runner
stop_windows_vm:
stage: package
image: docker:27-cli
rules:
- if: $CI_COMMIT_TAG =~ /^v/
when: manual
allow_failure: true
- if: $CI_COMMIT_BRANCH == "main"
when: manual
allow_failure: true
script:
- docker stop windows-runner
# CVE-Scan des eigenen Prod-Images (gitops#31): woechentlich per Schedule und
# manuell triggerbar. Bricht bewusst nicht hart ab (allow_failure) - Funde landen
# als Artifact + Job-Log, die Bewertung bleibt menschlich. Lab-interne Images
# (desktop-build, windows-vm) brauchen erst CA-Trust im Trivy-Container - notiert
# in gitops#31 als Ausbaustufe.
trivy_scan:
stage: build
image:
name: aquasec/trivy:0.58.2
entrypoint: [""]
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
allow_failure: true
- if: $CI_COMMIT_BRANCH == "main"
when: manual
allow_failure: true
variables:
GIT_STRATEGY: none
TRIVY_NO_PROGRESS: "true"
script:
- trivy image --severity HIGH,CRITICAL --format table --output trivy-web.txt rohana.axion1337.de/sorb/threadnet-web:latest-ci
- grep -E "Total|CRITICAL|HIGH" trivy-web.txt | head -20 || true
artifacts:
paths:
- trivy-web.txt
expire_in: 30 days
when: always
web:
stage: build
image: node:24-bullseye
rules:
# Release-Tags bauen immer (docker_web/desktop_* brauchen web als needs)
- if: $CI_COMMIT_TAG =~ /^v/
# Scheduled Pipelines gehoeren dem trivy_scan - kein wochentlicher Leerbuild
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
# Pushes nur, wenn build-relevante Pfade betroffen sind - Doku-Commits kosten nichts
- if: $CI_COMMIT_BRANCH
changes:
- apps/**/*
- packages/**/*
- patches/**/*
- scripts/**/*
- pnpm-lock.yaml
- pnpm-workspace.yaml
- .gitlab-ci.yml
variables:
NODE_OPTIONS: "--max-old-space-size=6144"
CI_PACKAGE: "true"
before_script:
- corepack enable
script:
- pnpm install --frozen-lockfile
- cp apps/web/element.io/develop/config.json apps/web/config.json
- VERSION=$(scripts/get-version-from-git.sh) pnpm --dir apps/web build
artifacts:
paths:
- apps/web/webapp
expire_in: 1 day
# Baut das kanonische Web-Image (apps/web/Dockerfile, Kontext = Monorepo-Root) und pusht
# es in die rohana-Registry, aus der Flux/k8s zieht. Deploy bleibt ein manueller Tag-Bump
# im gitops-Repo. Bewusster Doppel-Build (webpack laeuft im web-Job UND im Dockerfile) -
# kanonisch/reproduzierbar vor schnell; Optimierung als Folgearbeit in Issue #2.
docker_web:
stage: package
image: docker:27-cli
needs:
- job: web
artifacts: false
rules:
# Nur bei Release-Tags (v*) - "releasen" ist ein bewusster Akt:
# Tag pushen -> Image entsteht -> Tag-Bump im gitops-Repo deployt es
- if: $CI_COMMIT_TAG =~ /^v/
variables:
IMAGE: rohana.axion1337.de/sorb/threadnet-web
DOCKER_BUILDKIT: "1"
script:
- echo "$REGISTRY_PASSWORD" | docker login rohana.axion1337.de -u "$REGISTRY_USER" --password-stdin
- docker build -f apps/web/Dockerfile -t "$IMAGE:$CI_COMMIT_TAG" -t "$IMAGE:latest-ci" .
- docker push "$IMAGE:$CI_COMMIT_TAG"
- docker push "$IMAGE:latest-ci"
# Einmalig/selten: Build-Image fuer den Desktop-Build (rust:bullseye + node + tcl/sqlcipher,
# aus apps/desktop/dockerbuild). Manuell ausloesen, wenn sich .node-version oder das
# Dockerfile aendert.
desktop_image:
stage: package
image: docker:27-cli
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
allow_failure: true
variables:
# Lab-Registry statt rohana (OVERMIND-01): Konsument ist nur die Lab-CI selbst
IMAGE: $CI_REGISTRY_IMAGE/desktop-build
script:
- echo "$CI_JOB_TOKEN" | docker login "$CI_REGISTRY" -u gitlab-ci-token --password-stdin
- docker build -f apps/desktop/dockerbuild/Dockerfile -t "$IMAGE:bullseye" apps/desktop
- docker push "$IMAGE:bullseye"
# Electron-Linux-Build (amd64, static sqlcipher) - repliziert den am 2026-07-29 manuell
# verifizierten Build-Weg. Automatisch bei Release-Tags, auf main manuell triggerbar.
desktop_linux:
stage: package
image: registry.git.lab/axion1337.chat/threadnet-web/desktop-build:bullseye
needs:
- job: web
artifacts: true
rules:
- if: $CI_COMMIT_TAG =~ /^v/
- if: $CI_COMMIT_BRANCH == "main"
when: manual
allow_failure: true
variables:
MAX_GLIBC: "2.31"
USE_HARD_LINKS: "false"
SQLCIPHER_BUNDLED: "1"
# Eigene Build-Variante: Produktname ThreadNet statt Element. Ohne das nutzt
# electron-builder element.io/release/build.json und die Pakete heissen weiter
# "element-desktop" (real passiert 2026-08-02).
VARIANT_PATH: axion1337/build.json
script:
- pnpm install --frozen-lockfile --filter element-desktop
- cp -r apps/web/webapp apps/desktop/webapp
# Produktions-Client-Config (getrackt seit diesem Commit, vorher nur im manuellen Build)
- cp apps/desktop/axion1337/config.json apps/desktop/webapp/config.json
- cd apps/desktop
- pnpm run asar-webapp
- pnpm run build:native
# pnpm/npm setzen beim Install kein Executable-Bit auf 7za - bekannter Fix,
# gleicher Schritt wie in der Upstream-CI ("Fix permissions")
- chmod +x ../../node_modules/7zip-bin/linux/*/7za || true
- pnpm run build --publish never -l tar.gz -l deb
artifacts:
paths:
- apps/desktop/dist/*.deb
- apps/desktop/dist/*.tar.gz
expire_in: 1 week
# Windows-Desktop-Build (x64, unsigniert - Signing siehe Issue #5). Laeuft NUR auf dem
# Windows-Runner (tags), manuell: vorher start_windows_vm ausloesen. Uebersetzt aus dem
# Upstream-Workflow build_desktop_windows.yaml (x64-Pfad; arm-only-Schritte entfallen).
desktop_windows:
stage: package
tags:
- windows
needs:
- job: web
artifacts: true
rules:
- if: $CI_COMMIT_TAG =~ /^v/
when: manual
allow_failure: true
- if: $CI_COMMIT_BRANCH == "main"
when: manual
allow_failure: true
variables:
SQLCIPHER_BUNDLED: "1"
ELECTRON_CACHE: C:\electron-cache
ELECTRON_BUILDER_CACHE: C:\eb-cache
# Eigene Build-Variante (Produktname ThreadNet) - siehe desktop_linux
VARIANT_PATH: axion1337/build.json
script:
- pnpm install --frozen-lockfile --filter element-desktop
# GitHub-CDN-Downloads (Electron-Binary, winCodeSign, NSIS) reissen im Gast
# reproduzierbar ab und app-builder kann nicht fortsetzen (Jobs 415/416/424) -
# das Skript laedt alles resumefaehig in die persistenten Caches vor.
- powershell -ExecutionPolicy Bypass -File apps\desktop\axion1337\prefetch-buildcache.ps1
- Copy-Item -Recurse apps/web/webapp apps/desktop/webapp
- Copy-Item apps/desktop/axion1337/config.json apps/desktop/webapp/config.json -Force
- cd apps/desktop
- pnpm run asar-webapp
- '& "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\Tools\Launch-VsDevShell.ps1" -Arch amd64 -SkipAutomaticLocation'
- pnpm run build:native --target x86_64-pc-windows-msvc
- pnpm run build --publish never -w nsis
artifacts:
paths:
- apps/desktop/dist/*.exe
expire_in: 1 week
# Idempotente Werkzeug-Provisionierung im Windows-Gast (laeuft als SYSTEM ueber den
# Runner selbst - kein noVNC/RDP noetig). Hintergrund: choco akzeptiert --version nicht
# bei Mehrfach-Paketen, der urspruengliche Runbook-Einzeiler hat still nichts installiert.
# Startet am Ende den Runner-Dienst verzoegert neu, damit der neue PATH fuer
# Folge-Jobs greift (der Job selbst wird davon nicht mehr unterbrochen).
windows_provision:
stage: build
tags:
- windows
rules:
- if: $CI_COMMIT_BRANCH == "main"
when: manual
allow_failure: true
variables:
# Kein Checkout - der braeuchte git, das dieser Job erst installiert (Henne-Ei)
GIT_STRATEGY: none
script:
- choco install -y git
- choco install -y nasm
- choco install -y magicsplat-tcl-tk
- choco install -y nodejs --version=24.15.0
# Fuer den seshat-hak-Build (hak/matrix-seshat/check.ts): perl+patch (Strawberry
# liefert beides, patch.exe in C:\Strawberry\c\bin), python (node-gyp), rustc.
- choco install -y strawberryperl
- choco install -y python3
# Rust maschinenweit statt Benutzerprofil: der Runner-Dienst laeuft als SYSTEM und
# sieht nur die Maschinen-Umgebung - ein Default-rustup unter %USERPROFILE% waere
# fuer Jobs unsichtbar.
- $env:RUSTUP_HOME='C:\Rust\rustup'; $env:CARGO_HOME='C:\Rust\cargo'; Invoke-WebRequest -UseBasicParsing https://win.rustup.rs/x86_64 -OutFile "$env:TEMP\rustup-init.exe"
- '& "$env:TEMP\rustup-init.exe" -y --profile minimal --default-toolchain stable --default-host x86_64-pc-windows-msvc'
- '[Environment]::SetEnvironmentVariable(''RUSTUP_HOME'',''C:\Rust\rustup'',''Machine'')'
- '[Environment]::SetEnvironmentVariable(''CARGO_HOME'',''C:\Rust\cargo'',''Machine'')'
# choco-nasm traegt sich nicht selbst in den PATH ein (Upstream macht das auch
# explizit via GITHUB_PATH) - zusammen mit cargo\bin hier maschinenweit nachziehen
- $mp=[Environment]::GetEnvironmentVariable('Path','Machine'); if ($mp -notlike '*C:\Rust\cargo\bin*') { [Environment]::SetEnvironmentVariable('Path', "$mp;C:\Rust\cargo\bin;C:\Program Files\NASM", 'Machine') }
- refreshenv; corepack enable
- '& "C:\Program Files\Git\cmd\git.exe" --version'
- '& "C:\Program Files\nodejs\node.exe" --version'
- '& C:\Rust\cargo\bin\rustc.exe --version'
# Windows-260-Zeichen-Pfadlimit: die Visual-Baseline-Pfade des Monorepos sprengen
# MAX_PATH - beide Schalter noetig (git-seitig + OS-Policy)
- '& "C:\Program Files\Git\cmd\git.exe" config --system core.longpaths true'
- Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name LongPathsEnabled -Value 1 -Type DWord
# Dienst-Neustart als Scheduled Task: ueberlebt das Prozessbaum-Cleanup des Runners
# beim Job-Ende (der fruehere Start-Process-Trick wurde dabei gekillt und liess den
# Dienst gestoppt zurueck - Vorfall 2026-07-31, siehe ThreadNet-Web#5).
- schtasks /create /f /tn RunnerRestart /ru SYSTEM /sc once /st ((Get-Date).AddMinutes(1).ToString('HH:mm')) /tr "powershell -Command Restart-Service gitlab-runner -Force"
+1
View File
@@ -0,0 +1 @@
npx lint-staged --concurrent false
+3
View File
@@ -0,0 +1,3 @@
{
"*": "prettier --write --ignore-unknown"
}
-14
View File
@@ -1,14 +0,0 @@
{
"minify": true,
"classPrefix": "modernizr_",
"options": [
"setClasses"
],
"feature-detects": [
"test/css/displaytable",
"test/css/flexbox",
"test/es5/specification",
"test/css/objectfit",
"test/storage/localstorage"
]
}
+1
View File
@@ -0,0 +1 @@
24
-3
View File
@@ -1,3 +0,0 @@
example
examples
build/.module-cache
+71
View File
@@ -0,0 +1,71 @@
/build
/dist
/lib
node_modules
/apps/web/webapp
/*.log
pnpm-lock.yaml
electron/dist
electron/pub
**/.idea
/.tmp
webpack-stats.json
.vscode
.vscode/
.env
coverage
# Auto-generated files
*.api.md
/apps/web/src/modules.ts
/apps/web/src/modules.js
src/i18n/strings
/apps/web/build_config.yaml
# Raises an error because it contains a template var breaking the script tag
/apps/web/src/vector/index.html
/apps/web/src/vector/modernizr.cjs
/docs/lib
/book
debian/tmp
/.npmrc
package-lock.json
# This file is owned, parsed, and generated by allchange, which doesn't comply with prettier
CHANGELOG.md
/docs/changelogs
# Legacy skinning file that some people might still have
/apps/web/src/component-index.js
# Downloaded and already minified
/apps/web/res/jitsi_external_api.min.js
# This file is also machine-generated
/apps/web/playwright/e2e/crypto/test_indexeddb_cryptostore_dump/dump.json
/apps/web/playwright/test-results/
/apps/web/playwright/html-report/
/apps/web/playwright/logs/
/apps/web/playwright/snapshots/
/apps/desktop/.hak/
/apps/desktop/dist/
/apps/desktop/build/
/apps/desktop/dockerbuild/
/apps/desktop/deploys/
/apps/desktop/lib/
/apps/desktop/webapp
/apps/desktop/playwright/html-report
/apps/desktop/playwright/test-results
# Shared components generated files
/packages/shared-components/dist/
/packages/shared-components/src/i18n/i18nKeys.d.ts
/packages/shared-components/typedoc/
/packages/shared-components/storybook-static/
# These files are generated by running `pnpm -r lint:types` and do not adhere to prettier's requirements.
# All of them are .gitignored within their parent directory.
/packages/playwright-common/lib/
/packages/module-api/lib/
/packages/module-api/temp/
/.nx/
+1
View File
@@ -0,0 +1 @@
module.exports = require("eslint-plugin-matrix-org/.prettierrc.js");
+12
View File
@@ -10,3 +10,15 @@ include:
* Florent VIOLLEAU (https://github.com/floviolleau) <floviolleau at gmail dot com>
Improve README.md for a better understanding of installation instructions
* Michael Telatynski (https://github.com/t3chguy)
Improved consistency of inverted elements in dark theme across browsers
* Alexandr Korsak (https://github.com/oivoodoo)
Improved multiple file uploading
* Thom Cleary (https://github.com/thomcatdotrocks)
Small update for tarball deployment
* Alexander (https://github.com/ioalexander)
Save image on CTRL + S shortcut
+1786 -137
View File
File diff suppressed because it is too large Load Diff
+230
View File
@@ -0,0 +1,230 @@
# Contributing code to Element Web
Everyone is welcome to contribute code to Element Web, provided that they are willing to license their contributions to Element under a [Contributor License Agreement](https://cla-assistant.io/element-hq/element-web) (CLA). This ensures that their contribution will be made available under an OSI-approved open-source license, currently licensed under Affero General Public License v3 (AGPLv3) or General Public License v3 (GPLv3) at your choice.
If you're contributing, or thinking about contributing, please come & chat to
us in our development room, [#element-dev](https://matrix.to/#/#element-dev:matrix.org).
This is the best place to ask questions about the code, how to work on the project
or whether a change is likely to be accepted.
## How to contribute
The preferred and easiest way to contribute changes to the project is to fork
it on github, and then create a pull request to ask us to pull your changes
into our repo (https://help.github.com/articles/using-pull-requests/)
We use GitHub's pull request workflow to review the contribution, and either
ask you to make any refinements needed or merge it and make them ourselves.
Your PR should have a title that describes what change is being made. This
is used for the text in the Changelog entry by default (see below), so a good
title will tell a user succinctly what change is being made. "Fix bug where
cows had five legs" and, "Add support for miniature horses" are examples of good
titles. Don't include an issue number here: that belongs in the description.
Definitely don't use the GitHub default of "Update file.ts".
As for your PR description, it should include these things:
- References to any bugs fixed by the change (in GitHub's `Fixes` notation)
- Describe the why and what is changing in the PR description so it's easy for
onlookers and reviewers to onboard and context switch. This information is
also helpful when we come back to look at this in 6 months and ask "why did
we do it like that?" we have a chance of finding out.
- Why didn't it work before? Why does it work now? What use cases does it
unlock?
- If you find yourself adding information on how the code works or why you
chose to do it the way you did, make sure this information is instead
written as comments in the code itself.
- Sometimes a PR can change considerably as it is developed. In this case,
the description should be updated to reflect the most recent state of
the PR. (It can be helpful to retain the old content under a suitable
heading, for additional context.)
- Include both **before** and **after** screenshots to easily compare and discuss
what's changing.
- Include a step-by-step testing strategy so that a reviewer can check out the
code locally and easily get to the point of testing your change.
- Add comments to the diff for the reviewer that might help them to understand
why the change is necessary or how they might better understand and review it.
Please **_do not use force push_** in your PRs. Doing so means we can't see what
has changed. We use squash merge to get a "clean" git history.
### Adding a new feature or enhancement
To make a great product with a great user experience, all the small efforts need to go in the same direction and be aligned and consistent with each other.
Before making your contribution, please consider the following:
- One product cant do everything well. Element is focusing on private end-to-end encrypted messaging and voice - this can either be for consumers (e.g. friends and family) or for professional teams and organizations. Public forums and other types of chats without E2EE remain supported but are not the primary use case in case UX compromises need to be made.
- There are 3 platforms - Web/Desktop, [Android](https://github.com/element-hq/element-x-android) and [iOS](https://github.com/element-hq/element-x-ios). These platforms need to have feature parity and design consistency. For some features, supporting all platforms is a must have, in some cases exceptions can be made to have it on one platform only.
- To make sure your idea fits both from a design/solution and use case perspective, please open a new issue (or find an existing issue) in [element-meta](https://github.com/element-hq/element-meta/issues) repository describing the use case and how you plan to tackle it. Do not just describe what feature is missing, explain why the users need it with a couple of real life examples from the field.
- In case of an existing issue, please comment that you're planning to contribute. If you create a new issue, please specify that in the issue. In such a case we will try to review the issue ASAP and provide you with initial feedback so you can be confident if and at which conditions your contributions will be accepted.
Once we know that you want to contribute and have confirmed that the new feature is overall aligned with the product direction, the designers of the core team will help you with the designs and any other type of guidance when it comes to the user experience. We will try to unblock you as quickly as we can, but it may not be instant. Having a clear understanding of the use case and the impact of the feature will help us with the prioritization and faster responses.
Only once all of the above is met should you open a PR with your proposed changes.
### Changelogs
There's no need to manually add Changelog entries: we use information in the
pull request to populate the information that goes into the changelogs our
users see, both for Element Web itself and other projects on which it is based.
This is picked up from both labels on the pull request and the `Notes:`
annotation in the description. By default, the PR title will be used for the
changelog entry, but you can specify more options, as follows.
To add a longer, more detailed description of the change for the changelog:
_Fix llama herding bug_
```
Notes: Fix a bug (https://github.com/matrix-org/notaproject/issues/123) where the 'Herd' button would not herd more than 8 Llamas if the moon was in the waxing gibbous phase
```
For some PRs, it's not useful to have an entry in the user-facing changelog (this is
the default for PRs labelled with `T-Task`):
_Remove outdated comment from `Ungulates.ts`_
If your PR introduces a breaking change, use the `Notes` section in the same
way, additionally adding the `X-Breaking-Change` label (see below). There's no need
to specify in the notes that it's a breaking change - this will be added
automatically based on the label - but remember to tell the developer how to
migrate:
_Remove legacy class_
```
Notes: Remove legacy `Camelopard` class. `Giraffe` should be used instead.
```
Other metadata can be added using labels.
- `X-Breaking-Change`: A breaking change - adding this label will mean the change causes a _major_ version bump.
- `T-Enhancement`: A new feature - adding this label will mean the change causes a _minor_ version bump.
- `T-Defect`: A bug fix (in either code or docs).
- `T-Task`: No user-facing changes, eg. code comments, CI fixes, refactors or tests. Won't have a changelog entry unless you specify one.
If you don't have permission to add labels, your PR reviewer(s) can work with you
to add them: ask in the PR description or comments.
We use continuous integration, and all pull requests get automatically tested:
if your change breaks the build, then the PR will show that there are failed
checks, so please check back after a few minutes.
## Tests
Your PR should include tests.
For new user facing features in `matrix-js-sdk` or `element-web`, you must include:
1. Comprehensive unit tests written in Jest. These are located in `/test`.
2. "happy path" end-to-end tests.
These are located in `/playwright/e2e`, and are run using `element-web`.
Ideally, you would also include tests for edge and error cases.
Unit tests are expected even when the feature is in labs. It's good practice
to write tests alongside the code as it ensures the code is testable from
the start, and gives you a fast feedback loop while you're developing the
functionality. End-to-end tests should be added prior to the feature
leaving labs, but don't have to be present from the start (although it might
be beneficial to have some running early, so you can test things faster).
For bugs in those repos, your change must include at least one unit test or
end-to-end test; which is best depends on what sort of test most concisely
exercises the area.
Changes to must be accompanied by unit tests written in Jest.
These are located in `/spec/` in `matrix-js-sdk` or `/test/` in `element-web`.
When writing unit tests, please aim for a high level of test coverage
for new code - 80% or greater. If you cannot achieve that, please document
why it's not possible in your PR.
Some sections of code are not sensible to add coverage for, such as those
which explicitly inhibit noisy logging for tests. Which can be hidden using
an istanbul magic comment as [documented here][1]. See example:
```javascript
/* istanbul ignore if */
if (process.env.NODE_ENV !== "test") {
logger.error("Log line that is noisy enough in tests to want to skip");
}
```
Tests validate that your change works as intended and also document
concisely what is being changed. Ideally, your new tests fail
prior to your change, and succeed once it has been applied. You may
find this simpler to achieve if you write the tests first.
If you're spiking some code that's experimental and not being used to support
production features, exceptions can be made to requirements for tests.
Note that tests will still be required in order to ship the feature, and it's
strongly encouraged to think about tests early in the process, as adding
tests later will become progressively more difficult.
If you're not sure how to approach writing tests for your change, ask for help
in [#element-dev](https://matrix.to/#/#element-dev:matrix.org).
## Code style
Element Web aims to target TypeScript/ES6. All new files should be written in
TypeScript and existing files should use ES6 principles where possible.
Members should not be exported as a default export in general - it causes problems
with the architecture of the SDK (index file becomes less clear) and could
introduce naming problems (as default exports get aliased upon import). In
general, avoid using `export default`.
The remaining code style is documented in [code_style.md](./code_style.md).
Contributors are encouraged to it and follow the principles set out there.
Please ensure your changes match the cosmetic style of the existing project,
and **_never_** mix cosmetic and functional changes in the same commit, as it
makes it horribly hard to review otherwise.
## Shared Components
When creating new UI components, consider whether they should be added to the shared components package (`packages/shared-components`) rather than directly in the main `src/` directory. Components should be placed in shared components if they:
- Are reusable across different parts of the application
- Could potentially be used by other Element projects (Element Desktop, Aurora, Element modules...)
- Follow established patterns and don't have tight coupling to specific application logic
For more details, see the [shared components README](./packages/shared-components/README.md).
## Attribution
Everyone who contributes anything to Matrix is welcome to be listed in the
AUTHORS.rst file for the project in question. Please feel free to include a
change to AUTHORS.rst in your pull request to list yourself and a short
description of the area(s) you've worked on. Also, we sometimes have swag to
give away to contributors - if you feel that Matrix-branded apparel is missing
from your life, please mail us your shipping address to matrix at matrix.org
and we'll try to fix it :)
# Review expectations
See https://github.com/element-hq/element-meta/wiki/Review-process
# Merge Strategy
The preferred method for merging pull requests is squash merging to keep the
commit history trim, but it is up to the discretion of the team member merging
the change. We do not support rebase merges due to `allchange` being unable to
handle them. When merging make sure to leave the default commit title, or
at least leave the PR number at the end in brackets like by default.
When stacking pull requests, you may wish to do the following:
1. Branch from develop to your branch (branch1), push commits onto it and open a pull request
2. Branch from your base branch (branch1) to your work branch (branch2), push commits and open a pull request configuring the base to be branch1, saying in the description that it is based on your other PR.
3. Merge the first PR using a merge commit otherwise your stacked PR will need a rebase. Github will automatically adjust the base branch of your other PR to be develop.
[1]: https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md
# Decoding Stack Traces
Element Web has crashed and given you an obfuscated stack trace? Don't panic:
use the [Decoder Ring](https://app.element.io/decoder-ring/) (or /decoder-ring/
on any Element Web deploy). It is somewhat of a manual process, but it should
tell you what lines the stack trace corresponds to from the source maps.
-4
View File
@@ -1,4 +0,0 @@
Contributing code to Vector
===========================
Vector follows the same pattern as https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.rst
+208 -150
View File
@@ -1,177 +1,235 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
1. Definitions.
Preamble
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license.
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
The precise terms and conditions for copying, distribution and modification follow.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
TERMS AND CONDITIONS
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
0. Definitions.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
"This License" refers to version 3 of the GNU Affero General Public License.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
"Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
"The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations.
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work.
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
A "covered work" means either the unmodified Program or a work based on the Program.
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
1. Source Code.
The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those
subprograms and other parts of the work.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
END OF TERMS AND CONDITIONS
The Corresponding Source for a work in source code form is that same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices".
c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
"Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph.
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
ThreadNet-Web
Copyright (C) 2026 sorb
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements.
You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see <http://www.gnu.org/licenses/>.
+661
View File
@@ -0,0 +1,661 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.
+6
View File
@@ -0,0 +1,6 @@
Licensees holding a valid commercial license with Element may use this
software in accordance with the terms contained in a written agreement
between you and Element.
To purchase a commercial license please contact our sales team at
licensing@element.io
+674
View File
@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
+85 -193
View File
@@ -1,231 +1,123 @@
Vector/Web
==========
[![Chat](https://img.shields.io/matrix/element-web:matrix.org?logo=matrix)](https://matrix.to/#/#element-web:matrix.org)
![Tests](https://github.com/element-hq/element-web/actions/workflows/tests.yaml/badge.svg)
![Static Analysis](https://github.com/element-hq/element-web/actions/workflows/static_analysis.yaml/badge.svg)
[![Localazy](https://img.shields.io/endpoint?url=https%3A%2F%2Fconnect.localazy.com%2Fstatus%2Felement-web%2Fdata%3Fcontent%3Dall%26title%3Dlocalazy%26logo%3Dtrue)](https://localazy.com/p/element-web)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=element-web)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=coverage)](https://sonarcloud.io/summary/new_code?id=element-web)
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=element-web)
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=bugs)](https://sonarcloud.io/summary/new_code?id=element-web)
Vector is a Matrix web client built using the Matrix React SDK (https://github.com/matrix-org/matrix-react-sdk).
> **ThreadNet-Web**: this is a fork of Element Web, customized for the self-hosted
> [axion1337.chat](https://axion1337.chat) Matrix homeserver. See
> [docs/axion1337-fork.md](docs/axion1337-fork.md) for everything this fork changes versus
> upstream (Discord-style room list, client-side ClamAV content scanning, build fixes). The
> rest of this README describes upstream Element Web and is intentionally left as-is.
Getting Started
===============
# Element
The easiest way to test Vector is to just use the hosted copy at https://vector.im/beta.
The develop branch is continuously deployed by Jenkins at https://vector.im/develop for
those who like living dangerously.
Element (formerly known as Vector and Riot) is a Matrix web & desktop client built using the [Matrix
JS SDK](https://github.com/matrix-org/matrix-js-sdk).
To host your own copy of Vector, the quickest bet is to use a pre-built released version
of Vector:
# Supported Environments
1. Download the latest version from https://vector.im/packages/
1. Untar the tarball on your web server
1. Move (or symlink) the vector-x.x.x directory to an appropriate name
1. If desired, copy `config.sample.json` to `config.json` and edit it
as desired. See below for details.
1. Enter the URL into your browser and log into vector!
Element has several tiers of support for different environments:
Building From Source
====================
- Supported
- Definition:
- Issues **actively triaged**, regressions **block** the release
- Last 2 major versions of Chrome, Firefox, and Edge on desktop OSes
- Last 2 versions of Safari
- Latest release of official Element Desktop app on desktop OSes
- Desktop OSes means macOS, Windows, and Linux versions for desktop devices
that are actively supported by the OS vendor and receive security updates
- Best effort
- Definition:
- Issues **accepted**, regressions **do not block** the release
- The wider Element Products (including Element Call and the Enterprise Server Suite) do still not officially support these browsers.
- The element web project and its contributors should keep the client functioning and gracefully degrade where other sibling features (E.g. Element Call) may not function.
- Last major release of Firefox ESR and Chrome/Edge Extended Stable
- Community Supported
- Definition:
- Issues **accepted**, regressions **do not block** the release
- Community contributions are welcome to support these issues
- Mobile web for current stable version of Chrome, Firefox, and Safari on Android, iOS, and iPadOS
- Not supported
- Definition: Issues only affecting unsupported environments are **closed**
- Everything else
Vector is a modular webapp built with modern ES6 and requires a npm build system to build.
The period of support for these tiers should last until the releases specified above, plus 1 app release cycle(2 weeks). In the case of Firefox ESR this is extended further to allow it land in Debian Stable.
1. Install or update `node.js` so that your `npm` is at least at version `2.0.0`
1. Clone the repo: `git clone https://github.com/vector-im/vector-web.git`
1. Switch to the vector directory: `cd vector-web`
1. Install the prerequisites: `npm install`
1. If you are using the `develop` branch of vector, you will probably need to
rebuild one of the dependencies, due to https://github.com/npm/npm/issues/3055:
`(cd node_modules/matrix-react-sdk && npm install)`
1. Configure the app by copying `config.sample.json` to `config.json` and modifying
it (see below for details)
1. `npm run package` to build a tarball to deploy. Untaring this file will give
a version-specific directory containing all the files that need to go on your
web server.
For accessing Element on an Android or iOS device, we currently recommend the
native apps [element-x-android](https://github.com/element-hq/element-x-android)
and [element-x-ios](https://github.com/element-hq/element-x-ios).
Note that `npm run package` is not supported on Windows, so Windows users can run `npm
run build`, which will build all the necessary files into the `vector`
directory. The version of Vector will not appear in Settings without
using the package script. You can then mount the vector directory on your
webserver to actually serve up the app, which is entirely static content.
# Getting Started
config.json
===========
The easiest way to test Element is to just use the hosted copy at <https://app.element.io>.
The `develop` branch is continuously deployed to <https://develop.element.io>
for those who like living dangerously.
You can configure the app by copying `vector/config.sample.json` to
`vector/config.json` and customising it:
To host your own instance of Element see [Installing Element Web](docs/install.md).
1. `default_hs_url` is the default home server url.
1. `default_is_url` is the default identity server url (this is the server used
for verifying third party identifiers like email addresses). If this is blank,
registering with an email address, adding an email address to your account,
or inviting users via email address will not work. Matrix identity servers are
very simple web services which map third party identifiers (currently only email
addresses) to matrix IDs: see http://matrix.org/docs/spec/identity_service/unstable.html
for more details. Currently the only public matrix identity servers are https://matrix.org
and https://vector.im. In future identity servers will be decentralised.
To install Element as a desktop application, see [Running as a desktop app](#running-as-a-desktop-app) below.
---
Running as a Desktop app
========================
# Monorepo
In future we'll do an official distribution of Vector as an desktop app. Meanwhile,
there are a few options:
This repository is a monorepo hosting Element Web and other related projects in various subdirectories.
You can read more about the structure [here](docs/monorepo.md).
@asdf:matrix.org points out that you can use nativefier and it just works(tm):
# Element Web
```
sudo npm install nativefier -g
nativefier https://vector.im/beta/
```
To learn more about Element Web [click here](apps/web/README.md)
krisa has a dedicated electron project at https://github.com/krisak/vector-electron-desktop
(although you should swap out the 'vector' folder for the latest vector tarball you want to run)
# Running as a Desktop app
There's also a (much) older electron distribution at https://github.com/stevenhammerton/vector-desktop
Element can also be run as a desktop app, wrapped in Electron. You can download a
pre-built version from <https://element.io/get-started> or, if you prefer,
build it yourself.
To build it yourself, follow the instructions at <https://github.com/element-hq/element-web/tree/develop/apps/desktop>.
Development
===========
Many thanks to @aviraldg for the initial work on the Electron integration.
Before attempting to develop on Vector you **must** read the developer guide
for `matrix-react-sdk` at https://github.com/matrix-org/matrix-react-sdk, which
also defines the design, architecture and style for Vector too.
The [configuration docs](docs/config.md#desktop-app-configuration) show how to override the desktop app's default settings if desired.
The idea of Vector is to be a relatively lightweight "skin" of customisations on
top of the underlying `matrix-react-sdk`. `matrix-react-sdk` provides both the
higher and lower level React components useful for building Matrix communication
apps using React.
# Development
After creating a new component you must run `npm run reskindex` to regenerate
the `component-index.js` for the app (used in future for skinning)
Please read through the following:
**However, as of July 2016 this layering abstraction is broken due to rapid
development on Vector forcing `matrix-react-sdk` to move fast at the expense of
maintaining a clear abstraction between the two.** Hacking on Vector inevitably
means hacking equally on `matrix-react-sdk`, and there are bits of
`matrix-react-sdk` behaviour incorrectly residing in the `vector-web` project
(e.g. matrix-react-sdk specific CSS), and a bunch of Vector specific behaviour
in the `matrix-react-sdk` (grep for Vector). This separation problem will be
solved asap once development on Vector (and thus matrix-react-sdk) has
stabilised. Until then, the two projects should basically be considered as a
single unit. In particular, `matrix-react-sdk` issues are currently filed
against `vector-web` in github.
1. [Developer guide](./developer_guide.md)
2. [Code style](./code_style.md)
3. [Contribution guide](./CONTRIBUTING.md)
Please note that Vector is intended to run correctly without access to the public
internet. So please don't depend on resources (JS libs, CSS, images, fonts)
hosted by external CDNs or servers but instead please package all dependencies
into Vector itself.
# Translations
Setting up a dev environment
============================
To add a new translation, head to the [translating doc](docs/translating.md).
Much of the functionality in Vector is actually in the `matrix-react-sdk` and
`matrix-js-sdk` modules. It is possible to set these up in a way that makes it
easy to track the `develop` branches in git and to make local changes without
having to manually rebuild each time.
For a developer guide, see the [translating dev doc](docs/translating-dev.md).
First clone and build `matrix-js-sdk`:
# Triaging issues
1. `git clone git@github.com:matrix-org/matrix-js-sdk.git`
1. `pushd matrix-js-sdk`
1. `git checkout develop`
1. `npm install`
1. `npm install source-map-loader` # because webpack is made of fail (https://github.com/webpack/webpack/issues/1472)
1. `popd`
Issues are triaged by community members and the Web App Team, following the [triage process](https://github.com/element-hq/element-meta/wiki/Triage-process).
Then similarly with `matrix-react-sdk`:
We use [issue labels](https://github.com/element-hq/element-meta/wiki/Issue-labelling) to sort all incoming issues.
1. `git clone git@github.com:matrix-org/matrix-react-sdk.git`
1. `pushd matrix-react-sdk`
1. `git checkout develop`
1. `npm install`
1. `rm -r node_modules/matrix-js-sdk; ln -s ../../matrix-js-sdk node_modules/`
1. `popd`
## Copyright & License
Finally, build and start vector itself:
Copyright (c) 2014-2017 OpenMarket Ltd
Copyright (c) 2017 Vector Creations Ltd
Copyright (c) 2017-2025 New Vector Ltd
1. `git clone git@github.com:vector-im/vector-web.git`
1. `cd vector-web`
1. `git checkout develop`
1. `npm install`
1. `rm -r node_modules/matrix-js-sdk; ln -s ../../matrix-js-sdk node_modules/`
1. `rm -r node_modules/matrix-react-sdk; ln -s ../../matrix-react-sdk node_modules/`
1. `npm start`
1. Wait a few seconds for the initial build to finish; you should see something like:
This software is multi licensed by New Vector Ltd (Element). It can be used either:
```
Hash: b0af76309dd56d7275c8
Version: webpack 1.12.14
Time: 14533ms
Asset Size Chunks Chunk Names
bundle.js 4.2 MB 0 [emitted] main
bundle.css 91.5 kB 0 [emitted] main
bundle.js.map 5.29 MB 0 [emitted] main
bundle.css.map 116 kB 0 [emitted] main
+ 1013 hidden modules
```
Remember, the command will not terminate since it runs the web server
and rebuilds source files when they change. This development server also
disables caching, so do NOT use it in production.
1. Open http://127.0.0.1:8080/ in your browser to see your newly built Vector.
(1) for free under the terms of the GNU Affero General Public License (as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version); OR
When you make changes to `matrix-react-sdk`, you will need to run `npm run
build` in the relevant directory. You can do this automatically by instead
running `npm start` in the directory, to start a development builder which
will watch for changes to the files and rebuild automatically.
(2) for free under the terms of the GNU General Public License (as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version); OR
If you add or remove any components from the Vector skin, you will need to rebuild
the skin's index by running, `npm run reskindex`.
(3) under the terms of a paid-for Element Commercial License agreement between you and Element (the terms of which may vary depending on what you and Element have agreed to).
Unless required by applicable law or agreed to in writing, software distributed under the Licenses is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Licenses for the specific language governing permissions and limitations under the Licenses.
Filing issues
=============
All issues for Vector-web and Matrix-react-sdk should be filed at
https://github.com/matrix-org/matrix-react-sdk/issues
Triaging issues
===============
Issues will be triaged by the core team using the following primary set of tags:
priority:
P1: top priority; typically blocks releases.
P2: one below that
P3: non-urgent
P4/P5: bluesky some day, who knows.
bug or feature:
bug severity:
* cosmetic - feature works functionally but UI/UX is broken.
* critical - whole app doesn't work
* major - entire feature doesn't work
* minor - partially broken feature (but still usable)
* release blocker
* ui/ux (think of this as cosmetic)
* network (specific to network conditions)
* platform (platform specific)
Enabling encryption
===================
End-to-end encryption in Vector and Matrix is not yet considered ready for
day-to-day use; it is experimental and should be considered only as a
proof-of-concept. See https://matrix.org/jira/browse/SPEC-162 for an overview
of the current progress.
Vector is built with support for end-to-end encryption by default.
To enable encryption for a room, type
```
/encrypt on
```
in the message bar in that room. Vector will then generate a set of keys, and
encrypt all outgoing messages in that room. (Note that other people in that
room will send messages in the clear unless they also `/encrypt on`.)
Note that historical encrypted messages cannot currently be decoded - history
is therefore lost when the page is reloaded.
There is currently no visual indication of whether encryption is enabled for a
room.
Please contact [licensing@element.io](mailto:licensing@element.io) to purchase
an Element commercial license for this software.
+97
View File
@@ -0,0 +1,97 @@
module.exports = {
plugins: ["matrix-org", "n"],
extends: ["plugin:matrix-org/javascript"],
parserOptions: {
ecmaVersion: 2021,
project: ["tsconfig.json"],
},
env: {
es6: true,
node: true,
// we also have some browser code (ie. the preload script)
browser: true,
},
// NOTE: These rules are frozen and new rules should not be added here.
// New changes belong in https://github.com/matrix-org/eslint-plugin-matrix-org/
rules: {
"quotes": "off",
"indent": "off",
"prefer-promise-reject-errors": "off",
"no-async-promise-executor": "off",
"n/file-extension-in-import": ["error", "always"],
"unicorn/prefer-node-protocol": ["error"],
},
overrides: [
{
files: ["src/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
{
files: ["hak/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
parserOptions: {
project: ["hak/tsconfig.json"],
},
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"n/file-extension-in-import": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
{
files: ["scripts/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
parserOptions: {
project: ["scripts/tsconfig.json"],
},
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"n/file-extension-in-import": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
{
files: ["playwright/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
parserOptions: {
project: ["playwright/tsconfig.json"],
},
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
{
files: ["src/**/*.test.ts", "electron-builder.ts", "vitest.config.ts"],
extends: ["plugin:matrix-org/typescript"],
parserOptions: {
project: ["tsconfig.node.json"],
},
},
],
};
+22
View File
@@ -0,0 +1,22 @@
/dist
/lib
/webapp
/webapp.asar
/packages
/deploys
node_modules/
/pkg/control
/.hak
/.yarnrc
/docker
/.npmrc
.vscode
.vscode/
/test_artifacts/
/coverage/
yarn-error.log
/hak/**/*.js
/scripts/hak/**/*.js
.DS_Store
/playwright-report
.pnpm-store
+4
View File
@@ -0,0 +1,4 @@
{
"*": "prettier --write --ignore-unknown",
"*.(ts|tsx)": ["eslint --fix"]
}
+1
View File
@@ -0,0 +1 @@
24.15.0
+1
View File
@@ -0,0 +1 @@
module.exports = require("eslint-plugin-matrix-org/.prettierrc.js");
File diff suppressed because it is too large Load Diff
+173
View File
@@ -0,0 +1,173 @@
![Build](https://github.com/vector-im/element-desktop/actions/workflows/build_desktop_and_deploy.yaml/badge.svg)
![Static Analysis](https://github.com/vector-im/element-desktop/actions/workflows/static_analysis.yaml/badge.svg)
[![Localazy](https://img.shields.io/endpoint?url=https%3A%2F%2Fconnect.localazy.com%2Fstatus%2Felement-web%2Fdata%3Fcontent%3Dall%26title%3Dlocalazy%26logo%3Dtrue)](https://localazy.com/p/element-web)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=element-desktop&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=element-desktop)
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=element-desktop&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=element-desktop)
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=element-desktop&metric=bugs)](https://sonarcloud.io/summary/new_code?id=element-desktop)
# Element Desktop
Element Desktop is a Matrix client for desktop platforms with Element Web at its core.
# First Steps
Before you do anything else, fetch the dependencies:
```
pnpm install
```
# Fetching Element
Since this package is just the Electron wrapper for Element Web, it doesn't contain any of the Element Web code,
so the first step is to get a working copy of Element Web. There are a few ways of doing this:
```
# Fetch the prebuilt release Element package from the element-web GitHub releases page. The version
# fetched will be the same as the local element-desktop package.
# We're explicitly asking for no config, so the packaged Element will have no config.json.
pnpm run fetch --noverify --cfgdir ""
```
...or if you'd like to use GPG to verify the downloaded package:
```
# Fetch the Element public key from the element.io web server over a secure connection and import
# it into your local GPG keychain (you'll need GPG installed). You only need to to do this
# once.
pnpm run fetch --importkey
# Fetch the package and verify the signature
pnpm run fetch --cfgdir ""
```
...or either of the above, but fetching a specific version of Element:
```
# Fetch the prebuilt release Element package from the element-web GitHub releases page. The version
# fetched will be the same as the local element-desktop package.
pnpm run fetch --noverify --cfgdir "" v1.5.6
```
If you only want to run the app locally and don't need to build packages, you can
provide the `webapp` directory directly:
```
ln -s ../web/webapp ./
```
[TODO: add support for fetching develop builds, arbitrary URLs and arbitrary paths]
# Building
## Native Build
TODO: List native pre-requisites
Optionally, [build the native modules](https://github.com/vector-im/element-desktop/blob/develop/docs/native-node-modules.md),
which include support for searching in encrypted rooms and secure storage. Skipping this step is fine, you just won't have those features.
Then, run
```
pnpm run build
```
This will do a couple of things:
- Run the `setversion` script to set the local package version to match whatever
version of Element you installed above.
- Run electron-builder to build a package. The package built will match the operating system
you're running the build process on.
## Docker
Alternatively, you can also build using docker, which will always produce the linux package:
```
# Run this once to make the docker image
pnpm run docker:setup
pnpm run docker:install
# if you want to build the native modules (this will take a while)
pnpm run docker:build:native
pnpm run docker:build
```
After running, the packages should be in `dist/`.
# Starting
If you'd just like to run the electron app locally for development:
```
pnpm start
```
# Config
If you'd like the packaged Element to have a configuration file, you can create a
config directory and place `config.json` in there, then specify this directory
with the `--cfgdir` option to `pnpm run fetch`, eg:
```
mkdir myconfig
cp /path/to/my/config.json myconfig/
pnpm run fetch --cfgdir myconfig
```
The config dir for the official Element app is in `element.io`. If you use this,
your app will auto-update itself using builds from element.io.
# Profiles
To run multiple instances of the desktop app for different accounts, you can
launch the executable with the `--profile` argument followed by a unique
identifier, e.g `element-desktop --profile Work` for it to run a separate profile and
not interfere with the default one.
Alternatively, a custom location for the profile data can be specified using the
`--profile-dir` flag followed by the desired path.
# User-specified config.json
- `%APPDATA%\$NAME\config.json` on Windows
- `$XDG_CONFIG_HOME/$NAME/config.json` or `~/.config/$NAME/config.json` on Linux
- `~/Library/Application Support/$NAME/config.json` on macOS
In the paths above, `$NAME` is typically `Element`, unless you use `--profile
$PROFILE` in which case it becomes `Element-$PROFILE`, or it is using one of
the above created by a pre-1.7 install, in which case it will be `Riot` or
`Riot-$PROFILE`.
You may also specify a different path entirely for the `config.json` file by
providing the `--config $YOUR_CONFIG_JSON_FILE` to the process, or via the
`ELEMENT_DESKTOP_CONFIG_JSON` environment variable.
# Translations
To add a new translation, head to the [translating doc](https://github.com/vector-im/element-web/blob/develop/docs/translating.md).
For a developer guide, see the [translating dev doc](https://github.com/vector-im/element-web/blob/develop/docs/translating-dev.md).
# Report bugs & give feedback
If you run into any bugs or have feedback you'd like to share, please let us know on GitHub.
To help avoid duplicate issues, please [view existing issues](https://github.com/vector-im/element-web/issues?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc) first (and add a +1) or [create a new issue](https://github.com/vector-im/element-web/issues/new/choose) if you can't find it. Please note that this issue tracker is associated with the [element-web](https://github.com/vector-im/element-web) repo, but is also applied to the code in this repo as well.
## Copyright & License
Copyright (c) 2016-2017 OpenMarket Ltd
Copyright (c) 2017 Vector Creations Ltd
Copyright (c) 2017-2025 New Vector Ltd
This software is multi licensed by New Vector Ltd (Element). It can be used either:
(1) for free under the terms of the GNU Affero General Public License (as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version); OR
(2) for free under the terms of the GNU General Public License (as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version); OR
(3) under the terms of a paid-for Element Commercial License agreement between you and Element (the terms of which may vary depending on what you and Element have agreed to).
Unless required by applicable law or agreed to in writing, software distributed under the Licenses is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Licenses for the specific language governing permissions and limitations under the Licenses.
+7
View File
@@ -0,0 +1,7 @@
{
"appId": "im.riot.app",
"name": "threadnet-desktop",
"productName": "ThreadNet",
"description": "ThreadNet — powered by Element",
"protocols": ["io.element.desktop", "element"]
}
+649
View File
@@ -0,0 +1,649 @@
{
"brand": "aXion1337.Chat",
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix.axion1337.chat",
"server_name": "axion1337.chat"
}
},
"default_theme": "aXion1337 Dark",
"element_call": {
"use_exclusively": true
},
"embedded_pages": {
"login_for_welcome": true
},
"features": {
"feature_element_call_video_rooms": true,
"feature_group_calls": true,
"feature_new_room_decoration_ui": true,
"feature_new_room_list": true,
"feature_qr_code_login": true,
"feature_video_rooms": true
},
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx",
"mobile_guide_app_variant": "element",
"setting_defaults": {
"UIFeature.deactivate": false,
"UIFeature.passwordReset": false,
"UIFeature.registration": false,
"custom_themes": [
{
"name": "aXion1337 Dark true",
"is_dark": true,
"colors": {
"accent-color": "#ffaf0f",
"primary-color": "#ffaf0f",
"secondary-color": "#ffaf0f"
}
},
{
"name": "Deep Purple",
"is_dark": true,
"colors": {
"accent-color": "#6503b3",
"primary-color": "#368bd6",
"warning-color": "#b30356",
"sidebar-color": "#15171B",
"roomlist-background-color": "#22262E",
"roomlist-text-color": "#A1B2D1",
"roomlist-text-secondary-color": "#EDF3FF",
"roomlist-highlights-color": "#343A46",
"roomlist-separator-color": "#a1b2d1",
"timeline-background-color": "#181b21",
"timeline-text-color": "#EDF3FF",
"timeline-text-secondary-color": "#A1B2D1",
"timeline-highlights-color": "#22262E"
}
},
{
"name": "Discord Dark",
"is_dark": true,
"colors": {
"accent-color": "#747ff4",
"accent": "#747ff4",
"primary-color": "#00aff4",
"warning-color": "#faa81ad9",
"alert": "#faa81ad9",
"sidebar-color": "#202225",
"roomlist-background-color": "#2f3136",
"roomlist-text-color": "#dcddde",
"roomlist-text-secondary-color": "#8e9297",
"roomlist-highlights-color": "#4f545c52",
"roomlist-separator-color": "#40444b",
"timeline-background-color": "#36393f",
"timeline-text-color": "#dcddde",
"secondary-content": "#dcddde",
"tertiary-content": "#dcddde",
"timeline-text-secondary-color": "#b9bbbe",
"timeline-highlights-color": "#04040512",
"reaction-row-button-selected-bg-color": "#4752c4",
"menu-selected-color": "#4752c4",
"focus-bg-color": "#4752c4",
"room-highlight-color": "#4752c4",
"other-user-pill-bg-color": "#4752c4",
"togglesw-off-color": "#72767d"
},
"compound": {
"--cpd-color-theme-bg": "#0019ff",
"--cpd-color-bg-canvas-default": "#2f3136",
"--cpd-color-bg-subtle-secondary": "#2f3136",
"--cpd-color-bg-subtle-primary": "#4f545c52",
"--cpd-color-bg-action-primary-rest": "#dcddde",
"--cpd-color-bg-action-secondary-rest": "#2f3136",
"--cpd-color-bg-critical-primary": "#fd3f3c",
"--cpd-color-bg-critical-subtle": "#745862",
"--cpd-color-bg-critical-hovered": "#fd3f3c",
"--cpd-color-bg-accent-rest": "#4cb387",
"--cpd-color-text-primary": "#dcddde",
"--cpd-color-text-secondary": "#b9bbbe",
"--cpd-color-text-action-accent": "#b9bbbe",
"--cpd-color-text-critical-primary": "#fd3f3c",
"--cpd-color-text-success-primary": "#4cb387",
"--cpd-color-icon-primary": "#dcddde",
"--cpd-color-icon-secondary": "#dcddde",
"--cpd-color-icon-tertiary": "#a7a0a7",
"--cpd-color-icon-accent-tertiary": "#4cb387",
"--cpd-color-border-interactive-primary": "#5d6064",
"--cpd-color-border-interactive-secondary": "#5d6064",
"--cpd-color-border-critical-primary": "#fd3f3c",
"--cpd-color-border-success-subtle": "#4cb387"
}
},
{
"name": "Electric Blue",
"is_dark": false,
"colors": {
"accent-color": "#3596fc",
"primary-color": "#368bd6",
"warning-color": "#ff4b55",
"sidebar-color": "#27303a",
"roomlist-background-color": "#f3f8fd",
"roomlist-text-color": "#2e2f32",
"roomlist-text-secondary-color": "#61708b",
"roomlist-highlights-color": "#ffffff",
"roomlist-separator-color": "#e3e8f0",
"timeline-background-color": "#ffffff",
"timeline-text-color": "#2e2f32",
"timeline-text-secondary-color": "#61708b",
"timeline-highlights-color": "#f3f8fd",
"username-colors": [
"#ff0000",
"#ff7f00",
"#ffff00",
"#00ff00",
"#0000ff",
"#4b0082",
"#9400d3",
"#ff1493"
],
"avatar-background-colors": [
"#cc0000",
"#cc6600",
"#cccc00",
"#00cc00",
"#0000cc",
"#3b0066",
"#7a00b3",
"#cc1077"
]
},
"compound": {
"--cpd-color-icon-accent-tertiary": "var(--cpd-color-blue-800)",
"--cpd-color-text-action-accent": "var(--cpd-color-blue-900)"
}
},
{
"name": "Everforest dark hard",
"is_dark": true,
"colors": {
"accent-color": "#a7c080",
"primary-color": "#a7c080",
"warning-color": "#e67e80",
"sidebar-color": "#323d43",
"roomlist-background-color": "#2f383e",
"roomlist-text-color": "#d3c6aa",
"roomlist-text-secondary-color": "#d3c6aa",
"roomlist-highlights-color": "#4b565c",
"roomlist-separator-color": "#4b565c",
"timeline-background-color": "#2b3339",
"timeline-text-color": "#d3c6aa",
"secondary-content": "#d3c6aa",
"tertiary-content": "#d3c6aa",
"timeline-text-secondary-color": "#a7c080",
"timeline-highlights-color": "#4b565c",
"reaction-row-button-selected-bg-color": "#4b565c"
}
},
{
"name": "aXion1337 Dark",
"is_dark": true,
"colors": {
"accent-color": "#bd93f9",
"primary-color": "#fe8019",
"warning-color": "#fb4934",
"sidebar-color": "#282828",
"roomlist-background-color": "#1d2021",
"roomlist-text-color": "#a89984",
"roomlist-text-secondary-color": "#00ff00",
"roomlist-highlights-color": "#00000030",
"roomlist-separator-color": "#4d4d4d90",
"timeline-background-color": "#282828",
"timeline-text-color": "#ebdbb2",
"secondary-content": "#928374",
"tertiary-content": "#928374",
"quinary-content": "#504945",
"timeline-text-secondary-color": "#a89984",
"timeline-highlights-color": "#00000030",
"reaction-row-button-selected-bg-color": "#689d6a",
"menu-selected-color": "#504945",
"icon-button-color": "#928374",
"accent": "#689d6a",
"alert": "#cc241d",
"username-colors": [
"#cc241d",
"#98971a",
"#d79921",
"#458588",
"#b16286",
"#689d6a",
"#a89984",
"#d65d0e"
]
}
},
{
"name": "aXion1337 Light",
"is_dark": false,
"colors": {
"accent-color": "#8f3f71",
"primary-color": "#af3a03",
"warning-color": "#9d0006",
"sidebar-color": "#ebdbb2",
"roomlist-background-color": "#f2e5bc",
"roomlist-text-color": "#665c54",
"roomlist-text-secondary-color": "#427b58",
"roomlist-highlights-color": "#00000012",
"roomlist-separator-color": "#bdae9330",
"timeline-background-color": "#fbf1c7",
"timeline-text-color": "#3c3836",
"secondary-content": "#7c6f64",
"tertiary-content": "#7c6f64",
"quinary-content": "#d5c4a1",
"timeline-text-secondary-color": "#665c54",
"timeline-highlights-color": "#00000012",
"reaction-row-button-selected-bg-color": "#8ec07c",
"menu-selected-color": "#d5c4a1",
"icon-button-color": "#7c6f64",
"accent": "#427b58",
"alert": "#9d0006",
"username-colors": [
"#9d0006",
"#79740e",
"#b57614",
"#076678",
"#8f3f71",
"#427b58",
"#665c54",
"#af3a03"
]
}
},
{
"name": "Ocean Depths",
"is_dark": false,
"colors": {
"accent-color": "#2d8b8b",
"accent": "#2d8b8b",
"primary-color": "#a8dadc",
"warning-color": "#457b9d",
"alert": "#70555a",
"sidebar-color": "#e3ebe0",
"roomlist-background-color": "#eaf2e7",
"roomlist-text-color": "#1a2332",
"roomlist-text-secondary-color": "#656e74",
"roomlist-highlights-color": "#00000010",
"roomlist-separator-color": "#0000001f",
"timeline-background-color": "#f1faee",
"timeline-text-color": "#1a2332",
"secondary-content": "#656e74",
"tertiary-content": "#656e74",
"timeline-text-secondary-color": "#656e74",
"timeline-highlights-color": "#00000010",
"reaction-row-button-selected-bg-color": "#99c8c1",
"menu-selected-color": "#b6d9d0",
"focus-bg-color": "#b6d9d0",
"room-highlight-color": "#b6d9d0",
"other-user-pill-bg-color": "#d4ede7",
"icon-button-color": "#656e74",
"username-colors": [
"#2d8b8b",
"#a8dadc",
"#457b9d",
"#276c70",
"#7da3a9",
"#365c78",
"#6ab2b4",
"#76aabc"
]
}
},
{
"name": "Sunset Boulevard",
"is_dark": true,
"colors": {
"accent-color": "#e76f51",
"accent": "#e76f51",
"primary-color": "#f4a261",
"warning-color": "#e9c46a",
"alert": "#d6453a",
"sidebar-color": "#1b323c",
"roomlist-background-color": "#213c47",
"roomlist-text-color": "#f6efe6",
"roomlist-text-secondary-color": "#adb4b3",
"roomlist-highlights-color": "#ffffff14",
"roomlist-separator-color": "#ffffff26",
"timeline-background-color": "#264653",
"timeline-text-color": "#f6efe6",
"secondary-content": "#adb4b3",
"tertiary-content": "#adb4b3",
"timeline-text-secondary-color": "#adb4b3",
"timeline-highlights-color": "#ffffff14",
"reaction-row-button-selected-bg-color": "#7d5852",
"menu-selected-color": "#605252",
"focus-bg-color": "#605252",
"room-highlight-color": "#605252",
"other-user-pill-bg-color": "#786b59",
"icon-button-color": "#adb4b3",
"username-colors": [
"#e76f51",
"#f4a261",
"#e9c46a",
"#ec957e",
"#f5b989",
"#eed395",
"#ee8859",
"#eeb366"
]
}
},
{
"name": "Forest Canopy",
"is_dark": false,
"colors": {
"accent-color": "#2d4a2b",
"accent": "#2d4a2b",
"primary-color": "#7d8471",
"warning-color": "#a4ac86",
"alert": "#703126",
"sidebar-color": "#ebeae7",
"roomlist-background-color": "#f2f2ef",
"roomlist-text-color": "#22301f",
"roomlist-text-secondary-color": "#6e766a",
"roomlist-highlights-color": "#00000010",
"roomlist-separator-color": "#0000001f",
"timeline-background-color": "#faf9f6",
"timeline-text-color": "#22301f",
"secondary-content": "#6e766a",
"tertiary-content": "#6e766a",
"timeline-text-secondary-color": "#6e766a",
"timeline-highlights-color": "#00000010",
"reaction-row-button-selected-bg-color": "#9eaa9b",
"menu-selected-color": "#bcc4b9",
"focus-bg-color": "#bcc4b9",
"room-highlight-color": "#bcc4b9",
"other-user-pill-bg-color": "#c8cac1",
"icon-button-color": "#6e766a",
"username-colors": [
"#2d4a2b",
"#7d8471",
"#a4ac86",
"#2a4227",
"#626b58",
"#768162",
"#55674e",
"#90987c"
]
}
},
{
"name": "Modern Minimalist",
"is_dark": false,
"colors": {
"accent-color": "#36454f",
"accent": "#36454f",
"primary-color": "#708090",
"warning-color": "#d3d3d3",
"alert": "#752e39",
"sidebar-color": "#f0f0f0",
"roomlist-background-color": "#f7f7f7",
"roomlist-text-color": "#1c252b",
"roomlist-text-secondary-color": "#6b7175",
"roomlist-highlights-color": "#00000010",
"roomlist-separator-color": "#0000001f",
"timeline-background-color": "#ffffff",
"timeline-text-color": "#1c252b",
"secondary-content": "#6b7175",
"tertiary-content": "#6b7175",
"timeline-text-secondary-color": "#6b7175",
"timeline-highlights-color": "#00000010",
"reaction-row-button-selected-bg-color": "#a5abb0",
"menu-selected-color": "#c3c7ca",
"focus-bg-color": "#c3c7ca",
"room-highlight-color": "#c3c7ca",
"other-user-pill-bg-color": "#c6ccd3",
"icon-button-color": "#6b7175",
"username-colors": [
"#36454f",
"#708090",
"#d3d3d3",
"#2e3b44",
"#576572",
"#939698",
"#536270",
"#a2aab2"
]
}
},
{
"name": "Golden Hour",
"is_dark": true,
"colors": {
"accent-color": "#f4a900",
"accent": "#f4a900",
"primary-color": "#c1666b",
"warning-color": "#d4b896",
"alert": "#dd650e",
"sidebar-color": "#352e2a",
"roomlist-background-color": "#403732",
"roomlist-text-color": "#f7f0e6",
"roomlist-text-secondary-color": "#bab2aa",
"roomlist-highlights-color": "#ffffff14",
"roomlist-separator-color": "#ffffff26",
"timeline-background-color": "#4a403a",
"timeline-text-color": "#f7f0e6",
"secondary-content": "#bab2aa",
"tertiary-content": "#bab2aa",
"timeline-text-secondary-color": "#bab2aa",
"timeline-highlights-color": "#ffffff14",
"reaction-row-button-selected-bg-color": "#966f20",
"menu-selected-color": "#7d6029",
"focus-bg-color": "#7d6029",
"room-highlight-color": "#7d6029",
"other-user-pill-bg-color": "#7a4f4e",
"icon-button-color": "#bab2aa",
"username-colors": [
"#f4a900",
"#c1666b",
"#d4b896",
"#f5be45",
"#d18f90",
"#e0ccb2",
"#da8836",
"#ca8f80"
]
}
},
{
"name": "Arctic Frost",
"is_dark": false,
"colors": {
"accent-color": "#4a6fa5",
"accent": "#4a6fa5",
"primary-color": "#d4e4f7",
"warning-color": "#c0c0c0",
"alert": "#804569",
"sidebar-color": "#ebebeb",
"roomlist-background-color": "#f2f2f2",
"roomlist-text-color": "#1e2c40",
"roomlist-text-secondary-color": "#6b7481",
"roomlist-highlights-color": "#00000010",
"roomlist-separator-color": "#0000001f",
"timeline-background-color": "#fafafa",
"timeline-text-color": "#1e2c40",
"secondary-content": "#6b7481",
"tertiary-content": "#6b7481",
"timeline-text-secondary-color": "#6b7481",
"timeline-highlights-color": "#00000010",
"reaction-row-button-selected-bg-color": "#abbbd4",
"menu-selected-color": "#c5d0e0",
"focus-bg-color": "#c5d0e0",
"room-highlight-color": "#c5d0e0",
"other-user-pill-bg-color": "#ebf1f9",
"icon-button-color": "#6b7481",
"username-colors": [
"#4a6fa5",
"#d4e4f7",
"#c0c0c0",
"#3d5b87",
"#9dadc0",
"#878c93",
"#8faace",
"#cad2dc"
]
}
},
{
"name": "Desert Rose",
"is_dark": true,
"colors": {
"accent-color": "#d4a5a5",
"accent": "#d4a5a5",
"primary-color": "#b87d6d",
"warning-color": "#e8d5c4",
"alert": "#cb6369",
"sidebar-color": "#432132",
"roomlist-background-color": "#50283c",
"roomlist-text-color": "#f6ece4",
"roomlist-text-secondary-color": "#c0aaad",
"roomlist-highlights-color": "#ffffff14",
"roomlist-separator-color": "#ffffff26",
"timeline-background-color": "#5d2e46",
"timeline-text-color": "#f6ece4",
"secondary-content": "#c0aaad",
"tertiary-content": "#c0aaad",
"timeline-text-secondary-color": "#c0aaad",
"timeline-highlights-color": "#ffffff14",
"reaction-row-button-selected-bg-color": "#936471",
"menu-selected-color": "#815262",
"focus-bg-color": "#815262",
"room-highlight-color": "#815262",
"other-user-pill-bg-color": "#814e56",
"icon-button-color": "#c0aaad",
"username-colors": [
"#d4a5a5",
"#b87d6d",
"#e8d5c4",
"#debab8",
"#cb9e91",
"#edddcf",
"#c69189",
"#d0a998"
]
}
},
{
"name": "Tech Innovation",
"is_dark": false,
"colors": {
"accent-color": "#0066ff",
"accent": "#0066ff",
"primary-color": "#00ffff",
"warning-color": "#1e1e1e",
"alert": "#57409a",
"sidebar-color": "#f0f0f0",
"roomlist-background-color": "#f7f7f7",
"roomlist-text-color": "#1e1e1e",
"roomlist-text-secondary-color": "#6d6d6d",
"roomlist-highlights-color": "#00000010",
"roomlist-separator-color": "#0000001f",
"timeline-background-color": "#ffffff",
"timeline-text-color": "#1e1e1e",
"secondary-content": "#6d6d6d",
"tertiary-content": "#6d6d6d",
"timeline-text-secondary-color": "#6d6d6d",
"timeline-highlights-color": "#00000010",
"reaction-row-button-selected-bg-color": "#8cbaff",
"menu-selected-color": "#b2d1ff",
"focus-bg-color": "#b2d1ff",
"room-highlight-color": "#b2d1ff",
"other-user-pill-bg-color": "#99ffff",
"icon-button-color": "#6d6d6d",
"username-colors": [
"#0066ff",
"#00ffff",
"#1e1e1e",
"#0950bc",
"#09bcbc",
"#1e1e1e",
"#00b2ff",
"#0f8e8e"
]
}
},
{
"name": "Botanical Garden",
"is_dark": false,
"colors": {
"accent-color": "#4a7c59",
"accent": "#4a7c59",
"primary-color": "#f9a620",
"warning-color": "#b7472a",
"alert": "#804c3f",
"sidebar-color": "#e6e4df",
"roomlist-background-color": "#eeece6",
"roomlist-text-color": "#22331f",
"roomlist-text-secondary-color": "#6c7667",
"roomlist-highlights-color": "#00000010",
"roomlist-separator-color": "#0000001f",
"timeline-background-color": "#f5f3ed",
"timeline-text-color": "#22331f",
"secondary-content": "#6c7667",
"tertiary-content": "#6c7667",
"timeline-text-secondary-color": "#6c7667",
"timeline-highlights-color": "#00000010",
"reaction-row-button-selected-bg-color": "#a8bdaa",
"menu-selected-color": "#c2cfc1",
"focus-bg-color": "#c2cfc1",
"room-highlight-color": "#c2cfc1",
"other-user-pill-bg-color": "#f7d49b",
"icon-button-color": "#6c7667",
"username-colors": [
"#4a7c59",
"#f9a620",
"#b7472a",
"#3e6648",
"#b88420",
"#834026",
"#a2913c",
"#d87625"
]
}
},
{
"name": "Midnight Galaxy",
"is_dark": false,
"colors": {
"accent-color": "#2b1e3e",
"accent": "#2b1e3e",
"primary-color": "#4a4e8f",
"warning-color": "#a490c2",
"alert": "#6e1930",
"sidebar-color": "#d8d8eb",
"roomlist-background-color": "#dfdff2",
"roomlist-text-color": "#241a34",
"roomlist-text-secondary-color": "#686179",
"roomlist-highlights-color": "#00000010",
"roomlist-separator-color": "#0000001f",
"timeline-background-color": "#e6e6fa",
"timeline-text-color": "#241a34",
"secondary-content": "#686179",
"tertiary-content": "#686179",
"timeline-text-secondary-color": "#686179",
"timeline-highlights-color": "#00000010",
"reaction-row-button-selected-bg-color": "#928ca5",
"menu-selected-color": "#aeaac2",
"focus-bg-color": "#aeaac2",
"room-highlight-color": "#aeaac2",
"other-user-pill-bg-color": "#a8a9cf",
"icon-button-color": "#686179",
"username-colors": [
"#2b1e3e",
"#4a4e8f",
"#a490c2",
"#291d3b",
"#3f3e74",
"#776790",
"#3a3666",
"#776fa8"
]
}
}
],
"feature_group_calls": true
},
"show_labs_settings": true,
"sso_redirect_options": {
"immediate": false
}
}
@@ -0,0 +1,52 @@
# Laedt die Build-Artefakte resumefaehig vor, die app-builder sonst selbst (ohne
# Resume) von GitHub laedt: das CDN (185.199.109.x) reisst im Lab-Gast groessere
# Transfers reproduzierbar mitten im Stream ab (Jobs 415/416/424, wsarecv-Reset).
# curl -C - setzt nach jedem Abriss am letzten Byte fort; einmal geladen liegen
# die Artefakte in den persistenten Caches (ELECTRON_CACHE/ELECTRON_BUILDER_CACHE)
# und werden nie erneut geholt.
$ErrorActionPreference = 'Stop'
function Get-Resumable([string]$Url, [string]$Out) {
foreach ($i in 1..8) {
& curl.exe -sSL -C - -o $Out $Url
if ($LASTEXITCODE -eq 0) { return }
Start-Sleep 5
}
throw "Download nach 8 Versuchen gescheitert: $Url"
}
# --- 1. Electron-Binary -> ELECTRON_CACHE ------------------------------------
$pkg = Join-Path $PSScriptRoot '..\package.json'
$ev = (& node -p "require(process.argv[1]).devDependencies.electron" $pkg) -replace '[\^~]', ''
New-Item -ItemType Directory -Force $env:ELECTRON_CACHE | Out-Null
$zip = Join-Path $env:ELECTRON_CACHE "electron-v$ev-win32-x64.zip"
if (-not (Test-Path $zip)) {
Get-Resumable "https://github.com/electron/electron/releases/download/v$ev/electron-v$ev-win32-x64.zip" "$zip.part"
Move-Item -Force "$zip.part" $zip
}
# --- 2. electron-builder-Werkzeuge -> ELECTRON_BUILDER_CACHE -----------------
# Zielstruktur laut app-builder-Quellcode (artifactDownloader.go) + electron-builder
# 26.9.1 (binDownload.js): der Cache-Schluessel ist "<release>-<dateiname-ohne-ext>",
# also GEDOPPELT (z.B. nsis-3.0.4.1-nsis-3.0.4.1), und liegt unter dem Teil des
# Namens VOR dem ersten Bindestrich als Unterverzeichnis - nsis-resources landet
# deshalb ebenfalls unter nsis\. Job 431 bewies den Miss mit einfachem Namen.
$sevenZa = Join-Path $PSScriptRoot '..\..\..\node_modules\7zip-bin\win\x64\7za.exe'
function Get-EbArtifact([string]$Release, [string]$SubDir) {
$dest = Join-Path $env:ELECTRON_BUILDER_CACHE (Join-Path $SubDir "$Release-$Release")
if (Test-Path $dest) { return }
$tmp = Join-Path $env:TEMP "$Release.7z"
Get-Resumable "https://github.com/electron-userland/electron-builder-binaries/releases/download/$Release/$Release.7z" $tmp
New-Item -ItemType Directory -Force $dest | Out-Null
& $sevenZa x -y "-o$dest" $tmp | Out-Null
if ($LASTEXITCODE -ne 0) { Remove-Item -Recurse -Force $dest; throw "Entpacken gescheitert: $tmp" }
}
# Versionen passend zu electron-builder 26.9.1 (winCodeSign aus dem Job-424-Trace,
# nsis/nsis-resources samt Checksummen aus nsisUtil.js). Bei einem kuenftigen
# Mismatch laedt app-builder selbst und der Fehler nennt die richtige Version.
Get-EbArtifact 'winCodeSign-2.6.0' 'winCodeSign'
Get-EbArtifact 'nsis-3.0.4.1' 'nsis'
Get-EbArtifact 'nsis-resources-3.4.1' 'nsis'
Write-Output "prefetch ok: electron v$ev + winCodeSign/nsis in den Caches"
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
presets: [["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-typescript"],
};
+28
View File
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Entitlements from electron-builder's defaults
(https://github.com/electron-userland/electron-builder/blob/master/packages/app-builder-lib/templates/entitlements.mac.plist)
nb. This does *not* include the app sandbox: at the time of adding this file,
we were using electron-builder 21.2.0 which does not have the sandbox entitlement.
Latest electron-builder does, but it appears to be causing issues:
(https://github.com/electron-userland/electron-builder/issues/4390)
-->
<!-- https://github.com/electron/electron-notarize#prerequisites -->
<key>com.apple.security.cs.allow-jit</key>
<true/>
<!-- https://github.com/electron-userland/electron-builder/issues/3940 -->
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<!-- Our own additional entitlements (we need to access the camera and
mic for VoIP calls -->
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<true/>
</dict>
</plist>
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

+27
View File
@@ -0,0 +1,27 @@
{
"fill": "automatic",
"groups": [
{
"layers": [
{
"glass": false,
"image-name": "element.png",
"name": "element"
}
],
"name": "Figma",
"shadow": {
"kind": "none",
"opacity": 0.5
},
"specular": false,
"translucency": {
"enabled": false,
"value": 0.5
}
}
],
"supported-platforms": {
"squares": ["macOS"]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

+25
View File
@@ -0,0 +1,25 @@
# Docker image to facilitate building Element Desktop's native bits using a glibc version (2.31)
# with broader compatibility, down to Debian bullseye & Ubuntu focal.
FROM rust:bullseye@sha256:85f9d38ab80fa5752a6fd5bff34c953a59ce2c7ccb0d47fb678d3c0300b8a331
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -qq update && apt-get -y -qq dist-upgrade && \
apt-get -y -qq install --no-install-recommends \
# tclsh is required for building SQLite as part of SQLCipher
tcl \
# Used by seshat (when not SQLCIPHER_STATIC) \
libsqlcipher-dev && \
apt-get purge -y --auto-remove && rm -rf /var/lib/apt/lists/*
RUN ln -s /usr/bin/python3 /usr/bin/python & ln -s /usr/bin/pip3 /usr/bin/pip
ENV DEBUG_COLORS=true
ENV FORCE_COLOR=true
WORKDIR /project
ARG TARGETOS
ARG TARGETARCH
COPY .node-version dockerbuild/setup.sh /
RUN /setup.sh
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -x
declare -A archMap=(["amd64"]="x64" ["arm64"]="arm64")
ARCH="${archMap["$TARGETARCH"]}"
# The .node-version file generally doesn't have the 'v' (renovate does not put the 'v' and will
# strip it on upgrade if it's there) but the 'v' is also widely supported so we probably ought
# to just work either way.
NODE_VERSION=$(cat /.node-version | sed -e 's/^v//')
curl --proto "=https" -L "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-$TARGETOS-$ARCH.tar.gz" | tar xz -C /usr/local --strip-components=1 && \
unlink /usr/local/CHANGELOG.md && unlink /usr/local/LICENSE && unlink /usr/local/README.md
corepack enable
+235
View File
@@ -0,0 +1,235 @@
import * as os from "node:os";
import * as fs from "node:fs";
import * as path from "node:path";
import { type Configuration as BaseConfiguration } from "electron-builder";
/**
* This script has different outputs depending on your os platform.
*
* On Windows:
* Passes $ED_SIGNTOOL_THUMBPRINT and $ED_SIGNTOOL_SUBJECT_NAME to
* build.win.signtoolOptions.signingHashAlgorithms and build.win.signtoolOptions.certificateSubjectName respectively if specified.
*
* On Linux:
* Replaces spaces in the product name with dashes as spaces in paths can cause issues
* Removes libsqlcipher0 recommended dependency if env SQLCIPHER_BUNDLED is asserted.
* Passes $ED_DEBIAN_CHANGELOG to build.deb.fpm if specified
*/
/**
* Interface describing relevant fields of the package.json file.
*/
interface Pkg {
version: string;
}
/**
* Base metadata fields, used in both package.json and the variant configuration.
*/
interface Metadata {
name: string;
productName: string;
description: string;
}
/**
* Extra metadata fields that are injected into the build to pass to the app at runtime.
*/
interface ExtraMetadata extends Metadata {
electron_appId: string;
electron_protocol: string;
electron_windows_cert_sn?: string;
}
/**
* Interface describing the variant configuration format.
*/
interface Variant extends Metadata {
"appId": string;
"linux.executableName"?: string;
"linux.deb.name"?: string;
"protocols": string[];
}
type Writable<T> = NonNullable<
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
T extends Function ? T : T extends object ? { -readonly [K in keyof T]: Writable<T[K]> } : T
>;
// Load the default variant as a base configuration
const DEFAULT_VARIANT = path.join("element.io", "release", "build.json");
let variant: Variant = JSON.parse(fs.readFileSync(DEFAULT_VARIANT, "utf8"));
/**
* If a variant is specified, we will use it to override the build-specific values.
* This allows us to have different builds for different purposes (e.g. stable, nightly).
*/
if (process.env.VARIANT_PATH) {
console.log(`Using variant configuration from '${process.env.VARIANT_PATH}':`);
variant = {
...variant,
...JSON.parse(fs.readFileSync(`${process.env.VARIANT_PATH}`, "utf8")),
};
} else {
console.warn(`No VARIANT_PATH specified, using default variant configuration '${DEFAULT_VARIANT}':`);
}
for (const key in variant) {
console.log(`${key}: ${variant[key as keyof Variant]}`);
}
interface Configuration extends BaseConfiguration {
extraMetadata: Partial<Pick<Pkg, "version">> & ExtraMetadata;
linux: BaseConfiguration["linux"];
win: BaseConfiguration["win"];
mac: BaseConfiguration["mac"];
deb: {
fpm: string[];
} & BaseConfiguration["deb"];
}
/**
* @type {import('electron-builder').Configuration}
* @see https://www.electron.build/configuration/configuration
*/
const config: Omit<Writable<Configuration>, "electronFuses"> & {
// Make all fuses required to ensure they are all explicitly specified
electronFuses: Required<Configuration["electronFuses"]>;
} = {
appId: variant.appId,
asarUnpack: "**/*.node",
electronFuses: {
enableCookieEncryption: true,
onlyLoadAppFromAsar: true,
grantFileProtocolExtraPrivileges: false,
runAsNode: false,
enableNodeOptionsEnvironmentVariable: false,
enableNodeCliInspectArguments: false,
// We need to reset the signature if we are not signing on darwin otherwise it won't launch
resetAdHocDarwinSignature: !process.env.APPLE_TEAM_ID,
loadBrowserProcessSpecificV8Snapshot: false,
enableEmbeddedAsarIntegrityValidation: true,
},
files: [
"package.json",
{
from: ".hak/hakModules",
to: "node_modules",
},
"lib/**",
],
extraResources: ["build/icon.*", "webapp.asar"],
extraMetadata: {
name: variant.name,
productName: variant.productName,
description: variant.description,
electron_appId: variant.appId,
electron_protocol: variant.protocols[0],
},
linux: {
target: ["tar.gz", "deb"],
category: "Network;InstantMessaging;Chat",
icon: "icon.png",
executableName: variant.name, // element-desktop or element-desktop-nightly
},
deb: {
packageCategory: "net",
depends: [
"libgtk-3-0",
"libnotify4",
"libnss3",
"libxss1",
"libxtst6",
"xdg-utils",
"libatspi2.0-0",
"libuuid1",
"libsecret-1-0",
"libasound2",
"libgbm1",
],
recommends: ["libsqlcipher0", "element-io-archive-keyring"],
fpm: ["--deb-pre-depends", "libc6 (>= 2.31)"],
},
mac: {
target: ["dmg", "zip"],
category: "public.app-category.social-networking",
darkModeSupport: true,
hardenedRuntime: true,
gatekeeperAssess: true,
strictVerify: true,
entitlements: "./build/entitlements.mac.plist",
icon: "build/icon.icon",
mergeASARs: true,
x64ArchFiles: "**/matrix-seshat/*.node", // hak already runs lipo
},
dmg: {
badgeIcon: "build/icon.icon",
},
win: {
target: ["squirrel", "msi"],
signtoolOptions: {
signingHashAlgorithms: ["sha256"],
},
icon: "build/icon.ico",
},
msi: {
perMachine: true,
},
directories: {
output: "dist",
},
protocols: {
name: variant.productName,
schemes: variant.protocols,
},
nativeRebuilder: "sequential",
nodeGypRebuild: false,
npmRebuild: true,
};
/**
* Allow specifying the version via env var.
* If unspecified, it will default to the version in package.json.
* @param {string} process.env.VERSION
*/
if (process.env.VERSION) {
config.extraMetadata.version = process.env.VERSION;
}
if (variant["linux.deb.name"]) {
config.deb.fpm.push("--name", variant["linux.deb.name"]);
}
/**
* Allow specifying windows signing cert via env vars
* @param {string} process.env.ED_SIGNTOOL_SUBJECT_NAME
* @param {string} process.env.ED_SIGNTOOL_THUMBPRINT
*/
if (process.env.ED_SIGNTOOL_SUBJECT_NAME && process.env.ED_SIGNTOOL_THUMBPRINT) {
config.win.signtoolOptions!.certificateSubjectName = process.env.ED_SIGNTOOL_SUBJECT_NAME;
config.win.signtoolOptions!.certificateSha1 = process.env.ED_SIGNTOOL_THUMBPRINT;
config.extraMetadata.electron_windows_cert_sn = config.win.signtoolOptions!.certificateSubjectName;
}
if (os.platform() === "linux") {
// Electron crashes on debian if there's a space in the path.
// https://github.com/vector-im/element-web/issues/13171
config.extraMetadata.productName = config.extraMetadata.productName.replace(/ /g, "-");
/**
* Allow specifying deb changelog via env var
* @param {string} process.env.ED_DEB_CHANGELOG
*/
if (process.env.ED_DEBIAN_CHANGELOG) {
config.deb.fpm.push(`--deb-changelog=${process.env.ED_DEBIAN_CHANGELOG}`);
}
if (process.env.SQLCIPHER_BUNDLED) {
// Remove sqlcipher dependency when using bundled
config.deb.recommends = config.deb.recommends?.filter((d) => d !== "libsqlcipher0");
}
}
export default config;
@@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
MIIF8DCCBNigAwIBAgIRAIZSd8hNVs3w8AhJIsQSoYYwDQYJKoZIhvcNAQELBQAw
gZExCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTcwNQYD
VQQDEy5DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gQ29kZSBTaWduaW5n
IENBMB4XDTIwMDczMDAwMDAwMFoXDTIzMDczMDIzNTk1OVowgfMxETAPBgNVBAUT
CDEwODczNjYxMRMwEQYLKwYBBAGCNzwCAQMTAkdCMR0wGwYDVQQPExRQcml2YXRl
IE9yZ2FuaXphdGlvbjELMAkGA1UEBhMCR0IxDzANBgNVBBEMBlc0IDFRVTEYMBYG
A1UECAwPTG9uZG9uLCBDaXR5IG9mMQ8wDQYDVQQHDAZMb25kb24xJzAlBgNVBAkM
HjE0IFR1cm5oYW0gR3JlZW4sIFRlcnJhY2UgTWV3czEbMBkGA1UECgwSTmV3IFZl
Y3RvciBMaW1pdGVkMRswGQYDVQQDDBJOZXcgVmVjdG9yIExpbWl0ZWQwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKDnGul2M7oCCN+3veGf7yfakSfMjK
Kqeylyo0Nj8dUleNQvsRo0OHxIWJlbHDYglxebT109MqgyASr0SoeiqvXOSSFACD
MYFoyerRGMnXEuomTU0y7+FE3p/hcim8+C5gS+rHr3YaJJuzzXRztjjCBGoY4was
h9V8kYiyMMK0xi2WftOCBa1yYS32CInHIZVmdhzoK4k4YzSYIp57BWvnIUlDyCYk
slNfp0SFbDrOGa7kbmy8HRfWPLjNmW5PPIrsf8LlnVRBfmTeUIJtV31w/FuMjeir
pzYjzooXmpIrj96ecxdc9thP6etCUazvpowjfewu7UNWRUhGPtYn8v8rAgMBAAGj
ggHdMIIB2TAfBgNVHSMEGDAWgBTfj/MgDOnKpgTYW1g3Kj2rRtyDSTAdBgNVHQ4E
FgQUB9su4pCQXE5ZWFhB1eo48992LEcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB
/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEQYJYIZIAYb4QgEBBAQDAgQQMEkG
A1UdIARCMEAwNQYMKwYBBAGyMQECAQYBMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8v
c2VjdGlnby5jb20vQ1BTMAcGBWeBDAEDMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6
Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JTQUV4dGVuZGVkVmFsaWRhdGlvbkNv
ZGVTaWduaW5nQ0EuY3JsMIGGBggrBgEFBQcBAQR6MHgwUAYIKwYBBQUHMAKGRGh0
dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET1JTQUV4dGVuZGVkVmFsaWRhdGlv
bkNvZGVTaWduaW5nQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v
ZG9jYS5jb20wJgYDVR0RBB8wHaAbBggrBgEFBQcIA6APMA0MC0dCLTEwODczNjYx
MA0GCSqGSIb3DQEBCwUAA4IBAQBZ8/YtqW/+VUoV8knKpdhMR2uTn8AEyVmfmoZA
Ly5kdCRoKvFm/z4VK4cqF7gsUDxRIgDuMKKbWTtr1FEXuaZkUkOjicNcdYxc0pDn
nFKBWAv5pN5OmnC9cVqIG7PtvD+8bKVzDdQRjpGMy6PY4rN2PYGfQ7KGgddEDD6m
oM51jI/OTvCeU0Tyl0bixKEmpUJvbeQM9Ul2Y1o5Enx1Q9uda8xATb0HCMKgJ+GC
iFHL2DNC3j1xK4QoZEIYgbTscj9rK4OMEov3PT/e1FwQyB5V9xdJ5i1MDBDD9fAf
OiVgf90SffT7TgWUbA4Z+PtQHq/qNma0+dZWyeq7zYn2IIX3
-----END CERTIFICATE-----
+6
View File
@@ -0,0 +1,6 @@
This directory contains the config file for the official element.io distribution
of Element Desktop.
You probably do not want to build with this config unless you're building the
official element.io distribution, or you'll find your builds will replace
themselves with the element.io build.
@@ -0,0 +1,9 @@
{
"appId": "im.riot.nightly",
"name": "element-desktop-nightly",
"productName": "Element Nightly",
"description": "Element: the future of secure communication (nightly unstable build)",
"protocols": ["io.element.nightly", "element"],
"linux.executableName": "element-desktop-nightly",
"linux.deb.name": "element-nightly"
}
@@ -0,0 +1,65 @@
{
"update_base_url": "https://packages.element.io/nightly/update/",
"default_server_name": "matrix.org",
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix-client.matrix.org"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
},
"brand": "Element Nightly",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"bug_report_endpoint_url": "https://rageshakes.element.io/api/submit",
"uisi_autorageshake_app": "element-auto-uisi",
"show_labs_settings": true,
"room_directory": {
"servers": ["matrix.org", "gitter.im"]
},
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
},
"terms_and_conditions_links": [
{
"url": "https://element.io/privacy",
"text": "Privacy Policy"
},
{
"url": "https://element.io/cookie-policy",
"text": "Cookie Policy"
}
],
"sentry": {
"dsn": "https://029a0eb289f942508ae0fb17935bd8c5@sentry.matrix.org/6",
"environment": "nightly"
},
"posthog": {
"project_api_key": "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
"api_host": "https://posthog.element.io"
},
"privacy_policy_url": "https://element.io/cookie-policy",
"features": {
"threadsActivityCentre": true,
"feature_spotlight": true,
"feature_group_calls": true,
"feature_video_rooms": true,
"feature_element_call_video_rooms": true
},
"setting_defaults": {
"RustCrypto.staged_rollout_percent": 100
},
"element_call": {
"url": "https://call.element.dev"
},
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
}
@@ -0,0 +1,7 @@
{
"appId": "im.riot.app",
"name": "element-desktop",
"productName": "Element",
"description": "Element: the future of secure communication",
"protocols": ["io.element.desktop", "element"]
}
@@ -0,0 +1,59 @@
{
"update_base_url": "https://packages.element.io/desktop/update/",
"default_server_name": "matrix.org",
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix-client.matrix.org"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
},
"brand": "Element",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"bug_report_endpoint_url": "https://rageshakes.element.io/api/submit",
"uisi_autorageshake_app": "element-auto-uisi",
"room_directory": {
"servers": ["matrix.org", "gitter.im"]
},
"show_labs_settings": false,
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
},
"terms_and_conditions_links": [
{
"url": "https://element.io/privacy",
"text": "Privacy Policy"
},
{
"url": "https://element.io/cookie-policy",
"text": "Cookie Policy"
}
],
"posthog": {
"project_api_key": "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
"api_host": "https://posthog.element.io"
},
"privacy_policy_url": "https://element.io/cookie-policy",
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx",
"setting_defaults": {
"RustCrypto.staged_rollout_percent": 60
},
"features": {
"feature_video_rooms": true,
"feature_group_calls": true,
"feature_element_call_video_rooms": true
},
"element_call": {
"url": "https://call.element.io"
}
}
+34
View File
@@ -0,0 +1,34 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type HakEnv from "../../scripts/hak/hakEnv.ts";
import type { DependencyInfo } from "../../scripts/hak/dep.ts";
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const env = hakEnv.makeGypEnv();
if (!hakEnv.isHost()) {
env.CARGO_BUILD_TARGET = hakEnv.getTargetId();
}
console.log("Running yarn install");
await hakEnv.spawn("yarn", ["install"], {
cwd: moduleInfo.moduleBuildDir,
env,
shell: true,
});
const buildTarget = hakEnv.wantsStaticSqlCipher() ? "build-bundled" : "build";
console.log("Running yarn build");
await hakEnv.spawn("yarn", ["run", buildTarget], {
cwd: moduleInfo.moduleBuildDir,
env,
shell: true,
});
}
+60
View File
@@ -0,0 +1,60 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import childProcess from "node:child_process";
import fsProm from "node:fs/promises";
import type HakEnv from "../../scripts/hak/hakEnv.ts";
import type { Tool } from "../../scripts/hak/hakEnv.ts";
import type { DependencyInfo } from "../../scripts/hak/dep.ts";
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const tools: Tool[] = [["rustc", "--version"]];
if (hakEnv.isWin()) {
tools.push(["perl", "--version"]); // for openssl configure
tools.push(["nasm", "-v"]); // for openssl building
tools.push(["patch", "--version"]); // to patch sqlcipher Makefile.msc
tools.push(["nmake", "/?"]);
} else {
tools.push(["make", "--version"]);
}
await hakEnv.checkTools(tools);
try {
// node-gyp uses python for reasons beyond comprehension
// Try python3 first, to get a more sensible error if python is not found in the fallback
await hakEnv.checkTools([["python3", "--version"]]);
} catch {
await hakEnv.checkTools([["python", "--version"]]);
}
// Ensure Rust target exists (nb. we avoid depending on rustup)
await new Promise((resolve, reject) => {
const rustc = childProcess.execFile(
"rustc",
["--target", hakEnv.getTargetId(), "--emit=obj", "-o", "tmp", "-"],
(err, out) => {
if (err) {
reject(
"rustc can't build for target " +
hakEnv.getTargetId() +
": ensure target is installed via `rustup target add " +
hakEnv.getTargetId() +
"` " +
"or your package manager if not using `rustup`",
);
}
fsProm.unlink("tmp").then(resolve);
},
);
rustc.stdin!.write("fn main() {}");
rustc.stdout!.pipe(process.stdout);
rustc.stderr!.pipe(process.stderr);
rustc.stdin!.end();
});
}
+7
View File
@@ -0,0 +1,7 @@
{
"scripts": {
"check": "check.ts",
"build": "build.ts"
},
"copy": "index.node"
}
+14
View File
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"moduleResolution": "node16",
"module": "Node16",
"esModuleInterop": true,
"target": "es2022",
"sourceMap": false,
"strict": true,
"lib": ["es2022"],
"types": ["node"],
"allowImportingTsExtensions": true
},
"include": ["../scripts/@types/*.d.ts", "./**/*.ts"]
}
+119
View File
@@ -0,0 +1,119 @@
{
"name": "element-desktop",
"productName": "ThreadNet",
"main": "lib/electron-main.js",
"exports": "./lib/electron-main.js",
"version": "1.12.17",
"description": "Element: the future of secure communication",
"author": {
"name": "Element",
"email": "support@element.io"
},
"homepage": "https://element.io",
"repository": {
"type": "git",
"url": "https://github.com/vector-im/element-web"
},
"license": "SEE LICENSE IN README.md",
"type": "module",
"files": [],
"engines": {
"node": ">=22.18"
},
"scripts": {
"i18n": "matrix-gen-i18n && pnpm i18n:sort && pnpm i18n:lint",
"i18n:sort": "matrix-sort-i18n src/i18n/strings/en_EN.json",
"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",
"mkdirs": "mkdirp packages deploys",
"fetch": "pnpm run mkdirs && node scripts/fetch-package.ts",
"asar-webapp": "asar p webapp webapp.asar",
"start": "nx start",
"lint": "pnpm lint:types && pnpm lint:js",
"lint:js": "eslint --max-warnings 0 src hak playwright scripts",
"lint:js-fix": "eslint --fix --max-warnings 0 src hak playwright scripts && prettier --log-level=warn --write .",
"lint:types": "pnpm lint:types:src && pnpm lint:types:node && pnpm lint:types:test && pnpm lint:types:scripts && pnpm lint:types:hak",
"lint:types:src": "tsc --noEmit",
"lint:types:node": "tsc --noEmit -p tsconfig.node.json",
"lint:types:test": "tsc --noEmit -p playwright/tsconfig.json",
"lint:types:scripts": "tsc --noEmit -p scripts/tsconfig.json",
"lint:types:hak": "tsc --noEmit -p hak/tsconfig.json",
"build:native": "pnpm run hak",
"build:native:universal": "pnpm run hak --target x86_64-apple-darwin fetchandbuild && pnpm run hak --target aarch64-apple-darwin fetchandbuild && pnpm run hak --target x86_64-apple-darwin --target aarch64-apple-darwin copyandlink",
"build:32": "nx build --ia32",
"build:64": "nx build --x64",
"build:universal": "nx build --universal",
"build": "nx build --",
"docker:setup": "docker build --platform linux/amd64 -t element-desktop-dockerbuild -f dockerbuild/Dockerfile .",
"docker:build:native": "scripts/in-docker.sh pnpm run hak",
"docker:build": "scripts/in-docker.sh pnpm run build",
"docker:install": "scripts/in-docker.sh pnpm install",
"clean": "rimraf webapp.asar dist packages deploys lib",
"hak": "node scripts/hak/index.ts",
"test:unit": "vitest",
"test:playwright": "nx test:playwright --",
"test:playwright:open": "nx test:playwright -- --ui",
"test:playwright:screenshots": "nx test:playwright:screenshots --",
"sane-postinstall": "electron-builder install-app-deps"
},
"dependencies": {
"@sentry/electron": "^7.0.0",
"auto-launch": "^5.0.5",
"counterpart": "^0.18.6",
"electron-store": "^11.0.0",
"electron-window-state": "^5.0.3",
"minimist": "^1.2.6",
"png-to-ico": "^3.0.0",
"uuid": "^14.0.0"
},
"devDependencies": {
"@babel/core": "^7.18.10",
"@babel/preset-env": "^7.18.10",
"@babel/preset-typescript": "^7.18.6",
"@electron/asar": "4.2.0",
"@electron/fuses": "^2.1.1",
"@element-hq/vite-common": "workspace:*",
"@playwright/test": "catalog:",
"@stylistic/eslint-plugin": "^5.0.0",
"@types/auto-launch": "^5.0.1",
"@types/counterpart": "^0.18.1",
"@types/minimist": "^1.2.1",
"@types/node": "18.19.130",
"@types/pacote": "^11.1.1",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/coverage-v8": "catalog:",
"app-builder-lib": "26.9.1",
"chokidar": "^5.0.0",
"detect-libc": "^2.0.0",
"electron": "42.0.0",
"electron-builder": "26.9.1",
"electron-builder-squirrel-windows": "26.9.1",
"electron-devtools-installer": "^4.0.0",
"eslint": "^8.26.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^10.0.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-matrix-org": "^3.0.0",
"eslint-plugin-n": "^17.12.0",
"eslint-plugin-unicorn": "^56.0.0",
"glob": "^13.0.0",
"matrix-web-i18n": "catalog:",
"memfs": "^4.57.2",
"mkdirp": "^3.0.0",
"pacote": "^21.0.0",
"prettier": "^3.0.0",
"rimraf": "^6.0.0",
"tar": "^7.5.8",
"typescript": "6.0.3",
"vitest": "catalog:",
"vitest-sonar-reporter": "catalog:"
},
"hakDependencies": {
"matrix-seshat": "4.2.0"
},
"packageManager": "pnpm@10.33.3+sha512.a19744364a7e248b92657a4ca5973f9354d21caf982579674b1c539f32c7420c47138ad8b1254df07aba9bc782d9b3029e3db34d5dbff974326eb74dac8ff489",
"nx": {
"includedScripts": []
}
}
+27
View File
@@ -0,0 +1,27 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { defineConfig } from "@playwright/test";
export default defineConfig({
projects: [{ name: "Desktop" }],
tag: process.env.PW_TAG ? `@${process.env.PW_TAG}` : undefined,
use: {
viewport: { width: 1280, height: 720 },
video: "retain-on-failure",
trace: "on-first-retry",
},
testDir: "playwright/e2e",
outputDir: "playwright/test-results",
workers: 1,
retries: process.env.CI ? 2 : 0,
reporter: process.env.CI ? [["blob"], ["github"]] : [["html", { outputFolder: "playwright/html-report" }]],
snapshotDir: "playwright/snapshots",
snapshotPathTemplate: "{snapshotDir}/{testFilePath}/{arg}-{platform}{ext}",
timeout: 30 * 1000,
});
+5
View File
@@ -0,0 +1,5 @@
/test-results/
/html-report/
# Only commit snapshots from Linux
/snapshots/**/*.png
!/snapshots/**/*-linux.png
+19
View File
@@ -0,0 +1,19 @@
FROM mcr.microsoft.com/playwright:v1.59.1-jammy@sha256:8a0360d39d1973be506dd59002904a774f6d697d4946c94063b3fd006461c8ff
WORKDIR /work
RUN apt-get update && \
apt-get -y install xvfb dbus-x11 && \
apt-get purge -y --auto-remove && \
rm -rf /var/lib/apt/lists/* && \
corepack enable
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
ENV GITHUB_ACTIONS=1
ENV DEBUG=pw:browser
# switch to node user
USER 1000:1000
COPY apps/desktop/playwright/docker-entrypoint.sh /opt/docker-entrypoint.sh
ENTRYPOINT ["bash", "/opt/docker-entrypoint.sh"]
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
set -e
echo "Starting Xvfb"
Xvfb :99 -ac &
sleep 2
export DISPLAY=:99
PLAYWRIGHT_HTML_OPEN=never ELEMENT_DESKTOP_EXECUTABLE="./dist/linux-unpacked/element-desktop" \
exec pnpm -C apps/desktop exec playwright test --update-snapshots --reporter line,html "$1"
@@ -0,0 +1,44 @@
/*
Copyright 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { test, expect } from "../../element-desktop-test.js";
const __dirname = dirname(fileURLToPath(import.meta.url));
test.describe("App config options", () => {
test.describe("Should load custom config via env", () => {
test.slow();
test.use({
extraEnv: {
ELEMENT_DESKTOP_CONFIG_JSON: resolve(__dirname, "../..", "fixtures/custom-config.json"),
},
});
test("should launch and use configured homeserver", async ({ page }) => {
await page.locator("#matrixchat").waitFor();
await page.locator(".mx_Welcome").waitFor();
await expect(page).toHaveURL("vector://vector/webapp/#/welcome");
await page.getByText("Sign in").click();
await page.getByText("matrix.example.org", { exact: true }).waitFor();
});
});
test.describe("Should load custom config via argument", () => {
test.slow();
test.use({
extraArgs: ["--config", resolve(__dirname, "../..", "fixtures/custom-config.json")],
});
test("should launch and use configured homeserver", async ({ page }) => {
await page.locator("#matrixchat").waitFor();
await page.locator(".mx_Welcome").waitFor();
await expect(page).toHaveURL("vector://vector/webapp/#/welcome");
await page.getByText("Sign in").click();
await page.getByText("matrix.example.org", { exact: true }).waitFor();
});
});
});
@@ -0,0 +1,75 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2022, 2023 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { test, expect } from "../../element-desktop-test.js";
declare global {
interface ElectronPlatform {
getEventIndexingManager():
| {
supportsEventIndexing(): Promise<boolean>;
}
| undefined;
getPickleKey(userId: string, deviceId: string): Promise<string | null>;
createPickleKey(userId: string, deviceId: string): Promise<string | null>;
}
interface Window {
mxPlatformPeg: {
get(): ElectronPlatform;
};
}
}
test.describe("App launch", () => {
test.slow();
test.beforeEach(async ({ page }) => {
await page.locator("#matrixchat").waitFor();
await page.locator(".mx_Welcome").waitFor();
});
test("should launch and render the welcome view successfully", async ({ page }) => {
await expect(page).toHaveURL("vector://vector/webapp/#/welcome");
await expect(page).toHaveScreenshot();
});
test("should launch and render the welcome view successfully and support seshat", async ({ page }) => {
await expect(
page.evaluate<boolean>(async () => {
return window.mxPlatformPeg.get().getEventIndexingManager()?.supportsEventIndexing();
}),
).resolves.toBeTruthy();
});
test.describe("safeStorage", () => {
const userId = "@user:server";
const deviceId = "ABCDEF";
test("should be supported", async ({ page }) => {
await expect(
page.evaluate(
([userId, deviceId]) => window.mxPlatformPeg.get().createPickleKey(userId, deviceId),
[userId, deviceId],
),
).resolves.not.toBeNull();
});
});
test.describe("--no-update", () => {
test.use({
extraArgs: ["--no-update"],
});
// XXX: this test works fine locally but in CI the app start races with the test plumbing up the stdout/stderr pipes
// which means the logs are missed, disabling for now.
test.skip("should respect option", async ({ page, stdout }) => {
expect(stdout.data.toString()).toContain("Auto update disabled via command line flag");
});
});
});
@@ -0,0 +1,36 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { test, expect } from "../../element-desktop-test.js";
declare global {
interface ElectronPlatform {
getOidcCallbackUrl(): URL;
}
interface Window {
mxPlatformPeg: {
get(): ElectronPlatform;
};
}
}
test.describe("OIDC Native", () => {
test.slow();
test.beforeEach(async ({ page }) => {
await page.locator(".mx_Welcome").waitFor();
});
test("should use OIDC callback URL without authority component", async ({ page }) => {
await expect(
page.evaluate<string>(() => {
return window.mxPlatformPeg.get().getOidcCallbackUrl().toString();
}),
).resolves.toMatch(/io\.element\.(desktop|nightly):\/vector\/webapp\//);
});
});
@@ -0,0 +1,126 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { _electron as electron, test as base, expect as baseExpect, type ElectronApplication } from "@playwright/test";
import fs from "node:fs/promises";
import path, { dirname } from "node:path";
import os from "node:os";
import { fileURLToPath } from "node:url";
import { PassThrough } from "node:stream";
/**
* A PassThrough stream that captures all data written to it.
*/
class CapturedPassThrough extends PassThrough {
private _chunks: any[] = [];
public constructor() {
super();
super.on("data", this.onData);
}
private onData = (chunk: any): void => {
this._chunks.push(chunk);
};
public get data(): Buffer {
return Buffer.concat(this._chunks);
}
}
interface Fixtures {
app: ElectronApplication;
tmpDir: string;
extraEnv: Record<string, string>;
extraArgs: string[];
// Utilities to capture stdout and stderr for tests to make assertions against
stdout: CapturedPassThrough;
stderr: CapturedPassThrough;
}
const __dirname = dirname(fileURLToPath(import.meta.url));
export const test = base.extend<Fixtures>({
extraEnv: {},
extraArgs: [],
// eslint-disable-next-line no-empty-pattern
stdout: async ({}, use) => {
await use(new CapturedPassThrough());
},
// eslint-disable-next-line no-empty-pattern
stderr: async ({}, use) => {
await use(new CapturedPassThrough());
},
// eslint-disable-next-line no-empty-pattern
tmpDir: async ({}, use) => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "element-desktop-tests-"));
await use(tmpDir);
await fs.rm(tmpDir, { recursive: true });
},
app: async ({ tmpDir, extraEnv, extraArgs, stdout, stderr }, use) => {
const args = ["--profile-dir", tmpDir, ...extraArgs];
if (process.env.GITHUB_ACTIONS) {
args.push("--disable-gpu");
if (process.platform === "linux") {
if (process.getuid() === 0) {
args.push("--no-sandbox");
}
// GitHub Actions hosted runner lacks dbus and a compatible keyring, so we need to force plaintext storage
args.push("--storage-mode", "force-plaintext");
} else if (process.platform === "darwin") {
// GitHub Actions hosted runner has no working default keychain, so allow plaintext storage
args.push("--storage-mode", "allow-plaintext");
}
}
const executablePath = process.env["ELEMENT_DESKTOP_EXECUTABLE"];
if (!executablePath) {
// Unpackaged mode testing
args.unshift(path.join(__dirname, "..", "lib", "electron-main.js"));
}
console.log(`Launching '${executablePath || "electron"}' with args ${args.join(" ")}`);
const app = await electron.launch({
env: {
...process.env,
...extraEnv,
},
executablePath,
args,
});
app.process().stdout.pipe(stdout).pipe(process.stdout);
app.process().stderr.pipe(stderr).pipe(process.stderr);
await app.firstWindow();
// Block matrix.org access to ensure consistent tests
const context = app.context();
await context.route("https://matrix.org/**", async (route) => {
await route.abort();
});
await use(app);
},
page: async ({ app }, use) => {
const window = await app.firstWindow();
await use(window);
await app.close().catch((e) => {
console.error(e);
});
},
});
export const expect = baseExpect;
@@ -0,0 +1,10 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix.example.org"
},
"m.identity_server": {
"base_url": "https://identity.example.org"
}
}
}
+13
View File
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"resolveJsonModule": true,
"moduleResolution": "bundler",
"esModuleInterop": true,
"target": "es2022",
"module": "ESNext",
"lib": ["es2024", "dom", "dom.iterable"],
"strictNullChecks": false,
"types": ["node"]
},
"include": ["**/*.ts"]
}
+83
View File
@@ -0,0 +1,83 @@
{
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"implicitDependencies": ["element-web"],
"root": "apps/desktop",
"targets": {
"docker:build": {
"executor": "@nx-tools/nx-container:build",
"options": {
"load": true,
"engine": "docker",
"platforms": ["linux/amd64", "linux/arm64"],
"provenance": "true",
"sbom": true,
"context": "{projectRoot}",
"file": "{projectRoot}/dockerbuild/Dockerfile",
"metadata": {
"images": ["ghcr.io/element-hq/element-web/desktop-build-env"],
"tags": ["type=ref,event=branch"]
}
}
},
"build:ts": {
"cache": true,
"command": "tsc",
"inputs": ["src", "{projectRoot}/tsconfig.json"],
"outputs": ["{projectRoot}/lib/*.js", "{projectRoot}/lib/*.d.ts"],
"options": { "cwd": "apps/desktop" }
},
"build:res": {
"cache": true,
"command": "node scripts/copy-res.ts",
"inputs": ["{projectRoot}/i18n"],
"outputs": ["{projectRoot}/lib/i18n"],
"options": { "cwd": "apps/desktop" }
},
"build": {
"cache": true,
"command": "pnpm exec electron-builder",
"inputs": [
"src",
"{projectRoot}/.hak/hakModules",
"{projectRoot}/electron-builder.json",
"{projectRoot}/webapp.asar"
],
"outputs": ["{projectRoot}/dist"],
"options": { "cwd": "apps/desktop" },
"dependsOn": ["build:*"]
},
"start": {
"command": "electron .",
"options": { "cwd": "apps/desktop" },
"dependsOn": ["build:*"]
},
"test:playwright": {
"command": "playwright test",
"options": { "cwd": "apps/desktop" }
},
"test:playwright:screenshots:build-app": {
"executor": "nx:run-commands",
"options": {
"commands": [
"pnpm run build -l --x64 --dir --publish=never",
"pnpm exec electron-fuses write --app ./dist/linux-unpacked/element-desktop EnableNodeCliInspectArguments=on"
],
"parallel": false,
"cwd": "apps/desktop"
},
"dependsOn": ["build:*"]
},
"test:playwright:screenshots:build-docker": {
"cache": true,
"command": "docker build -f playwright/Dockerfile -t element-desktop-playwright --platform linux/amd64 ../..",
"inputs": ["{projectRoot}/playwright/Dockerfile", "{projectRoot}/playwright/docker-entrypoint.sh"],
"options": { "cwd": "apps/desktop" }
},
"test:playwright:screenshots": {
"command": "docker run --rm --network host -v $(pwd)/../../:/work/ --platform linux/amd64 -it element-desktop-playwright",
"options": { "cwd": "apps/desktop" },
"dependsOn": ["test:playwright:screenshots:*"]
}
}
}
+7
View File
@@ -0,0 +1,7 @@
REM Batch file to aid in cross-compiling sqlcipher for Windows ARM64
REM Full path should be passed to Makefile.msc as NCC env var
setlocal
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" %VSCMD_ARG_HOST_ARCH%
cl.exe %*
endlocal
+81
View File
@@ -0,0 +1,81 @@
#!/usr/bin/env node
// copies resources into the lib directory.
import parseArgs from "minimist";
import * as chokidar from "chokidar";
import * as path from "node:path";
import * as fs from "node:fs";
const argv = parseArgs(process.argv.slice(2), {});
const watch = argv.w;
const verbose = argv.v;
function errCheck(err: unknown): void {
if (err) {
console.error(err instanceof Error ? err.message : err);
process.exit(1);
}
}
const I18N_BASE_PATH = "src/i18n/strings/";
const INCLUDE_LANGS = fs.readdirSync(I18N_BASE_PATH).filter((fn) => fn.endsWith(".json"));
// Ensure lib, lib/i18n and lib/i18n/strings all exist
fs.mkdirSync("lib/i18n/strings", { recursive: true });
type Translations = Record<string, Record<string, string> | string>;
function genLangFile(file: string, dest: string): void {
const translations: Translations = {};
[file].forEach(function (f) {
if (fs.existsSync(f)) {
try {
Object.assign(translations, JSON.parse(fs.readFileSync(f).toString()));
} catch (e) {
console.error("Failed: " + f, e);
throw e;
}
}
});
const json = JSON.stringify(translations, null, 4);
const filename = path.basename(file);
fs.writeFileSync(dest + filename, json);
if (verbose) {
console.log("Generated language file: " + filename);
}
}
/*
watch the input files for a given language,
regenerate the file, and regenerating languages.json with the new filename
*/
function watchLanguage(file: string, dest: string): void {
// XXX: Use a debounce because for some reason if we read the language
// file immediately after the FS event is received, the file contents
// appears empty. Possibly https://github.com/nodejs/node/issues/6112
let makeLangDebouncer: NodeJS.Timeout | undefined;
const makeLang = (): void => {
if (makeLangDebouncer) {
clearTimeout(makeLangDebouncer);
}
makeLangDebouncer = setTimeout(() => {
genLangFile(file, dest);
}, 500);
};
chokidar.watch(file).on("add", makeLang).on("change", makeLang).on("error", errCheck);
}
// language resources
const I18N_DEST = "lib/i18n/strings/";
INCLUDE_LANGS.forEach((file): void => {
genLangFile(I18N_BASE_PATH + file, I18N_DEST);
}, {});
if (watch) {
INCLUDE_LANGS.forEach((file) => watchLanguage(I18N_BASE_PATH + file, I18N_DEST));
}
+240
View File
@@ -0,0 +1,240 @@
#!/usr/bin/env node
import * as path from "node:path";
import { createWriteStream, promises as fs } from "node:fs";
import * as childProcess from "node:child_process";
import * as tar from "tar";
import * as asar from "@electron/asar";
import { promises as stream } from "node:stream";
import riotDesktopPackageJson from "../package.json" with { type: "json" };
import { setPackageVersion } from "./set-version.ts";
const PUB_KEY_URL = "https://packages.riot.im/element-release-key.asc";
const PACKAGE_URL_PREFIX = "https://github.com/element-hq/element-web/releases/download/";
const DEVELOP_TGZ_URL = "https://develop.element.io/develop.tar.gz";
const ASAR_PATH = "webapp.asar";
async function downloadToFile(url: string, filename: string): Promise<void> {
console.log("Downloading " + url + "...");
try {
const resp = await fetch(url);
if (!resp.ok) throw new Error(`unexpected response ${resp.statusText}`);
if (!resp.body) throw new Error(`unexpected response has no body ${resp.statusText}`);
await stream.pipeline(resp.body, createWriteStream(filename));
} catch (e) {
console.error(e);
try {
await fs.unlink(filename);
} catch {}
throw e;
}
}
async function verifyFile(filename: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
childProcess.execFile("gpg", ["--verify", filename + ".asc", filename], (error) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
}
async function main(): Promise<number | undefined> {
let verify = true;
let importkey = false;
let pkgDir = "packages";
let deployDir = "deploys";
let cfgDir: string | undefined;
let targetVersion: string | undefined;
let filename: string | undefined;
let url: string | undefined;
let setVersion = false;
while (process.argv.length > 2) {
switch (process.argv[2]) {
case "--noverify":
verify = false;
break;
case "--importkey":
importkey = true;
break;
case "--packages":
process.argv.shift();
pkgDir = process.argv[2];
break;
case "--deploys":
process.argv.shift();
deployDir = process.argv[2];
break;
case "--cfgdir":
case "-d":
process.argv.shift();
cfgDir = process.argv[2];
break;
default:
targetVersion = process.argv[2];
}
process.argv.shift();
}
if (targetVersion === undefined) {
targetVersion = "v" + riotDesktopPackageJson.version;
} else if (targetVersion !== "develop") {
setVersion = true; // version was specified
}
if (targetVersion === "develop") {
filename = "develop.tar.gz";
url = DEVELOP_TGZ_URL;
verify = false; // develop builds aren't signed
} else if (targetVersion.includes("://")) {
filename = targetVersion.substring(targetVersion.lastIndexOf("/") + 1);
url = targetVersion;
verify = false; // manually verified
} else {
filename = `element-${targetVersion}.tar.gz`;
url = PACKAGE_URL_PREFIX + targetVersion + "/" + filename;
}
const haveGpg = await new Promise<boolean>((resolve) => {
childProcess.execFile("gpg", ["--version"], (error) => {
resolve(!error);
});
});
if (importkey) {
if (!haveGpg) {
console.log("Can't import key without working GPG binary: install GPG and try again");
return 1;
}
await new Promise<boolean>((resolve, reject) => {
const gpgProc = childProcess.execFile("gpg", ["--import"], (error) => {
if (error) {
console.log("Failed to import key", error);
} else {
console.log("Key imported!");
}
resolve(!error);
});
fetch(PUB_KEY_URL)
.then((resp) => {
if (!resp.ok) throw new Error(`unexpected response ${resp.statusText}`);
if (!resp.body) throw new Error(`unexpected response has no body ${resp.statusText}`);
stream.pipeline(resp.body, gpgProc.stdin!).catch(reject);
})
.catch(reject);
});
return 0;
}
if (cfgDir === undefined) {
console.log("No config directory set");
console.log("Specify a config directory with --cfgdir or -d");
console.log("To build with no config (and no auto-update), pass the empty string (-d '')");
return 1;
}
if (verify && !haveGpg) {
console.log("No working GPG binary: install GPG or pass --noverify to skip verification");
return 1;
}
let haveDeploy = false;
let expectedDeployDir = path.join(deployDir, path.basename(filename).replace(/\.tar\.gz/, ""));
try {
await fs.opendir(expectedDeployDir);
console.log(expectedDeployDir + "already exists");
haveDeploy = true;
} catch {}
if (!haveDeploy) {
const outPath = path.join(pkgDir, filename);
try {
await fs.stat(outPath);
console.log("Already have " + filename + ": not redownloading");
} catch {
try {
await downloadToFile(url, outPath);
} catch (e) {
console.log("Failed to download " + url, e);
return 1;
}
}
if (verify) {
try {
await fs.stat(outPath + ".asc");
console.log("Already have " + filename + ".asc: not redownloading");
} catch {
try {
await downloadToFile(url + ".asc", outPath + ".asc");
} catch (e) {
console.log("Failed to download " + url, e);
return 1;
}
}
try {
await verifyFile(outPath);
console.log(outPath + " downloaded and verified");
} catch (e) {
console.log("Signature verification failed!", e);
return 1;
}
} else {
console.log(outPath + " downloaded but NOT verified");
}
await tar.x({
file: outPath,
cwd: deployDir,
onentry: (entry) => {
// Find the appropriate extraction path, only needed for `develop` where the dir name is unknown
if (entry.type === "Directory" && !path.join(deployDir, entry.path).startsWith(expectedDeployDir)) {
expectedDeployDir = path.join(deployDir, entry.path);
}
},
});
}
try {
await fs.stat(ASAR_PATH);
console.log(ASAR_PATH + " already present: removing");
await fs.unlink(ASAR_PATH);
} catch {}
if (cfgDir.length) {
const configJsonSource = path.join(cfgDir, "config.json");
const configJsonDest = path.join(expectedDeployDir, "config.json");
console.log(configJsonSource + " -> " + configJsonDest);
await fs.copyFile(configJsonSource, configJsonDest);
} else {
console.log("Skipping config file");
}
console.log("Pack " + expectedDeployDir + " -> " + ASAR_PATH);
await asar.createPackage(expectedDeployDir, ASAR_PATH);
if (setVersion) {
const semVer = (await fs.readFile(path.join(expectedDeployDir, "version"), "utf-8")).trim();
console.log("Updating version to " + semVer);
await setPackageVersion(semVer);
}
console.log("Done!");
}
main()
.then((ret) => {
process.exit(ret);
})
.catch((e) => {
console.error(e);
process.exit(1);
});
@@ -0,0 +1,41 @@
#!/usr/bin/env node
/**
* Script to generate incremental Nightly build versions, based on the latest Nightly build version of that kind.
* The version format is YYYYMMDDNN where NN is in case we need to do multiple versions in a day.
*
* NB. on windows, squirrel will try to parse the version number parts, including this string, into 32-bit integers,
* which is fine as long as we only add two digits to the end...
*/
import parseArgs from "minimist";
const argv = parseArgs<{
latest?: string;
}>(process.argv.slice(2), {
string: ["latest"],
});
function parseVersion(version: string): [Date, number] {
const year = parseInt(version.slice(0, 4), 10);
const month = parseInt(version.slice(4, 6), 10);
const day = parseInt(version.slice(6, 8), 10);
const num = parseInt(version.slice(8, 10), 10);
return [new Date(year, month - 1, day), num];
}
const [latestDate, latestNum] = argv.latest ? parseVersion(argv.latest) : [];
const now = new Date();
const month = (now.getMonth() + 1).toString().padStart(2, "0");
const date = now.getDate().toString().padStart(2, "0");
let buildNum = 1;
if (latestDate && new Date(latestDate).getDate().toString().padStart(2, "0") === date) {
buildNum = latestNum! + 1;
}
if (buildNum > 99) {
throw new Error("Maximum number of Nightlies exceeded on this day.");
}
console.log(now.getFullYear() + month + date + buildNum.toString().padStart(2, "0"));
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env node
/*
* Checks for the presence of a webapp, inspects its version and prints it
*/
import url from "node:url";
import { versionFromAsar } from "./set-version.ts";
async function main(): Promise<number> {
const version = await versionFromAsar();
console.log(version);
return 0;
}
if (import.meta.url.startsWith("file:")) {
const modulePath = url.fileURLToPath(import.meta.url);
if (process.argv[1] === modulePath) {
main()
.then((ret) => {
process.exit(ret);
})
.catch((e) => {
console.error(e);
process.exit(1);
});
}
}
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
# Source https://gist.github.com/vladimyr/9a03481154cd3048a486bdf71e5e1535/57e57a6ace6fb2c8bba948bce726df7a96c3f99f
# This scripts lets you check which minimum GLIBC version an executable requires.
# Simply run './glibc-check.sh path/to/your/binary'
MAX_GLIBC="${MAX_GLIBC:-2.28}"
BINARY="$1"
# Version comparison function in bash
vercomp() {
if [[ $1 == "$2" ]]; then
return 0
fi
local i ver1 ver2
IFS="." read -ra ver1 <<<"$1"
IFS="." read -ra ver2 <<<"$2"
# fill empty fields in ver1 with zeros
for ((i = ${#ver1[@]}; i < ${#ver2[@]}; i++)); do
ver1[i]=0
done
for ((i = 0; i < ${#ver1[@]}; i++)); do
if [[ -z ${ver2[i]} ]]; then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]})); then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]})); then
return 2
fi
done
return 0
}
IFS="
"
VERS=$(objdump -T "$BINARY" | grep GLIBC_ | sed 's/.*GLIBC_\([.0-9]*\).*/\1/g' | sort -u)
for VER in $VERS; do
vercomp "$VER" "$MAX_GLIBC"
COMP=$?
if [[ $COMP -eq 1 ]]; then
echo "Error! ${BINARY} requests GLIBC ${VER}, which is higher than target ${MAX_GLIBC}"
echo "Affected symbols:"
objdump -T "$BINARY" | grep -F "GLIBC_${VER}"
echo "Looking for symbols in libraries..."
for LIBRARY in $(ldd "$BINARY" | cut -d ' ' -f 3); do
echo "$LIBRARY"
objdump -T "$LIBRARY" | grep -F "GLIBC_${VER}"
done
exit 27
else
echo "Found version ${VER}"
fi
done
+78
View File
@@ -0,0 +1,78 @@
# hak
This tool builds native dependencies for element-desktop. Here follows some very minimal
documentation for it.
Goals:
- Must build compiled native node modules in a shippable state
(ie. only dynamically linked against libraries that will be on the
target system, all unnecessary files removed).
- Must be able to build any native module, no matter what build system
it uses (electron-rebuild is supposed to do this job but only works
for modules that use gyp).
It's also loosely designed to be a general tool and agnostic to what it's
actually building. It's used here to build modules for the electron app
but should work equally well for building modules for normal node.
# Running
Hak is invoked with a command and a dependency, eg. `pnpm run hak fetch matrix-seshat`.
If no dependencies are given, hak runs the command on all dependencies.
# Files
There are a lot of files involved:
- scripts/hak/... - The tool itself
- hak/[dependency] - Files provided by the app that tell hak how to build each of its native dependencies.
Contains a hak.json file and also some script files, each of which must be referenced in hak.json.
- .hak/ - Files generated by hak in the course of doing its job. Includes the dependency module itself and
any of the native dependency's native dependencies.
- .hak/[dependency]/build - An extracted copy of the dependency's node module used to build it.
- .hak/[dependency]/out - Another extracted copy of the dependency, this one contains only what will be shipped.
# Workings
Hak works around native node modules that try to fetch or build their native component in
the npm 'install' phase - modules that do this will typically end up with native components
targeted to the build platform and the node that npm/pnpm is using, which is no good for an
electron app.
It does this by installing it with `--ignore-scripts` and then using `pnpm link` to keep the
dependency module separate so pnpm doesn't try to run its install / postinstall script
at other points (eg. whenever you `pnpm add` a random other dependency).
This also means that the dependencies cannot be listed in `dependencies` or
`devDependencies` in the project, since this would cause pnpm to install them and
try to fetch their native parts. Instead, they are listed in `hakDependencies` which
hak reads to install them for you.
Hak will _not_ install dependencies for the copy of the module it links into your
project, so if your native module has javascript dependencies that are actually needed at
runtime (and not just to fetch / build the native parts), it won't work.
# Lifecycle
Hak is divided into lifecycle stages, in order:
- fetch - Download and extract the source of the dependency
- link - Link the copy of the dependency into your node_modules directory
- build - The Good Stuff. Configure and build any native dependencies, then the module itself.
- copy - Copy the built artifact from the module build directory to the module output directory.
# hak.json
The scripts section contains scripts used for lifecycle stages that need them (fetch, build).
It also contains 'prune' and 'copy' which are globs of files to delete from the output module directory
and copy over from the module build directory to the output module directory, respectively.
# Shortcomings
Hak doesn't know about dependencies between lifecycle stages, ie. it doesn't know that you need to
'fetch' before you can 'build', etc. You get to run each individually, and remember
the right order.
There is also a _lot_ of duplication in the command execution: we should abstract away
some of the boilerplate required to run commands & so forth.
+14
View File
@@ -0,0 +1,14 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type { DependencyInfo } from "./dep.ts";
import type HakEnv from "./hakEnv.ts";
export default async function build(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
await moduleInfo.scripts.build(hakEnv, moduleInfo);
}
+14
View File
@@ -0,0 +1,14 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type { DependencyInfo } from "./dep.ts";
import type HakEnv from "./hakEnv.ts";
export default async function check(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
await moduleInfo.scripts.check?.(hakEnv, moduleInfo);
}
+19
View File
@@ -0,0 +1,19 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import { rimraf } from "rimraf";
import type { DependencyInfo } from "./dep.ts";
import type HakEnv from "./hakEnv.ts";
export default async function clean(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
await rimraf(moduleInfo.moduleDotHakDir);
await rimraf(path.join(hakEnv.dotHakDir, "links", moduleInfo.name));
await rimraf(path.join(hakEnv.projectRoot, "node_modules", moduleInfo.name));
}
+62
View File
@@ -0,0 +1,62 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import fsProm from "node:fs/promises";
import childProcess from "node:child_process";
import { glob } from "glob";
import { mkdirp } from "mkdirp";
import type HakEnv from "./hakEnv.ts";
import type { DependencyInfo } from "./dep.ts";
export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
if (moduleInfo.cfg.copy) {
// If there are multiple moduleBuildDirs, singular moduleBuildDir
// is the same as moduleBuildDirs[0], so we're just listing the contents
// of the first one.
const files = await glob(moduleInfo.cfg.copy, {
cwd: moduleInfo.moduleBuildDir,
});
if (moduleInfo.moduleBuildDirs.length > 1) {
if (!hakEnv.isMac()) {
console.error(
"You asked me to copy multiple targets but I've only been taught " + "how to do that on macOS.",
);
throw new Error("Can't copy multiple targets on this platform");
}
for (const f of files) {
const components = moduleInfo.moduleBuildDirs.map((dir) => path.join(dir, f));
const dst = path.join(moduleInfo.moduleOutDir, f);
await mkdirp(path.dirname(dst));
await new Promise<void>((resolve, reject) => {
childProcess.execFile("lipo", ["-create", "-output", dst, ...components], (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
} else {
console.log("Copying files from " + moduleInfo.moduleBuildDir + " to " + moduleInfo.moduleOutDir);
for (const f of files) {
console.log("\t" + f);
const src = path.join(moduleInfo.moduleBuildDir, f);
const dst = path.join(moduleInfo.moduleOutDir, f);
await mkdirp(path.dirname(dst));
await fsProm.copyFile(src, dst);
}
}
}
}
+24
View File
@@ -0,0 +1,24 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type HakEnv from "./hakEnv.ts";
export interface DependencyInfo {
name: string;
version: string;
cfg: Record<string, any>;
moduleHakDir: string;
moduleDotHakDir: string;
moduleTargetDotHakDir: string;
moduleBuildDir: string;
moduleBuildDirs: string[];
moduleOutDir: string;
nodeModuleBinDir: string;
depPrefix: string;
scripts: Record<string, (hakEnv: HakEnv, moduleInfo: DependencyInfo) => Promise<void>>;
}
+59
View File
@@ -0,0 +1,59 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import fsProm from "node:fs/promises";
import pacote from "pacote";
import path from "node:path";
import type HakEnv from "./hakEnv.ts";
import type { DependencyInfo } from "./dep.ts";
export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
let haveModuleBuildDir;
try {
const stats = await fsProm.stat(moduleInfo.moduleBuildDir);
haveModuleBuildDir = stats.isDirectory();
} catch {
haveModuleBuildDir = false;
}
if (haveModuleBuildDir) return;
console.log("Fetching " + moduleInfo.name + "@" + moduleInfo.version);
const packumentCache = new Map();
await pacote.extract(`${moduleInfo.name}@${moduleInfo.version}`, moduleInfo.moduleBuildDir, {
packumentCache,
});
// Workaround for us switching to pnpm but matrix-seshat still using yarn classic
const packageJsonPath = path.join(moduleInfo.moduleBuildDir, "package.json");
const packageJson = await fsProm.readFile(packageJsonPath, "utf-8");
const packageJsonData = JSON.parse(packageJson);
packageJsonData["packageManager"] = "yarn@1.22.22";
await fsProm.writeFile(packageJsonPath, JSON.stringify(packageJsonData, null, 2), "utf-8");
console.log("Running yarn install in " + moduleInfo.moduleBuildDir);
await hakEnv.spawn("yarn", ["install", "--ignore-scripts"], {
cwd: moduleInfo.moduleBuildDir,
});
// also extract another copy to the output directory at this point
// nb. we do not yarn install in the output copy: we could install in
// production mode to get only runtime dependencies and not devDependencies,
// but usually native modules come with dependencies that are needed for
// building/fetching the native modules (eg. node-pre-gyp) rather than
// actually used at runtime: we do not want to bundle these into our app.
// We therefore just install no dependencies at all, and accept that any
// actual runtime dependencies will have to be added to the main app's
// dependencies. We can't tell what dependencies are real runtime deps
// and which are just used for native module building.
await pacote.extract(`${moduleInfo.name}@${moduleInfo.version}`, moduleInfo.moduleOutDir, {
packumentCache,
});
}
+132
View File
@@ -0,0 +1,132 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import os from "node:os";
import { getElectronVersionFromInstalled } from "app-builder-lib/out/electron/electronVersion.js";
import childProcess, { type SpawnOptions } from "node:child_process";
import { type Arch, type Target, TARGETS, getHost, isHostId, type TargetId } from "./target.ts";
async function getRuntimeVersion(projectRoot: string): Promise<string> {
const electronVersion = await getElectronVersionFromInstalled(path.join(projectRoot, "..", ".."));
if (!electronVersion) {
throw new Error("Can't determine Electron version");
}
return electronVersion;
}
export type Tool = [cmd: string, ...args: string[]];
export default class HakEnv {
public readonly target: Target;
public runtime: string = "electron";
public runtimeVersion?: string;
public dotHakDir: string;
public readonly projectRoot: string;
public constructor(projectRoot: string, targetId: TargetId | null) {
this.projectRoot = projectRoot;
const target = targetId ? TARGETS[targetId] : getHost();
if (!target) {
throw new Error(`Unknown target ${targetId}!`);
}
this.target = target;
this.dotHakDir = path.join(this.projectRoot, ".hak");
}
public async init(): Promise<void> {
this.runtimeVersion = await getRuntimeVersion(this.projectRoot);
}
public getTargetId(): TargetId {
return this.target.id;
}
public isWin(): boolean {
return this.target.platform === "win32";
}
public isMac(): boolean {
return this.target.platform === "darwin";
}
public isLinux(): boolean {
return this.target.platform === "linux";
}
public isFreeBSD(): boolean {
return this.target.platform === "freebsd";
}
public getTargetArch(): Arch {
return this.target.arch;
}
public isHost(): boolean {
return isHostId(this.target.id);
}
public makeGypEnv(): Record<string, string | undefined> {
return {
...process.env,
npm_config_arch: this.target.arch,
npm_config_target_arch: this.target.arch,
npm_config_disturl: "https://electronjs.org/headers",
npm_config_runtime: this.runtime,
npm_config_target: this.runtimeVersion,
npm_config_build_from_source: "true",
npm_config_devdir: path.join(os.homedir(), ".electron-gyp"),
};
}
public wantsStaticSqlCipher(): boolean {
return !(this.isLinux() || this.isFreeBSD()) || process.env.SQLCIPHER_BUNDLED == "1";
}
public spawn(
cmd: string,
args: string[],
{ ignoreWinCmdlet, ...options }: SpawnOptions & { ignoreWinCmdlet?: boolean } = {},
): Promise<void> {
return new Promise((resolve, reject) => {
const proc = childProcess.spawn(cmd + (!ignoreWinCmdlet && this.isWin() ? ".cmd" : ""), args, {
stdio: "inherit",
// We need shell mode on Windows to be able to launch `.cmd` executables
// See https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2
shell: this.isWin(),
...options,
});
proc.on("error", (err) => {
reject(err);
});
proc.on("exit", (code) => {
if (code) {
reject(code);
} else {
resolve();
}
});
});
}
public async checkTools(tools: Tool[]): Promise<void> {
for (const [tool, ...args] of tools) {
try {
await this.spawn(tool, args, {
ignoreWinCmdlet: true,
stdio: ["ignore"],
shell: false,
});
} catch {
throw new Error(`Can't find ${tool}`);
}
}
}
}
+147
View File
@@ -0,0 +1,147 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path, { dirname } from "node:path";
import { fileURLToPath } from "node:url";
import HakEnv from "./hakEnv.ts";
import type { TargetId } from "./target.ts";
import type { DependencyInfo } from "./dep.ts";
import { loadJsonFile } from "../../src/utils.ts";
import packageJson from "../../package.json" with { type: "json" };
// These can only be run on specific modules
const MODULECOMMANDS = ["check", "fetch", "link", "build", "copy", "clean"];
// Shortcuts for multiple commands at once (useful for building universal binaries
// because you can run the fetch/build for each arch and then copy/link once)
const METACOMMANDS: Record<string, string[]> = {
fetchandbuild: ["check", "fetch", "build"],
copyandlink: ["copy", "link"],
};
// Scripts valid in a hak.json 'scripts' section
const HAKSCRIPTS = ["check", "fetch", "build"];
const __dirname = dirname(fileURLToPath(import.meta.url));
async function main(): Promise<void> {
const prefix = path.join(__dirname, "..", "..");
const targetIds: TargetId[] = [];
// Apply `--target <target>` option if specified
// Can be specified multiple times for the copy command to bundle
// multiple arches into a single universal output module)
for (;;) {
// eslint-disable-line no-constant-condition
const targetIndex = process.argv.indexOf("--target");
if (targetIndex === -1) break;
if (targetIndex + 1 >= process.argv.length) {
console.error("--target option specified without a target");
process.exit(1);
}
// Extract target ID and remove from args
targetIds.push(process.argv.splice(targetIndex, 2)[1] as TargetId);
}
const hakEnvs = targetIds.map((tid) => new HakEnv(prefix, tid));
if (hakEnvs.length == 0) hakEnvs.push(new HakEnv(prefix, null));
for (const h of hakEnvs) {
await h.init();
}
const hakEnv = hakEnvs[0];
const deps: Record<string, DependencyInfo> = {};
const hakDepsCfg = packageJson.hakDependencies || {};
for (const dep in hakDepsCfg) {
const hakJsonPath = path.join(prefix, "hak", dep, "hak.json");
let hakJson: Record<string, any>;
try {
hakJson = loadJsonFile(hakJsonPath);
} catch {
console.error("No hak.json found for " + dep + ".");
console.log("Expecting " + hakJsonPath);
process.exit(1);
}
deps[dep] = {
name: dep,
version: hakDepsCfg[dep as keyof typeof hakDepsCfg],
cfg: hakJson,
moduleHakDir: path.join(prefix, "hak", dep),
moduleDotHakDir: path.join(hakEnv.dotHakDir, dep),
moduleTargetDotHakDir: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId()),
moduleBuildDir: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId(), "build"),
moduleBuildDirs: hakEnvs.map((h) => path.join(h.dotHakDir, dep, h.getTargetId(), "build")),
moduleOutDir: path.join(hakEnv.dotHakDir, "hakModules", dep),
nodeModuleBinDir: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId(), "build", "node_modules", ".bin"),
depPrefix: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId(), "opt"),
scripts: {},
};
for (const s of HAKSCRIPTS) {
if (hakJson.scripts?.[s]) {
// Shockingly, using path.join and backslashes here doesn't work on Windows
const scriptModule = await import(`../../hak/${dep}/${hakJson.scripts[s]}`);
if (scriptModule.default) {
deps[dep].scripts[s] = scriptModule.default;
} else {
deps[dep].scripts[s] = scriptModule;
}
}
}
}
let cmds: string[];
if (process.argv.length < 3) {
cmds = ["check", "fetch", "build", "copy", "link"];
} else if (METACOMMANDS[process.argv[2]]) {
cmds = METACOMMANDS[process.argv[2]];
} else {
cmds = [process.argv[2]];
}
if (hakEnvs.length > 1 && cmds.some((c) => !["copy", "link"].includes(c))) {
// We allow link here too for convenience because it's completely arch independent
console.error("Multiple targets only supported with the copy command");
return;
}
let modules = process.argv.slice(3);
if (modules.length === 0) modules = Object.keys(deps);
for (const cmd of cmds) {
if (!MODULECOMMANDS.includes(cmd)) {
console.error("Unknown command: " + cmd);
console.log("Commands I know about:");
for (const cmd of MODULECOMMANDS) {
console.log("\t" + cmd);
}
process.exit(1);
}
const cmdFunc = (await import(`./${cmd}.ts`)).default;
for (const mod of modules) {
const depInfo = deps[mod];
if (depInfo === undefined) {
console.log("Module " + mod + " not found - is it in hakDependencies " + "in your package.json?");
process.exit(1);
}
console.log("hak " + cmd + ": " + mod);
await cmdFunc(hakEnv, depInfo);
}
}
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
+16
View File
@@ -0,0 +1,16 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type HakEnv from "./hakEnv.ts";
import { type DependencyInfo } from "./dep.ts";
export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
await hakEnv.spawn("pnpm", ["link", moduleInfo.moduleOutDir], {
cwd: hakEnv.projectRoot,
});
}
+217
View File
@@ -0,0 +1,217 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { GLIBC, MUSL, familySync as processLibC } from "detect-libc";
// We borrow Rust's target naming scheme as a way of expressing all target
// details in a single string.
// See https://doc.rust-lang.org/rustc/platform-support.html.
export type TargetId =
| "aarch64-apple-darwin"
| "x86_64-apple-darwin"
| "universal-apple-darwin"
| "i686-pc-windows-msvc"
| "x86_64-pc-windows-msvc"
| "aarch64-pc-windows-msvc"
| "i686-unknown-freebsd"
| "x86_64-unknown-freebsd"
| "aarch64-unknown-freebsd"
| "i686-unknown-linux-musl"
| "i686-unknown-linux-gnu"
| "x86_64-unknown-linux-musl"
| "x86_64-unknown-linux-gnu"
| "aarch64-unknown-linux-musl"
| "aarch64-unknown-linux-gnu"
| "powerpc64le-unknown-linux-musl"
| "powerpc64le-unknown-linux-gnu";
// Values are expected to match those used in `process.platform`.
export type Platform = "darwin" | "freebsd" | "linux" | "win32";
// Values are expected to match those used in `process.arch`.
export type Arch = "arm64" | "ia32" | "x64" | "ppc64" | "universal";
// Values are expected to match those used by Visual Studio's `vcvarsall.bat`.
// See https://docs.microsoft.com/cpp/build/building-on-the-command-line?view=msvc-160#vcvarsall-syntax
export type VcVarsArch = "amd64" | "arm64" | "x86";
export type Target = {
id: TargetId;
platform: Platform;
arch: Arch;
};
export type WindowsTarget = Target & {
platform: "win32";
vcVarsArch: VcVarsArch;
};
export type LinuxTarget = Target & {
platform: "linux";
libC: typeof GLIBC | typeof MUSL;
};
export type UniversalTarget = Target & {
arch: "universal";
subtargets: Target[];
};
const aarch64AppleDarwin: Target = {
id: "aarch64-apple-darwin",
platform: "darwin",
arch: "arm64",
};
const x8664AppleDarwin: Target = {
id: "x86_64-apple-darwin",
platform: "darwin",
arch: "x64",
};
const universalAppleDarwin: UniversalTarget = {
id: "universal-apple-darwin",
platform: "darwin",
arch: "universal",
subtargets: [aarch64AppleDarwin, x8664AppleDarwin],
};
const i686PcWindowsMsvc: WindowsTarget = {
id: "i686-pc-windows-msvc",
platform: "win32",
arch: "ia32",
vcVarsArch: "x86",
};
const x8664PcWindowsMsvc: WindowsTarget = {
id: "x86_64-pc-windows-msvc",
platform: "win32",
arch: "x64",
vcVarsArch: "amd64",
};
const aarch64WindowsMsvc: WindowsTarget = {
id: "aarch64-pc-windows-msvc",
platform: "win32",
arch: "arm64",
vcVarsArch: "arm64",
};
const i686UnknownFreebsd: Target = {
id: "i686-unknown-freebsd",
platform: "freebsd",
arch: "ia32",
};
const x8664UnknownFreebsd: Target = {
id: "x86_64-unknown-freebsd",
platform: "freebsd",
arch: "x64",
};
const aarch64UnknownFreebsd: Target = {
id: "aarch64-unknown-freebsd",
platform: "freebsd",
arch: "arm64",
};
const x8664UnknownLinuxGnu: LinuxTarget = {
id: "x86_64-unknown-linux-gnu",
platform: "linux",
arch: "x64",
libC: GLIBC,
};
const x8664UnknownLinuxMusl: LinuxTarget = {
id: "x86_64-unknown-linux-musl",
platform: "linux",
arch: "x64",
libC: MUSL,
};
const i686UnknownLinuxGnu: LinuxTarget = {
id: "i686-unknown-linux-gnu",
platform: "linux",
arch: "ia32",
libC: GLIBC,
};
const i686UnknownLinuxMusl: LinuxTarget = {
id: "i686-unknown-linux-musl",
platform: "linux",
arch: "ia32",
libC: MUSL,
};
const aarch64UnknownLinuxGnu: LinuxTarget = {
id: "aarch64-unknown-linux-gnu",
platform: "linux",
arch: "arm64",
libC: GLIBC,
};
const aarch64UnknownLinuxMusl: LinuxTarget = {
id: "aarch64-unknown-linux-musl",
platform: "linux",
arch: "arm64",
libC: MUSL,
};
const powerpc64leUnknownLinuxGnu: LinuxTarget = {
id: "powerpc64le-unknown-linux-gnu",
platform: "linux",
arch: "ppc64",
libC: GLIBC,
};
const powerpc64leUnknownLinuxMusl: LinuxTarget = {
id: "powerpc64le-unknown-linux-musl",
platform: "linux",
arch: "ppc64",
libC: MUSL,
};
export const TARGETS: Record<TargetId, Target> = {
// macOS
"aarch64-apple-darwin": aarch64AppleDarwin,
"x86_64-apple-darwin": x8664AppleDarwin,
"universal-apple-darwin": universalAppleDarwin,
// Windows
"i686-pc-windows-msvc": i686PcWindowsMsvc,
"x86_64-pc-windows-msvc": x8664PcWindowsMsvc,
"aarch64-pc-windows-msvc": aarch64WindowsMsvc,
// FreeBSD
"i686-unknown-freebsd": i686UnknownFreebsd,
"x86_64-unknown-freebsd": x8664UnknownFreebsd,
"aarch64-unknown-freebsd": aarch64UnknownFreebsd,
// Linux
"i686-unknown-linux-musl": i686UnknownLinuxMusl,
"i686-unknown-linux-gnu": i686UnknownLinuxGnu,
"x86_64-unknown-linux-musl": x8664UnknownLinuxMusl,
"x86_64-unknown-linux-gnu": x8664UnknownLinuxGnu,
"aarch64-unknown-linux-musl": aarch64UnknownLinuxMusl,
"aarch64-unknown-linux-gnu": aarch64UnknownLinuxGnu,
"powerpc64le-unknown-linux-musl": powerpc64leUnknownLinuxMusl,
"powerpc64le-unknown-linux-gnu": powerpc64leUnknownLinuxGnu,
};
export function getHost(): Target | undefined {
return Object.values(TARGETS).find(
(target) =>
target.platform === process.platform &&
target.arch === process.arch &&
(process.platform !== "linux" || (target as LinuxTarget).libC === processLibC()),
);
}
export function isHostId(id: TargetId): boolean {
return getHost()?.id === id;
}
export function isHost(target: Target): boolean {
return getHost()?.id === target.id;
}
+30
View File
@@ -0,0 +1,30 @@
#!/bin/bash
set -e
cd $(dirname "$0")/..
IMAGE=${DOCKER_IMAGE_NAME:-"element-desktop-dockerbuild"}
docker inspect "$IMAGE" 2> /dev/null > /dev/null
if [ $? != 0 ]; then
echo "Docker image $IMAGE not found. Have you run pnpm run docker:setup?"
exit 1
fi
mkdir -p docker/node_modules docker/.hak docker/.gnupg
# Taken from https://www.electron.build/multi-platform-build#docker
# Pass through any vars prefixed with INDOCKER_, removing the prefix
docker run --rm -ti \
--platform linux/amd64 \
--env-file <(env | grep -E '^INDOCKER_' | sed -e 's/^INDOCKER_//') \
--env ELECTRON_CACHE="/root/.cache/electron" \
--env ELECTRON_BUILDER_CACHE="/root/.cache/electron-builder" \
-v ${PWD}:/project \
-v ${PWD}/docker/node_modules:/project/node_modules \
-v ${PWD}/docker/.hak:/project/.hak \
-v ${PWD}/docker/.gnupg:/root/.gnupg \
-v ~/.cache/electron:/root/.cache/electron \
-v ~/.cache/electron-builder:/root/.cache/electron-builder \
"$IMAGE" "$@"
+73
View File
@@ -0,0 +1,73 @@
#!/usr/bin/env node
/*
* Checks for the presence of a webapp, inspects its version and sets the
* version metadata of the package to match.
*/
import { promises as fs } from "node:fs";
import * as asar from "@electron/asar";
import * as childProcess from "node:child_process";
import * as url from "node:url";
export async function versionFromAsar(): Promise<string> {
try {
await fs.stat("webapp.asar");
} catch {
throw new Error("No 'webapp.asar' found. Run 'pnpm run fetch'");
}
return asar.extractFile("webapp.asar", "version").toString().trim();
}
export async function setPackageVersion(ver: string): Promise<void> {
// set version in package.json: electron-builder will use this to populate
// all the various version fields
await new Promise<void>((resolve, reject) => {
childProcess.execFile(
process.platform === "win32" ? "pnpm.cmd" : "pnpm",
[
"version",
"-s",
"--no-git-tag-version", // This also means "don't commit to git" as it turns out
"--new-version",
ver,
],
{
// We need shell mode on Windows to be able to launch `.cmd` executables
// See https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2
shell: process.platform === "win32",
},
(err) => {
if (err) {
reject(err);
} else {
resolve();
}
},
);
});
}
async function main(args: string[]): Promise<number> {
let version = args[0];
if (version === undefined) version = await versionFromAsar();
await setPackageVersion(version);
return 0;
}
if (import.meta.url.startsWith("file:")) {
const modulePath = url.fileURLToPath(import.meta.url);
if (process.argv[1] === modulePath) {
main(process.argv.slice(2))
.then((ret) => {
process.exit(ret);
})
.catch((e) => {
console.error(e);
process.exit(1);
});
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"resolveJsonModule": true,
"moduleResolution": "node16",
"skipLibCheck": true,
"esModuleInterop": true,
"target": "es2022",
"module": "node20",
"sourceMap": false,
"strict": true,
"lib": ["es2022"],
"types": ["node"],
"allowImportingTsExtensions": true
},
"include": ["../src/@types", "./**/*.ts"]
}
+22
View File
@@ -0,0 +1,22 @@
/*
Copyright 2021-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { type BrowserWindow } from "electron";
import { type AppLocalization } from "../language-helper.js";
// global type extensions need to use var for whatever reason
/* eslint-disable no-var */
declare global {
type IConfigOptions = Record<string, any>;
var mainWindow: BrowserWindow | null;
var appQuitting: boolean;
var appLocalization: AppLocalization;
var vectorConfig: IConfigOptions;
}
/* eslint-enable no-var */
+136
View File
@@ -0,0 +1,136 @@
/*
Copyright 2022-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
declare module "matrix-seshat" {
interface IConfig {
language?: string;
passphrase?: string;
}
/* eslint-disable camelcase */
interface IMatrixEvent {
event_id: string;
sender: string;
room_id: string;
origin_server_ts: number;
content: Record<string, any>;
}
interface IMatrixProfile {
displayname?: string;
avatar_url?: string;
}
interface ISearchArgs {
searchTerm: number;
limit: number;
before_limit: number;
after_limit: number;
order_by_recency: boolean;
next_batch?: string;
}
interface ISearchContext {
events_before: IMatrixEvent[];
events_after: IMatrixEvent[];
profile_info: { [userId: string]: IMatrixProfile };
}
interface ISearchResult {
next_batch: string;
count: number;
results: Array<{
rank: number;
result: IMatrixEvent;
context: ISearchContext;
}>;
}
/* eslint-enable camelcase */
interface ICheckpoint {
roomId: string;
token: string;
fullCrawl: boolean;
direction: "b" | "f";
}
interface IDatabaseStats {
size: number;
eventCount: number;
roomCount: number;
}
interface ILoadArgs {
roomId: string;
limit: number;
fromEvent: string;
direction: "b" | "f";
}
interface ILoadResult {
event: IMatrixEvent;
matrixProfile: IMatrixProfile;
}
export class Seshat {
public constructor(path: string, config?: IConfig);
public addEvent(matrixEvent: IMatrixEvent, profile?: IMatrixProfile): void;
public deleteEvent(eventId: string): Promise<boolean>;
public commit(force?: boolean): Promise<number>;
public commitSync(wait?: boolean, force?: boolean): number;
public reload(): void;
public search(args: ISearchArgs): Promise<ISearchResult>;
public searchSync(
term: string,
limit?: number,
beforeLimit?: number,
afterLimit?: number,
orderByRecency?: boolean,
): ISearchResult;
public addHistoricEventsSync(
events: IMatrixEvent[],
newCheckpoint?: ICheckpoint,
oldCheckpoint?: ICheckpoint,
): boolean;
public addHistoricEvents(
events: IMatrixEvent[],
newCheckpoint?: ICheckpoint,
oldCheckpoint?: ICheckpoint,
): Promise<boolean>;
public addCrawlerCheckpoint(checkpoint: ICheckpoint): Promise<void>;
public removeCrawlerCheckpoint(checkpoint: ICheckpoint): Promise<void>;
public loadCheckpoints(): Promise<ICheckpoint[]>;
public getSize(): Promise<number>;
public getStats(): Promise<IDatabaseStats>;
public delete(): Promise<void>;
public shutdown(): Promise<void>;
public changePassphrase(newPassphrase: string): Promise<void>;
public isEmpty(): Promise<boolean>;
public isRoomIndexed(roomId: string): Promise<boolean>;
public getUserVersion(): Promise<number>;
public setUserVersion(version: number): Promise<void>;
public loadFileEvents(args: ILoadArgs): Promise<ILoadResult[]>;
}
interface IRecoveryInfo {
totalEvents: number;
reindexedEvents: number;
done: number;
}
export class SeshatRecovery {
public constructor(path: string, config?: IConfig);
public info(): IRecoveryInfo;
public getUserVersion(): Promise<number>;
public shutdown(): Promise<void>;
public reindex(): Promise<void>;
}
export class ReindexError extends Error {
public constructor(message?: string);
}
}

Some files were not shown because too many files have changed in this diff Show More