Projekte / Delta Chat Desktop

Delta Chat Desktop

TypeScriptElectronReact
Screenshot von Delta Chat Desktop mit einem Gruppenchat

Über dieses Projekt

Delta Chat ist ein dezentraler, verschlüsselter Messenger, der über Standard-E-Mail funktioniert. Der Desktop-Client ist eine Electron/React-App, die für Windows, macOS und Linux (einschließlich Flathub, Mac App Store und Microsoft Store) ausgeliefert wird.

Ich bin Ende 2018 zum kleinen Desktop-Team (2-5 Personen über die Jahre) gestoßen und habe nach und nach mehr Verantwortung übernommen, bis ich zum De-facto-Lead wurde - zuerst zusammen mit jikstra, dann allein nach seinem Weggang vom Desktop-Team 2022. Im Frühjahr 2024 begann Nico mich abzulösen, und wir schlossen den Übergang 2025 ab. Meine letzte große Initiative war das DeltaTauri-Projekt - ein NLnet-geförderter Prototyp zur Portierung der App von Electron auf Tauri.

Technische Herausforderungen

Zähmung der Binding-Schichten

Die ursprüngliche Architektur hatte zu viele Schichten: eine C-Core-Bibliothek, über NAPI-Bindings gewrappt, nochmal in ein JS-Modul gewrappt, aufgerufen von Electrons Main-Prozess, der alles an den Renderer weiterleitete. Jede Methode wurde auf jeder Schicht neu definiert. Schlimmer noch: Wir konnten den C-Core unter Windows überhaupt nicht linken, was die App dort lange blockiert hatte.

Der C-Core wurde schließlich in Rust umgeschrieben (über c2rust1, dann 1,5 Jahre manuelles Aufräumen), was das Windows-Problem sofort löste - Rusts Tooling kann Cross-Compilation deutlich besser. Aber die geschichteten NAPI/CFFI-Bindings und ihre Wiederholungen blieben. Ich habe schließlich eine JSON-RPC-API eingeführt mit auto-generierten TypeScript-Bindings - einmal in Rust definieren, direkt in TypeScript nutzen. Später, während des DeltaTauri-Projekts, haben wir die NAPI-Schicht komplett durch ein stdio-basiertes RPC-Binary ersetzt2 - bis dahin lief die JSON-RPC-API noch über die alte CFFI-Schicht. Ich habe einen Blogpost über den Weg dahin geschrieben.

Nachrichtenliste und Chatlisten-Performance

Die Nachrichtenliste schnell und fehlerfrei zu bekommen brauchte mehrere Anläufe. Virtualisierungs-Bibliotheken unterstützten damals keine dynamisch-hohen Elemente beim Scrollen von unten nach oben (was bei Chat-Apps üblich ist), also nutzten wir stattdessen einen Paginierungs-Ansatz. Aber Nachrichten als diskrete Seiten zu behandeln brachte eigene Bugs: Seiten die nicht laden, doppelte Nachrichten, Zustand der sich beim Löschen nicht aktualisiert. Wir behielten schließlich den Batch-Lademechanismus, ließen aber die Seiten-Abstraktion fallen und behandelten alles als eine einzige flache Liste. Später hat WofWca einen Deep Dive in die verbleibenden Edge Cases gemacht und viele subtile Bugs behoben.

Webxdc-Sandboxing

Delta Chat unterstützt webxdc-Apps. Das sind kleine Web-Apps, die im Messenger ohne Internetzugriff laufen. Herauszufinden, wie man nicht vertrauenswürdige, nutzergenerierte Inhalte in Electron richtig sandboxen kann, war eine erhebliche Herausforderung. Diese Arbeit setzte sich später im DeltaTauri-Projekt fort, wo Tauris Capability-basiertes Berechtigungssystem ein natürlicheres Modell für das Sandboxing bot.

Supply-Chain-Bewusstsein

Wir haben die Anzahl der Abhängigkeiten bewusst niedrig gehalten. Das war ein generelles Prinzip, wurde aber sehr real, als eine Abhängigkeit unseres Test-Frameworks (TestCafe) zu Beginn des Ukrainekriegs von ihrem eigenen Maintainer sabotiert wurde: Der Code löschte Dateien auf Systemen, die er Russland zuordnete, und hinterlegte auf allen anderen eine Protestnachricht. Eines Tages fand ich eine be glad that you are not russian-Textdatei auf meinem Desktop. Wir haben uns schließlich von TestCafe verabschiedet.

Architekturentscheidungen

Ich habe mich stark für die Einführung von TypeScript und später für die Aktivierung des Strict-Modus (noImplicitAny und strictNullChecks) eingesetzt. Das hat sich enorm ausgezahlt, als die Codebasis wuchs. Ich habe auch den Wechsel von der geschichteten NAPI-Binding-Architektur zur JSON-RPC-API vorangetrieben, was eine der wirkungsvollsten Änderungen war - es vereinfachte die Codebasis und ermöglichte es, neue Frontends zu unterstützen, ohne neue Bindings schreiben zu müssen.

Distribution und Releases

Die Auslieferung an den Mac App Store, Microsoft Store und Flathub bedeutete den Umgang mit Review-Zyklen, ablaufenden Zertifikaten und plattformspezifischen Build-Eigenheiten. Flathub verlangt vollständig offline Builds auf ihren Runnern, was viel Kopfzerbrechen verursachte - Iterationszyklen sind langsam3, und man muss deren Build-System verstehen. Positiv ist, dass die Flathub-Maintainer sehr hilfsbereit sind, wenn man fragt.

Wir haben stark in die Automatisierung des Release-Prozesses investiert, aber er erforderte trotzdem manuelle Eingriffe: Test-Releases, Last-Minute-Bugfixes, Entscheidungen welche PRs ins Release-Fenster kommen, und Kommunikation mit Testern. Wir hatten einen hohen Qualitätsanspruch an Releases, was bedeutete, dass der Prozess nie vollständig automatisch lief.

Was ich gelernt habe

Das war mein erstes Projekt in einem Team aus echten Entwicklern, und es hat mir weit über reinen Code hinaus viel beigebracht. React, Rust, verschiedene Bundler und Build-Tools, Issue-Gardening, wie man mit Menschen über verschiedene Zeitzonen und circadiane Rhythmen4 hinweg zusammenarbeitet, und wie man ein langlebiges Open-Source-Projekt pflegt, ohne auszubrennen - wobei mir Letzteres nicht immer gelungen ist. Ich war auch im breiteren Delta-Chat-Ökosystem aktiv (Community-Forum, webxdc, Bots, Chatmail), was bereichernd war, aber zeitweise schlicht etwas zu viel.


  1. c2rust ist ein automatisierter C-zu-Rust-Transpiler. Er erzeugt funktionierenden, aber nicht-idiomatischen Rust-Code, der dann manuell aufgeräumt werden muss.
  2. Das betrifft die Electron-Version. Die Tauri-Edition bindet den Rust-Core direkt ein, da Tauri ebenfalls in Rust geschrieben ist.
  3. Man kann flatpak-builder lokal ausführen, und das habe ich irgendwann auch gemacht, aber die Iteration ist trotzdem langsam - man braucht einen schnellen Linux-Rechner, da das Tool nicht für macOS gemacht ist.
  4. Ich war selbst eine ganze Weile eine Nachteule, besonders in den frühen Jahren.