Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d17c40e79f | ||
|
|
7c857bea1e | ||
|
|
f2db3b1b3e | ||
|
|
5efd214ebe | ||
|
|
e988465906 | ||
|
|
effa27da3d | ||
|
|
8d80ebf4c2 | ||
|
|
0914339180 | ||
|
|
9fcbd410f2 | ||
|
|
d76d276da4 | ||
|
|
8d47df711d | ||
|
|
9baafd4928 | ||
|
|
97d9416b01 | ||
|
|
9c5a183025 | ||
|
|
1dccca914c |
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Jared Vititoe
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -111,7 +111,7 @@ matrix/
|
||||
- Build log: `/var/log/cinny-build.log`
|
||||
- Nginx site config: `/etc/nginx/sites-available/cinny` (copy in this repo: `cinny/nginx.conf`, synced with live on 2026-09-23)
|
||||
- Nginx security headers: `/etc/nginx/snippets/cinny-security-headers.conf` (`cinny/nginx-security-headers.conf`). Included at server level **and** in every `location` that sets its own `add_header`; nginx drops inherited `add_header`s in such blocks, which left static assets without `nosniff` and `/sw.js` without its CSP (cinny #210). Edit the CSP here, not in the site config. **Exception:** `/public/element-call/` (the bundled Element Call, which the app itself frames) uses `cinny-security-headers-framed.conf` (`cinny/nginx-security-headers-framed.conf`), the same headers **without** the CSP. The app CSP's `frame-ancestors 'none'` would block every web call.
|
||||
- ⚠️ The `matrix-deploy` hook on 106 has been unreachable since May (webhook bound to `127.0.0.1:9000`), so edits to these files in the repo are **not** auto-deployed there. Apply them by hand (`nginx -t` then `nginx -s reload`) and keep the repo copy in sync.
|
||||
- The `matrix-deploy` hook on 106 is served by `webhook-lotus` on `10.10.10.6:9001` (Gitea hook → `http://10.10.10.6:9001/hooks/matrix-deploy`). It was pointed at `:9000` until 2026-09-28, which is bound to `127.0.0.1`, so nothing deployed from May to then (matrix #13). `cinny/config.json` is **merged** into the live file (server-injected values such as `gifApiKey` are kept), and the script installs its own updates (`deploy/lxc106-cinny.sh` → `/usr/local/bin/matrix-deploy.sh`).
|
||||
|
||||
---
|
||||
|
||||
@@ -132,7 +132,7 @@ Pushes to `main` on `LotusGuild/matrix` automatically deploy to the relevant LXC
|
||||
| LXC | Service | IP | Port | Deploys When Changed |
|
||||
|-----|---------|----|----|----------------------|
|
||||
| 151 | matrix/hookshot | 10.10.10.29 | **9500** | `hookshot/*.js`, `systemd/livekit-server.service`, `livekit/voice-limit-guard.py`, `systemd/voice-limit-guard.service`, `matrixbot/*` |
|
||||
| 106 | cinny | 10.10.10.6 | 9000 | `cinny/config.json`, `cinny/upstream-check.sh`, `cinny/lotus-build.sh`, `deploy/hooks-lxc106.json`, `systemd/cinny-upstream-check.cron` |
|
||||
| 106 | cinny | 10.10.10.6 | 9001 | `cinny/config.json` (merged), `cinny/nginx.conf`, `cinny/upstream-check.sh`, `cinny/lotus-build.sh`, `cinny/lotus_deploy.sh`, `deploy/hooks-lxc106.json`, `deploy/lxc106-cinny.sh` (self), `systemd/cinny-upstream-check.cron` |
|
||||
| 139 | landing/NPM | 10.10.10.27 | 9000 | `landing/index.html` |
|
||||
| 110 | draupnir | 10.10.10.24 | 9000 | `draupnir/production.yaml` |
|
||||
|
||||
@@ -352,6 +352,8 @@ Webhook URL format: `https://matrix.lotusguild.org/webhook/<uuid>`
|
||||
| Owncast (Livestream) | `9993e911-c68b-4271-a178-c2d65ca88499` | STREAM_STARTED / STREAM_STOPPED |
|
||||
| Bazarr | `470fb267-3436-4dd3-a70c-e6e8db1721be` | Subtitle events (Apprise JSON notifier) |
|
||||
| Tinker-Tickets | `6e306faf-8eea-4ba5-83ef-bf8f421f929e` | Custom transformation code |
|
||||
| Ci-Alert | `5e7051e7-fd0c-4930-a711-9c67daf6f0b9` | Gitea Actions `notify-failure` jobs (org secret `MATRIX_WEBHOOK_URL`); transform `hookshot/ci-alert.js` |
|
||||
| Devdesk | `4a3ccfc9-e1fe-4124-b014-7842fe51b9dc` | DevDesk "Claude needs you" (CT 126 `devdesk-notify-matrix`, URL in `/etc/devdesk/matrix-webhook`); transform `hookshot/devdesk.js`; avatar set via the appservice token |
|
||||
|
||||
**Hookshot notes:**
|
||||
- Spam and Stuff is intentionally **unencrypted** — hookshot bridges cannot join E2EE rooms
|
||||
@@ -361,6 +363,7 @@ Webhook URL format: `https://matrix.lotusguild.org/webhook/<uuid>`
|
||||
- NPM proxies `/sfu/get` and `/get_token` → `http://10.10.10.29:8070` (lk-jwt-service). Both paths are in `/data/nginx/proxy_host/49.conf` on LXC 139 — **NPM will overwrite these if proxy host 49 is re-saved via the UI; re-add both location blocks after any NPM save**
|
||||
- Proxmox sends Discord embed format: `data.embeds[0].{title,description,fields}` — NOT flat fields
|
||||
- Transform functions are stored as Matrix room state (`uk.half-shot.matrix-hookshot.generic.hook`) and deployed via `hookshot/deploy.sh`
|
||||
- Hook UUIDs are **not** in that state. Hookshot creates them and keeps a `{uuid: name}` map in the `@hookshot` bot's room account data (same event type). Deploying a new transform creates the hook. To look a UUID up on LXC 151, use the appservice token from `/etc/matrix-synapse/hookshot-registration.yaml`: `GET /_matrix/client/v3/user/@hookshot:matrix.lotusguild.org/rooms/<room>/account_data/uk.half-shot.matrix-hookshot.generic.hook?user_id=@hookshot:matrix.lotusguild.org`
|
||||
|
||||
**Deploying hookshot transforms manually:**
|
||||
```bash
|
||||
|
||||
+14
-2
@@ -16,5 +16,17 @@
|
||||
"enabled": false,
|
||||
"basename": "/"
|
||||
},
|
||||
"gifApiKey": ""
|
||||
}
|
||||
"gifApiKey": "",
|
||||
"elementCallUrl": "https://call.chat.lotusguild.org/public/element-call/index.html",
|
||||
"statusPages": {
|
||||
"matrix.lotusguild.org": {
|
||||
"url": "https://isitup.lotusguild.org",
|
||||
"slug": "matrix",
|
||||
"groups": {
|
||||
"homeserver": "Homeserver",
|
||||
"calls": "Voice calls",
|
||||
"login": "Login"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Headers for the Element Call page on its own origin, call.chat.lotusguild.org
|
||||
# (cinny #43). Installed on LXC 106 as /etc/nginx/snippets/cinny-security-headers-call.conf
|
||||
# (deploy/lxc106-cinny.sh does NOT copy snippets — install by hand, like the others).
|
||||
#
|
||||
# frame-ancestors: only the web app may frame the call page (replaces
|
||||
# X-Frame-Options SAMEORIGIN, which would block the now cross-origin parent;
|
||||
# browsers honour frame-ancestors over X-Frame-Options anyway).
|
||||
# Permissions-Policy: "self" here is the call origin, which is what uses the
|
||||
# mic/camera/screen; the app's own policy delegates them to this origin.
|
||||
add_header Content-Security-Policy "frame-ancestors https://chat.lotusguild.org" always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header Referrer-Policy strict-origin-when-cross-origin always;
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
|
||||
add_header Permissions-Policy "accelerometer=(), autoplay=(self), camera=(self), display-capture=(self), encrypted-media=(self), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(self), midi=(), payment=(), usb=()" always;
|
||||
@@ -3,10 +3,13 @@
|
||||
# nginx drops inherited add_header directives in any block that defines one,
|
||||
# so without the include, static assets lost nosniff and /sw.js lost its CSP
|
||||
# (a service worker's CSP comes from its own script response). cinny #210.
|
||||
# Permissions-Policy delegates autoplay/camera/display-capture/microphone to the
|
||||
# call page's own origin (call.chat.lotusguild.org, cinny #43); without it the
|
||||
# cross-origin call frame's getUserMedia is refused (NotAllowedError).
|
||||
add_header X-Frame-Options SAMEORIGIN always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy strict-origin-when-cross-origin always;
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
|
||||
add_header Permissions-Policy "accelerometer=(), autoplay=(self), camera=(self), display-capture=(self), encrypted-media=(self), fullscreen=(self), geolocation=(self), gyroscope=(), magnetometer=(), microphone=(self), midi=(), payment=(), usb=()" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https://matrix.lotusguild.org https://matrix.org https://*.matrix.org https://mozilla.org https://mozilla.modular.im https://drive.lotusguild.org https://media.giphy.com https://media0.giphy.com https://media1.giphy.com https://media2.giphy.com https://media3.giphy.com https://media4.giphy.com https://www.openstreetmap.org https://tile.openstreetmap.org; font-src 'self' data:; connect-src 'self' https://matrix.lotusguild.org wss://matrix.lotusguild.org https://matrix.org https://*.matrix.org https://mozilla.org https://mozilla.modular.im https://chat.mozilla.org https://vector.im https://api.giphy.com https://*.giphy.com wss:; media-src 'self' https: blob:; frame-src 'self' https:; worker-src 'self' blob:; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" always;
|
||||
add_header Permissions-Policy 'accelerometer=(), autoplay=(self "https://call.chat.lotusguild.org"), camera=(self "https://call.chat.lotusguild.org"), display-capture=(self "https://call.chat.lotusguild.org"), encrypted-media=(self), fullscreen=(self), geolocation=(self), gyroscope=(), magnetometer=(), microphone=(self "https://call.chat.lotusguild.org"), midi=(), payment=(), usb=()' always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https://matrix.lotusguild.org https://matrix.org https://*.matrix.org https://mozilla.org https://mozilla.modular.im https://drive.lotusguild.org https://media.giphy.com https://media0.giphy.com https://media1.giphy.com https://media2.giphy.com https://media3.giphy.com https://media4.giphy.com https://www.openstreetmap.org https://tile.openstreetmap.org; font-src 'self' data:; connect-src 'self' https://matrix.lotusguild.org wss://matrix.lotusguild.org https://isitup.lotusguild.org https://matrix.org https://*.matrix.org https://mozilla.org https://mozilla.modular.im https://chat.mozilla.org https://vector.im https://api.giphy.com https://*.giphy.com wss:; media-src 'self' https: blob:; frame-src 'self' https:; worker-src 'self' blob:; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';" always;
|
||||
|
||||
@@ -108,3 +108,53 @@ server {
|
||||
rewrite ^(.+)$ /index.html break;
|
||||
}
|
||||
}
|
||||
|
||||
# [cinny #43] Element Call on its own origin. The web app frames
|
||||
# https://call.chat.lotusguild.org/public/element-call/index.html (config.json
|
||||
# `elementCallUrl`), so the call page can no longer read the app's storage
|
||||
# (login token, crypto store) or use its service worker. Serves ONLY the call
|
||||
# page — the same files as chat.lotusguild.org/public/element-call/ — and 404s
|
||||
# everything else, so this hostname exposes nothing new.
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name call.chat.lotusguild.org;
|
||||
|
||||
brotli on;
|
||||
brotli_static on;
|
||||
brotli_comp_level 6;
|
||||
brotli_types text/plain text/css application/javascript application/json
|
||||
image/svg+xml application/wasm font/woff2;
|
||||
|
||||
root /var/www/html;
|
||||
server_tokens off;
|
||||
limit_req zone=chat_limit burst=60 nodelay;
|
||||
limit_conn chat_conn 25;
|
||||
|
||||
include snippets/cinny-security-headers-call.conf;
|
||||
|
||||
location ^~ /public/element-call/ {
|
||||
include snippets/cinny-security-headers-call.conf;
|
||||
location ~* \.map$ {
|
||||
return 404;
|
||||
}
|
||||
location ~ /\. {
|
||||
return 404;
|
||||
}
|
||||
location ~* \.html$ {
|
||||
include snippets/cinny-security-headers-call.conf;
|
||||
expires -1;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
|
||||
}
|
||||
location ~* \.(?:js|css|woff2?|png|svg|ico|webp|wasm)$ {
|
||||
include snippets/cinny-security-headers-call.conf;
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable" always;
|
||||
}
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 404;
|
||||
}
|
||||
}
|
||||
|
||||
+53
-5
@@ -3,7 +3,8 @@
|
||||
# Handles: cinny/config.json, cinny/nginx.conf, cinny/upstream-check.sh,
|
||||
# cinny/lotus-build.sh, cinny/lotus_deploy.sh,
|
||||
# deploy/hooks-lxc106.json, systemd/cinny-upstream-check.cron
|
||||
# Triggered by: Gitea webhook on push to main
|
||||
# Triggered by: Gitea webhook on push to main → http://10.10.10.6:9001/hooks/matrix-deploy
|
||||
# (webhook-lotus; the :9000 listener is bound to 127.0.0.1 and unreachable).
|
||||
set -euo pipefail
|
||||
|
||||
REPO_DIR="/opt/matrix-config"
|
||||
@@ -27,9 +28,39 @@ else
|
||||
fi
|
||||
|
||||
if echo "$CHANGED" | grep -q '^cinny/config.json'; then
|
||||
echo "Deploying cinny config.json..."
|
||||
cp "$REPO_DIR/cinny/config.json" /var/www/html/config.json
|
||||
echo "✓ config.json deployed"
|
||||
echo "Deploying cinny config.json (merged: keeps server-only values)..."
|
||||
# The live file carries values injected on the server that are empty in git
|
||||
# (gifApiKey, set by lotus_deploy.sh from GIPHY_API_KEY). A plain copy would
|
||||
# blank them, so repo keys win except where the repo value is empty and the
|
||||
# live one isn't. Backup outside the web root; on any error the live file
|
||||
# is left untouched.
|
||||
mkdir -p /root/config-backups
|
||||
cp -p /var/www/html/config.json "/root/config-backups/config.json.$(date +%Y%m%d%H%M%S)" 2>/dev/null || true
|
||||
if python3 - "$REPO_DIR/cinny/config.json" /var/www/html/config.json <<'PY'
|
||||
import json, os, sys, tempfile
|
||||
repo_path, live_path = sys.argv[1], sys.argv[2]
|
||||
repo = json.load(open(repo_path))
|
||||
live = json.load(open(live_path)) if os.path.exists(live_path) else {}
|
||||
merged = dict(repo)
|
||||
kept = []
|
||||
for key, value in live.items():
|
||||
if key in repo and repo[key] in ("", None) and value not in ("", None):
|
||||
merged[key] = value
|
||||
kept.append(key)
|
||||
fd, tmp = tempfile.mkstemp(dir=os.path.dirname(live_path))
|
||||
with os.fdopen(fd, "w") as f:
|
||||
json.dump(merged, f, indent=2)
|
||||
f.write("\n")
|
||||
json.load(open(tmp))
|
||||
os.chmod(tmp, 0o644)
|
||||
os.replace(tmp, live_path)
|
||||
print("kept server values for: " + (", ".join(kept) or "none"))
|
||||
PY
|
||||
then
|
||||
echo "✓ config.json deployed"
|
||||
else
|
||||
echo "✗ config.json merge FAILED — live file left unchanged"
|
||||
fi
|
||||
fi
|
||||
|
||||
if echo "$CHANGED" | grep -q '^cinny/nginx.conf'; then
|
||||
@@ -80,7 +111,11 @@ if echo "$CHANGED" | grep -q '^deploy/hooks-lxc106.json'; then
|
||||
echo "Deploying hooks-lxc106.json..."
|
||||
cp "$REPO_DIR/deploy/hooks-lxc106.json" /etc/webhook/hooks.json
|
||||
systemctl restart webhook
|
||||
echo "✓ hooks.json deployed, webhook restarted"
|
||||
# webhook-lotus (:9001) serves the same hooks and is the one running THIS
|
||||
# script (Gitea posts matrix-deploy there), so restarting it now would kill
|
||||
# this deploy mid-run: restart it shortly after we exit instead.
|
||||
systemd-run --on-active=15s --unit="webhook-lotus-reload-$(date +%s)" systemctl restart webhook-lotus
|
||||
echo "✓ hooks.json deployed, webhook restarted (webhook-lotus in 15s)"
|
||||
fi
|
||||
|
||||
if echo "$CHANGED" | grep -q '^systemd/cinny-upstream-check.cron'; then
|
||||
@@ -90,4 +125,17 @@ if echo "$CHANGED" | grep -q '^systemd/cinny-upstream-check.cron'; then
|
||||
echo "✓ cron deployed"
|
||||
fi
|
||||
|
||||
# Keep the installed copy of this script in step with the repo (the webhook
|
||||
# runs /usr/local/bin/matrix-deploy.sh, not the repo file). Checked with bash -n
|
||||
# first; takes effect from the next deploy.
|
||||
if echo "$CHANGED" | grep -q '^deploy/lxc106-cinny.sh'; then
|
||||
if bash -n "$REPO_DIR/deploy/lxc106-cinny.sh"; then
|
||||
cp "$REPO_DIR/deploy/lxc106-cinny.sh" /usr/local/bin/matrix-deploy.sh
|
||||
chmod +x /usr/local/bin/matrix-deploy.sh
|
||||
echo "✓ matrix-deploy.sh updated"
|
||||
else
|
||||
echo "✗ bash -n FAILED on lxc106-cinny.sh — keeping the installed copy"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "=== $(date) === LXC106 deploy complete ==="
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// DevDesk "Claude needs you" (devdesk#28)
|
||||
// Receives: { session, message, url, host, text } from devdesk-notify-matrix on
|
||||
// CT 126 when a Claude session waits for input and no browser tab or SSH client
|
||||
// is attached to it.
|
||||
var session = String(data.session || 'a session');
|
||||
var message = String(data.message || 'Claude is waiting for your input');
|
||||
var url = data.url ? String(data.url) : '';
|
||||
function esc(t) {
|
||||
return t.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
}
|
||||
// m.text, not m.notice: notices are muted by default push rules, and this one
|
||||
// exists to reach your phone.
|
||||
result = {
|
||||
version: 'v2',
|
||||
plain: '🔔 Claude needs you in ' + session + ': ' + message + (url ? ' — ' + url : ''),
|
||||
html: '🔔 <b>Claude needs you</b> in <code>' + esc(session) + '</code>: ' + esc(message)
|
||||
+ (url ? ' — <a href="' + esc(url) + '">open in DevDesk</a>' : ''),
|
||||
msgtype: 'm.text',
|
||||
};
|
||||
+9
-1
@@ -23,6 +23,14 @@ import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def human_date(iso):
|
||||
"""2026-09-26 -> September 26, 2026 (the page avoids hyphens in visible text)."""
|
||||
from datetime import date
|
||||
|
||||
d = date.fromisoformat(iso)
|
||||
return f"{d:%B} {d.day}, {d.year}"
|
||||
INDEX = ROOT / "index.html"
|
||||
MARK = {"yes": "✓", "no": "✗", "part": "~"}
|
||||
|
||||
@@ -96,7 +104,7 @@ def main():
|
||||
new = replace_block(new, "features", render_features(features))
|
||||
new = replace_block(new, "comparison", render_comparison(comparison))
|
||||
new = replace_block(
|
||||
new, "reviewed", f'Client comparison last reviewed <time datetime="{comparison["reviewed"]}">{comparison["reviewed"]}</time>'
|
||||
new, "reviewed", f'Client comparison last reviewed <time datetime="{comparison["reviewed"]}">{human_date(comparison["reviewed"])}</time>'
|
||||
)
|
||||
if "--check" in sys.argv:
|
||||
if new != html:
|
||||
|
||||
+312
-259
File diff suppressed because it is too large
Load Diff
+24
-24
@@ -2,63 +2,63 @@
|
||||
{
|
||||
"title": "Calls & Voice",
|
||||
"items": [
|
||||
"Voice rooms with our own Element Call fork on a self-hosted LiveKit SFU",
|
||||
"Push-to-talk and push-to-deafen, with system-wide hotkeys on the Windows app (work while a game has focus)",
|
||||
"Mic level meter on the mute button; per-person call volume that's remembered between calls",
|
||||
"On-device noise suppression: Off, browser-native, or ML (RNNoise, Speex, DTLN, DeepFilterNet 3)",
|
||||
"In-call soundboard with your own clips, synced across your devices",
|
||||
"Incoming-call ring with Answer/Decline, join/leave sounds, draggable picture-in-picture window",
|
||||
"Screenshare fullscreen and audio mute; per-user mic/screenshare bitrate and framerate caps",
|
||||
"Server-enforced room limits and permissions (max participants, audio-only, no screenshare) for every Matrix client",
|
||||
"AFK auto-mute after a configurable idle time"
|
||||
"Voice rooms with our own Element Call fork on a self hosted LiveKit SFU",
|
||||
"Push to talk and push to deafen, with system wide hotkeys on the Windows app (work while a game has focus)",
|
||||
"Mic level meter on the mute button; per person call volume that's remembered between calls",
|
||||
"On device noise suppression: Off, browser native, or ML (RNNoise, Speex, DTLN, DeepFilterNet 3)",
|
||||
"In call soundboard with your own clips, synced across your devices",
|
||||
"Incoming call ring with Answer/Decline, join/leave sounds, draggable picture in picture window",
|
||||
"Screenshare fullscreen and audio mute; per user mic/screenshare bitrate and framerate caps",
|
||||
"Server enforced room limits and permissions (max participants, audio only, no screenshare) for every Matrix client",
|
||||
"AFK auto mute after a configurable idle time"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Messaging",
|
||||
"items": [
|
||||
"Threads with a side panel, unread chips, “Mark all read” and per-thread notification overrides",
|
||||
"Threads with a side panel, unread chips, “Mark all read” and per thread notification overrides",
|
||||
"Search operators: <code>from:</code>, <code>in:</code>, <code>before:</code>/<code>after:</code> (dates or <code>7d</code>), <code>has:link|image|video|file</code>, <code>is:pinned</code>",
|
||||
"Voice messages with 0.75×–2× playback (MSC3245, E2EE)",
|
||||
"Voice messages with 0.75× to 2× playback (MSC3245, E2EE)",
|
||||
"Polls, message scheduling (MSC4140), forwarding, captions and location sharing",
|
||||
"Pinned messages, saved messages/bookmarks and private notes on people, synced across devices",
|
||||
"Who-reacted viewer, read receipt avatars, quick reactions on hover",
|
||||
"Who reacted viewer, read receipt avatars, quick reactions on hover",
|
||||
"GIF picker (Giphy), custom emoji & sticker packs, math/LaTeX (KaTeX)",
|
||||
"Pasted code is offered as a formatted code block, with the language detected",
|
||||
"On-device message translation: text never leaves your machine, works in encrypted rooms"
|
||||
"On device message translation: text never leaves your machine, works in encrypted rooms"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Media & Links",
|
||||
"items": [
|
||||
"Click-to-play inline embeds: YouTube, Vimeo, Twitch, TikTok, X, Instagram, Reddit, Bluesky, Spotify, SoundCloud, Apple Music, Tidal and more",
|
||||
"Click to play inline embeds: YouTube, Vimeo, Twitch, TikTok, X, Instagram, Reddit, Bluesky, Spotify, SoundCloud, Apple Music, Tidal and more",
|
||||
"Rich link cards for GitHub, Steam, Wikipedia, IMDb, npm and others; animated GIF previews",
|
||||
"Full-screen viewer with pinch-zoom, swipe/arrow-key navigation and captions; media gallery for every file shared in a room",
|
||||
"Optional image compression, folder drag-and-drop upload"
|
||||
"Full screen viewer with pinch zoom, swipe/arrow key navigation and captions; media gallery for every file shared in a room",
|
||||
"Optional image compression, folder drag and drop upload"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Privacy & Security",
|
||||
"items": [
|
||||
"Private read receipts, hide typing, hide online status",
|
||||
"Tracking-parameter stripping (utm_*, fbclid, YouTube si= and ~40 more), on your device",
|
||||
"Opt-in on-device search index for encrypted rooms, wiped on logout",
|
||||
"Device verification fixes (cross-client emoji SAS) and a per-member session panel"
|
||||
"Tracking parameter stripping (utm_*, fbclid, YouTube si= and ~40 more), on your device",
|
||||
"Opt in on device search index for encrypted rooms, wiped on logout",
|
||||
"Device verification fixes (cross client emoji SAS) and a per member session panel"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Look & Feel",
|
||||
"items": [
|
||||
"Lotus Terminal theme, night-light filter, glassmorphism sidebar",
|
||||
"Lotus Terminal theme, night light filter, glassmorphism sidebar",
|
||||
"Animated chat backgrounds and 11 seasonal overlays (all respect reduced motion)",
|
||||
"629 animated avatar decorations in 28 categories, visible to other Lotus users (MSC4133)",
|
||||
"Custom status with emoji and auto-clear, Discord-style presence rings",
|
||||
"Custom status with emoji and auto clear, Discord style presence rings",
|
||||
"Settings sync across devices (theme, layout, notification and privacy preferences)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Desktop App",
|
||||
"items": [
|
||||
"Windows, macOS and Linux (Tauri)",
|
||||
"Windows and Linux (Tauri): installer, AppImage, .deb and Arch package",
|
||||
"Rich Windows notifications with inline reply; Focus Assist sync",
|
||||
"Taskbar call controls, jump list and upload progress; tray with call status",
|
||||
"Stays awake during calls, reconnects on network changes, updates itself"
|
||||
@@ -67,9 +67,9 @@
|
||||
{
|
||||
"title": "Rooms & Moderation",
|
||||
"items": [
|
||||
"Knock-to-join with an admin approve/deny panel and live pending-count badge",
|
||||
"Knock to join with an admin approve/deny panel and live pending count badge",
|
||||
"Invite links with QR codes, favourites, room filter, room history export (txt/json/html)",
|
||||
"Room activity & mod log, stats panel, server ACL editor, policy-list viewer",
|
||||
"Room activity & mod log, stats panel, server ACL editor, policy list viewer",
|
||||
"Room widgets, with a permission prompt before a widget may read or send in the room"
|
||||
]
|
||||
}
|
||||
|
||||
+217
-211
@@ -426,12 +426,12 @@
|
||||
background: #111;
|
||||
}
|
||||
tr.section-header td {
|
||||
/* section headers span full width — override sticky bg */
|
||||
/* section headers span full width: override sticky bg */
|
||||
position: static;
|
||||
background: rgba(152,0,0,0.06);
|
||||
}
|
||||
|
||||
/* Scroll hint — visible only on mobile via JS class */
|
||||
/* Scroll hint: visible only on mobile via JS class */
|
||||
.scroll-hint {
|
||||
display: none;
|
||||
font-size: 0.72rem;
|
||||
@@ -543,11 +543,11 @@
|
||||
<ol class="steps">
|
||||
<li>
|
||||
<span class="step-num">1</span>
|
||||
<span class="step-text">Open <a href="https://chat.lotusguild.org" target="_blank" rel="noopener">chat.lotusguild.org</a> — your homeserver is pre-configured</span>
|
||||
<span class="step-text">Ask <code class="homeserver">@jared:matrix.lotusguild.org</code> for a Lotus Guild account</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="step-num">2</span>
|
||||
<span class="step-text">Register with a <strong>token from Jared</strong> — <code class="homeserver">@jared:matrix.lotusguild.org</code></span>
|
||||
<span class="step-text">Open <a href="https://chat.lotusguild.org" target="_blank" rel="noopener">chat.lotusguild.org</a> and sign in with <strong>Lotus SSO</strong></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="step-num">3</span>
|
||||
@@ -569,12 +569,14 @@
|
||||
<div class="client-featured">
|
||||
<a href="https://chat.lotusguild.org" target="_blank" rel="noopener">
|
||||
<span class="client-name">Lotus Guild Chat</span>
|
||||
<span class="client-desc">Hosted Cinny — homeserver pre-configured, no setup</span>
|
||||
<span class="client-desc">Hosted Cinny with the homeserver already set up</span>
|
||||
<span class="tag-row">
|
||||
<span class="tag dim">Desktop & Web</span>
|
||||
<span class="tag dim">Windows</span>
|
||||
<span class="tag dim">Linux</span>
|
||||
<span class="tag dim">Web</span>
|
||||
<span class="tag dev">Lotus Fork</span>
|
||||
<span class="tag voice">Voice & Video Rooms</span>
|
||||
<span class="tag">Discord-like UI</span>
|
||||
<span class="tag voice">Voice, Video & Screenshare</span>
|
||||
<span class="tag">Discord like UI</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
@@ -584,63 +586,63 @@
|
||||
<div class="fork-group">
|
||||
<h4>Calls & Voice</h4>
|
||||
<ul>
|
||||
<li>Voice rooms with our own Element Call fork on a self-hosted LiveKit SFU</li>
|
||||
<li>Push-to-talk and push-to-deafen, with system-wide hotkeys on the Windows app (work while a game has focus)</li>
|
||||
<li>Mic level meter on the mute button; per-person call volume that's remembered between calls</li>
|
||||
<li>On-device noise suppression: Off, browser-native, or ML (RNNoise, Speex, DTLN, DeepFilterNet 3)</li>
|
||||
<li>In-call soundboard with your own clips, synced across your devices</li>
|
||||
<li>Incoming-call ring with Answer/Decline, join/leave sounds, draggable picture-in-picture window</li>
|
||||
<li>Screenshare fullscreen and audio mute; per-user mic/screenshare bitrate and framerate caps</li>
|
||||
<li>Server-enforced room limits and permissions (max participants, audio-only, no screenshare) for every Matrix client</li>
|
||||
<li>AFK auto-mute after a configurable idle time</li>
|
||||
<li>Voice rooms with our own Element Call fork on a self hosted LiveKit SFU</li>
|
||||
<li>Push to talk and push to deafen, with system wide hotkeys on the Windows app (work while a game has focus)</li>
|
||||
<li>Mic level meter on the mute button; per person call volume that's remembered between calls</li>
|
||||
<li>On device noise suppression: Off, browser native, or ML (RNNoise, Speex, DTLN, DeepFilterNet 3)</li>
|
||||
<li>In call soundboard with your own clips, synced across your devices</li>
|
||||
<li>Incoming call ring with Answer/Decline, join/leave sounds, draggable picture in picture window</li>
|
||||
<li>Screenshare fullscreen and audio mute; per user mic/screenshare bitrate and framerate caps</li>
|
||||
<li>Server enforced room limits and permissions (max participants, audio only, no screenshare) for every Matrix client</li>
|
||||
<li>AFK auto mute after a configurable idle time</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="fork-group">
|
||||
<h4>Messaging</h4>
|
||||
<ul>
|
||||
<li>Threads with a side panel, unread chips, “Mark all read” and per-thread notification overrides</li>
|
||||
<li>Threads with a side panel, unread chips, “Mark all read” and per thread notification overrides</li>
|
||||
<li>Search operators: <code>from:</code>, <code>in:</code>, <code>before:</code>/<code>after:</code> (dates or <code>7d</code>), <code>has:link|image|video|file</code>, <code>is:pinned</code></li>
|
||||
<li>Voice messages with 0.75×–2× playback (MSC3245, E2EE)</li>
|
||||
<li>Voice messages with 0.75× to 2× playback (MSC3245, E2EE)</li>
|
||||
<li>Polls, message scheduling (MSC4140), forwarding, captions and location sharing</li>
|
||||
<li>Pinned messages, saved messages/bookmarks and private notes on people, synced across devices</li>
|
||||
<li>Who-reacted viewer, read receipt avatars, quick reactions on hover</li>
|
||||
<li>Who reacted viewer, read receipt avatars, quick reactions on hover</li>
|
||||
<li>GIF picker (Giphy), custom emoji & sticker packs, math/LaTeX (KaTeX)</li>
|
||||
<li>Pasted code is offered as a formatted code block, with the language detected</li>
|
||||
<li>On-device message translation: text never leaves your machine, works in encrypted rooms</li>
|
||||
<li>On device message translation: text never leaves your machine, works in encrypted rooms</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="fork-group">
|
||||
<h4>Media & Links</h4>
|
||||
<ul>
|
||||
<li>Click-to-play inline embeds: YouTube, Vimeo, Twitch, TikTok, X, Instagram, Reddit, Bluesky, Spotify, SoundCloud, Apple Music, Tidal and more</li>
|
||||
<li>Click to play inline embeds: YouTube, Vimeo, Twitch, TikTok, X, Instagram, Reddit, Bluesky, Spotify, SoundCloud, Apple Music, Tidal and more</li>
|
||||
<li>Rich link cards for GitHub, Steam, Wikipedia, IMDb, npm and others; animated GIF previews</li>
|
||||
<li>Full-screen viewer with pinch-zoom, swipe/arrow-key navigation and captions; media gallery for every file shared in a room</li>
|
||||
<li>Optional image compression, folder drag-and-drop upload</li>
|
||||
<li>Full screen viewer with pinch zoom, swipe/arrow key navigation and captions; media gallery for every file shared in a room</li>
|
||||
<li>Optional image compression, folder drag and drop upload</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="fork-group">
|
||||
<h4>Privacy & Security</h4>
|
||||
<ul>
|
||||
<li>Private read receipts, hide typing, hide online status</li>
|
||||
<li>Tracking-parameter stripping (utm_*, fbclid, YouTube si= and ~40 more), on your device</li>
|
||||
<li>Opt-in on-device search index for encrypted rooms, wiped on logout</li>
|
||||
<li>Device verification fixes (cross-client emoji SAS) and a per-member session panel</li>
|
||||
<li>Tracking parameter stripping (utm_*, fbclid, YouTube si= and ~40 more), on your device</li>
|
||||
<li>Opt in on device search index for encrypted rooms, wiped on logout</li>
|
||||
<li>Device verification fixes (cross client emoji SAS) and a per member session panel</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="fork-group">
|
||||
<h4>Look & Feel</h4>
|
||||
<ul>
|
||||
<li>Lotus Terminal theme, night-light filter, glassmorphism sidebar</li>
|
||||
<li>Lotus Terminal theme, night light filter, glassmorphism sidebar</li>
|
||||
<li>Animated chat backgrounds and 11 seasonal overlays (all respect reduced motion)</li>
|
||||
<li>629 animated avatar decorations in 28 categories, visible to other Lotus users (MSC4133)</li>
|
||||
<li>Custom status with emoji and auto-clear, Discord-style presence rings</li>
|
||||
<li>Custom status with emoji and auto clear, Discord style presence rings</li>
|
||||
<li>Settings sync across devices (theme, layout, notification and privacy preferences)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="fork-group">
|
||||
<h4>Desktop App</h4>
|
||||
<ul>
|
||||
<li>Windows, macOS and Linux (Tauri)</li>
|
||||
<li>Windows and Linux (Tauri): installer, AppImage, .deb and Arch package</li>
|
||||
<li>Rich Windows notifications with inline reply; Focus Assist sync</li>
|
||||
<li>Taskbar call controls, jump list and upload progress; tray with call status</li>
|
||||
<li>Stays awake during calls, reconnects on network changes, updates itself</li>
|
||||
@@ -649,16 +651,16 @@
|
||||
<div class="fork-group">
|
||||
<h4>Rooms & Moderation</h4>
|
||||
<ul>
|
||||
<li>Knock-to-join with an admin approve/deny panel and live pending-count badge</li>
|
||||
<li>Knock to join with an admin approve/deny panel and live pending count badge</li>
|
||||
<li>Invite links with QR codes, favourites, room filter, room history export (txt/json/html)</li>
|
||||
<li>Room activity & mod log, stats panel, server ACL editor, policy-list viewer</li>
|
||||
<li>Room activity & mod log, stats panel, server ACL editor, policy list viewer</li>
|
||||
<li>Room widgets, with a permission prompt before a widget may read or send in the room</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END:features -->
|
||||
<p class="fork-more">Full list in <a href="https://code.lotusguild.org/LotusGuild/cinny/src/branch/lotus/LOTUS_FEATURES.md" target="_blank" rel="noopener">LOTUS_FEATURES.md</a>.</p>
|
||||
<p class="also-available">Prefer the unmodified upstream? <a href="https://cinny.in" target="_blank" rel="noopener">cinny.in</a> works with our homeserver — set it to <code class="hs-inline">matrix.lotusguild.org</code>.</p>
|
||||
<p class="also-available">Prefer the unmodified upstream? <a href="https://cinny.in" target="_blank" rel="noopener">cinny.in</a> works with our homeserver: set it to <code class="hs-inline">matrix.lotusguild.org</code>.</p>
|
||||
|
||||
<div class="space-join">
|
||||
<p>Already signed in? Jump straight into the community:</p>
|
||||
@@ -672,23 +674,26 @@
|
||||
<h3>Other Clients</h3>
|
||||
|
||||
<div class="client-group">
|
||||
<p class="client-group-label">Web & Desktop — Official Cinny</p>
|
||||
<p class="client-group-label">Web & Desktop: Official Cinny</p>
|
||||
<div class="client-cards">
|
||||
<div class="client-card">
|
||||
<div class="client-card-top">
|
||||
<a href="https://cinny.in" target="_blank" rel="noopener" class="client-card-name">Cinny</a>
|
||||
<div class="client-card-tags">
|
||||
<span class="tag dim">Windows</span>
|
||||
<span class="tag dim">macOS</span>
|
||||
<span class="tag dim">Linux</span>
|
||||
<span class="tag dim">Web</span>
|
||||
<span class="tag dim">Desktop</span>
|
||||
<span class="tag voice">Voice, Video & Screenshare</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="client-card-desc">The upstream open-source Cinny client. Same Discord-like UI and best-in-class space navigation as Lotus Chat, but without our custom additions (no GIF picker, no call ring notification, no PiP window, no message forwarding). Set homeserver to <code style="font-size:0.85em;color:#e88;background:rgba(152,0,0,0.08);padding:1px 5px;border-radius:4px;">matrix.lotusguild.org</code>.</p>
|
||||
<p class="client-card-desc">The upstream open source Cinny client, on the web and as a desktop app for Windows, macOS and Linux. It has the same Discord like UI and space navigation as Lotus Chat, and now includes voice/video calls, voice rooms and screenshare through embedded Element Call, with ringing for DM calls. It lacks our custom additions (no GIF picker, no PiP window, no message forwarding). Set homeserver to <code style="font-size:0.85em;color:#e88;background:rgba(152,0,0,0.08);padding:1px 5px;border-radius:4px;">matrix.lotusguild.org</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="client-group">
|
||||
<p class="client-group-label">Mobile — iOS & Android</p>
|
||||
<p class="client-group-label">Mobile: iOS & Android</p>
|
||||
<div class="client-cards">
|
||||
<div class="client-card">
|
||||
<div class="client-card-top">
|
||||
@@ -697,10 +702,10 @@
|
||||
<span class="tag dim">iOS</span>
|
||||
<span class="tag dim">Android</span>
|
||||
<span class="tag rust">Rust SDK</span>
|
||||
<span class="tag voice">Voice, Video & Screenshare</span>
|
||||
<span class="tag voice">Voice & Video</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="client-card-desc">Fastest Matrix client — instant load via Sliding Sync. Native MatrixRTC calls (voice-only + video), screenshare, DM voice calls, live location sharing, media captions. Full space create & management. Rust encryption (Vodozemac).</p>
|
||||
<p class="client-card-desc">Element's next generation mobile client for iOS and Android, built on the Rust SDK with Simplified Sliding Sync for near instant startup (the iOS app also runs on Apple Silicon Macs). Voice and video calls, 1:1 and group, via embedded Element Call (MatrixRTC). It can view but not start screenshares. Live location sharing, media captions, polls, pinned messages, a media browser and spaces with create and management, plus custom status on supported homeservers. Threads are in Labs. Rust crypto (Vodozemac).</p>
|
||||
</div>
|
||||
<div class="client-card">
|
||||
<div class="client-card-top">
|
||||
@@ -708,19 +713,19 @@
|
||||
<div class="client-card-tags">
|
||||
<span class="tag dim">iOS</span>
|
||||
<span class="tag dim">Android</span>
|
||||
<span class="tag dim">Desktop</span>
|
||||
<span class="tag dim">Linux</span>
|
||||
<span class="tag dim">Web</span>
|
||||
<span class="tag dim">Dart SDK</span>
|
||||
<span class="tag warn">Calls Experimental</span>
|
||||
<span class="tag rust">Dart SDK</span>
|
||||
<span class="tag warn">Voice & Video (Experimental)</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="client-card-desc">Simple, beginner-friendly, fully cross-platform. Dart SDK with Vodozemac encryption. Unique: supports image captions (text + image as one event). Voice/video calls are experimental — reliability varies by homeserver and platform.</p>
|
||||
<p class="client-card-desc">Simple, beginner friendly Matrix client with a WhatsApp/Telegram style design, available on Android, iOS, web and Linux desktop. Built on the Dart SDK with Vodozemac encryption. Supports threads, polls, image captions, custom sticker packs, voice messages and spaces. 1:1 voice and video calls exist but remain experimental: they are off by default, DM only, legacy WebRTC, and there are no group calls.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="client-group">
|
||||
<p class="client-group-label">Discord-like — Android, Windows, macOS & Linux</p>
|
||||
<p class="client-group-label">Like Discord: Android, Windows, Linux & Web</p>
|
||||
<div class="client-cards">
|
||||
<div class="client-card">
|
||||
<div class="client-card-top">
|
||||
@@ -728,19 +733,19 @@
|
||||
<div class="client-card-tags">
|
||||
<span class="tag dim">Android</span>
|
||||
<span class="tag dim">Windows</span>
|
||||
<span class="tag dim">macOS</span>
|
||||
<span class="tag dim">Linux</span>
|
||||
<span class="tag beta">Beta</span>
|
||||
<span class="tag voice">Voice & Video</span>
|
||||
<span class="tag dim">Web</span>
|
||||
<span class="tag rust">Dart SDK</span>
|
||||
<span class="tag voice">Voice, Video & Screenshare</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="client-card-desc">Most Discord-like client overall. Multi-account support, built-in GIF search (privacy proxy — uploads to homeserver), shared calendars & photo albums, polls, screenshare on browsers & Android. Available on Android, Windows, macOS, Linux, and Web. Active development — iOS planned.</p>
|
||||
<p class="client-card-desc">Discord style client built with Flutter. Multi account support with all accounts signed in at once, built in GIF search (Tenor through a privacy proxy, uploaded to your homeserver), shared calendar and photo album rooms, polls, threads and widgets (new in v0.5.0). 1:1 calls use WebRTC and voice channels use MatrixRTC/LiveKit, with screenshare on desktop, Android and web. Encrypted group calls are experimental. Available for Windows, Linux, Android and on the web at app.commet.chat. Actively developed; macOS and iOS are planned.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="client-group">
|
||||
<p class="client-group-label">Desktop — Windows, macOS & Linux</p>
|
||||
<p class="client-group-label">Desktop: Windows, macOS & Linux</p>
|
||||
<div class="client-cards">
|
||||
<div class="client-card">
|
||||
<div class="client-card-top">
|
||||
@@ -753,7 +758,7 @@
|
||||
<span class="tag voice">Voice, Video & Screenshare</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="client-card-desc">Most feature-complete Matrix client — every spec feature including polls, widgets, threads, screenshare. Heavier on resources. Encrypted message search on desktop only (not web).</p>
|
||||
<p class="client-card-desc">Element's reference web and desktop client (Electron), with the broadest feature set here: threads, polls, widgets, location sharing, chat export and a room list with sections, filters and sorting. Voice/video calls with screenshare use embedded Element Call when the homeserver provides it, with legacy 1:1 and Jitsi fallbacks. Heavier on resources. Encrypted message search on desktop only (not web).</p>
|
||||
</div>
|
||||
<div class="client-card">
|
||||
<div class="client-card-top">
|
||||
@@ -762,10 +767,11 @@
|
||||
<span class="tag dim">Windows</span>
|
||||
<span class="tag dim">macOS</span>
|
||||
<span class="tag dim">Linux</span>
|
||||
<span class="tag voice">Voice & Video</span>
|
||||
<span class="tag rust">Qt/C++</span>
|
||||
<span class="tag voice">Voice, Video & Screenshare (1:1, Linux)</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="client-card-desc">Native C++/Qt client — lightest desktop option, no Electron. Deep KDE/Plasma integration. No threads, no mobile or web. Best for Linux power users who want minimal resource usage.</p>
|
||||
<p class="client-card-desc">Native Qt/C++ desktop client with no Electron and a low resource footprint. It has threads, local encrypted search, custom emoji and sticker packs, and a D-Bus API for Linux integrations. 1:1 voice and video calls with screenshare use legacy WebRTC and are only in Linux builds; there are no group calls. No mobile or web version. Development has slowed: the last release was v0.12.1 in August 2025. A good fit for Linux users who want a lightweight native client.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -779,7 +785,7 @@
|
||||
<div class="comparison-section">
|
||||
<p class="comparison-title">Client Feature Comparison</p>
|
||||
<p class="reviewed"><!-- BEGIN:reviewed -->
|
||||
Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
Client comparison last reviewed <time datetime="2026-09-26">September 26, 2026</time>
|
||||
<!-- END:reviewed --></p>
|
||||
<p class="scroll-hint" id="scrollHint">← swipe to compare →</p>
|
||||
<div class="table-wrap">
|
||||
@@ -791,8 +797,8 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<th class="ours">Lotus Chat<small>chat.lotusguild.org<br>Our Cinny fork</small></th>
|
||||
<th>Cinny<small>cinny.in<br>Official</small></th>
|
||||
<th>Element X<small>iOS & Android</small></th>
|
||||
<th>FluffyChat<small>All platforms</small></th>
|
||||
<th>Commet<small>Android / Win / macOS / Linux</small></th>
|
||||
<th>FluffyChat<small>Android, iOS, Web & Linux</small></th>
|
||||
<th>Commet<small>Android / Win / Linux / Web</small></th>
|
||||
<th>Element<small>Web & Desktop</small></th>
|
||||
<th>Nheko<small>Desktop only</small></th>
|
||||
</tr>
|
||||
@@ -823,9 +829,9 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td>Desktop app</td>
|
||||
<td class="ours"><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span><small>Cinny Desktop</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>iOS build runs on Apple Silicon Macs (no Windows/Linux)</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span><small>Win, macOS & Linux</small></td>
|
||||
<td><span class="yes">✓</span><small>Windows & Linux (macOS: build from source only)</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
</tr>
|
||||
@@ -835,7 +841,7 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>app.commet.chat (v0.5.0)</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
@@ -855,10 +861,10 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td class="ours"><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>Linux: click opens chat, Mark as read/Mute actions; no inline reply</small></td>
|
||||
<td><span class="yes">✓</span><small>Windows & Linux: click to open, inline reply, call accept/decline</small></td>
|
||||
<td><span class="part">~</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>Linux inline reply (D-Bus), macOS quick reply, click to open</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Windows Jump List (recent rooms)</td>
|
||||
@@ -871,7 +877,7 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Taskbar + volume-flyout call controls</td>
|
||||
<td>Taskbar + volume flyout call controls</td>
|
||||
<td class="ours"><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -881,7 +887,7 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Focus Assist → auto Do-Not-Disturb</td>
|
||||
<td>Focus Assist → auto Do Not Disturb</td>
|
||||
<td class="ours"><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -895,13 +901,13 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td class="ours"><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>wakelock during (experimental) calls</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Recursive folder drag-drop upload</td>
|
||||
<td>Recursive folder drag drop upload</td>
|
||||
<td class="ours"><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -923,18 +929,18 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Vodozemac encryption<small>stronger crypto track record</small></td>
|
||||
<td class="ours"><span class="no">✗</span><small>js-sdk</small></td>
|
||||
<td><span class="no">✗</span><small>js-sdk</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>Rust crypto (matrix-sdk-crypto-wasm) via js-sdk</small></td>
|
||||
<td><span class="yes">✓</span><small>Rust crypto (matrix-sdk-crypto-wasm) via js-sdk</small></td>
|
||||
<td><span class="yes">✓</span><small>Rust SDK</small></td>
|
||||
<td><span class="yes">✓</span><small>dart-sdk</small></td>
|
||||
<td><span class="yes">✓</span><small>dart-sdk</small></td>
|
||||
<td><span class="no">✗</span><small>js-sdk, migrating</small></td>
|
||||
<td><span class="yes">✓</span><small>Rust crypto (matrix-sdk-crypto-wasm)</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Device verification</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>SAS emoji, cross-client requests show inline card</small></td>
|
||||
<td><span class="part">~</span><small>cross-client requests<br>may show unsupported</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>SAS emoji, cross client requests show inline card</small></td>
|
||||
<td><span class="part">~</span><small>own devices only (emoji + recovery key)</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
@@ -945,36 +951,46 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<tr>
|
||||
<td>Voice & video calls</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>rooms & DMs, group calls,<br>screenshare via Element Call</small></td>
|
||||
<td><span class="part">~</span><small>Element Call embed;<br>no ring notification</small></td>
|
||||
<td><span class="yes">✓</span><small>MatrixRTC</small></td>
|
||||
<td><span class="part">~</span><small>experimental, varies<br>by homeserver</small></td>
|
||||
<td><span class="part">~</span><small>1:1 + group,<br>no E2EE voice rooms</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span><small>1:1 + group via embedded Element Call</small></td>
|
||||
<td><span class="yes">✓</span><small>1:1 & group via embedded Element Call</small></td>
|
||||
<td><span class="part">~</span><small>experimental setting, DMs only (legacy 1:1 WebRTC)</small></td>
|
||||
<td><span class="yes">✓</span><small>1:1 WebRTC; voice channels via MatrixRTC + LiveKit; E2EE experimental</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="part">~</span><small>1:1 only, legacy VoIP; Linux builds only</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Screenshare</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>via Element Call; fullscreen button,<br>independent audio mute</small></td>
|
||||
<td><span class="yes">✓</span><small>via Element Call embed</small></td>
|
||||
<td><span class="no">✗</span><small>can view others' screenshares, cannot start one</small></td>
|
||||
<td><span class="part">~</span><small>experimental 1:1 calls, mobile & web only</small></td>
|
||||
<td><span class="yes">✓</span><small>desktop, Android & browser; 1:1 and voice channels</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span><small>XDG portals & native</small></td>
|
||||
<td><span class="yes">✓</span><small>Linux builds only (1:1 calls; XDG portal)</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Noise suppression<small>filter background noise from mic</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>3 tiers: off / browser-native /<br>on-device ML (RNNoise, Speex,<br>DTLN, DeepFilterNet 3),<br>works on self-hosted SFU</small></td>
|
||||
<td><span class="part">~</span><small>browser-native<br>via Element Call</small></td>
|
||||
<td><span class="part">~</span><small>browser-native</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>browser-native;<br>ML only on LiveKit Cloud</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>3 tiers: off / browser native /<br>on device ML (RNNoise, Speex,<br>DTLN, DeepFilterNet 3),<br>works on self hosted SFU</small></td>
|
||||
<td><span class="part">~</span><small>browser native<br>via Element Call</small></td>
|
||||
<td><span class="part">~</span><small>browser native</small></td>
|
||||
<td><span class="part">~</span><small>WebRTC native</small></td>
|
||||
<td><span class="part">~</span><small>browser native (WebRTC)</small></td>
|
||||
<td><span class="part">~</span><small>browser native (WebRTC noiseSuppression toggle)</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Push-to-Talk<small>hold key to transmit</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>configurable hold key,<br>PTT badge in call bar;<br>M = push-to-deafen;<br>system-wide on Windows desktop</small></td>
|
||||
<td>Push to Talk<small>hold key to transmit</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>configurable hold key,<br>PTT badge in call bar;<br>M = push to deafen;<br>system wide on Windows desktop</small></td>
|
||||
<td><span class="part">~</span><small>hold Space while muted (Element Call built in); no configurable key</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>hold Space while muted in Element Call; no configurable key</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AFK auto mute<small>silence mic after idle timeout</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>1 to 30 min timeout,<br>toast notification</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -983,18 +999,8 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AFK auto-mute<small>silence mic after idle timeout</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>1–30 min timeout,<br>toast notification</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Voice channel user limit<small>admin-set max participants</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>per-room cap,<br>server-enforced<br>for all clients</small></td>
|
||||
<td>Voice channel user limit<small>admin set max participants</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>per room cap,<br>server enforced<br>for all clients</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -1005,58 +1011,58 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<tr>
|
||||
<td>Call join/leave sounds<small>cue when others come & go</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>3 styles,<br>Web Audio synth</small></td>
|
||||
<td><span class="yes">✓</span><small>via Element Call (calls up to 8 people)</small></td>
|
||||
<td><span class="yes">✓</span><small>via Element Call</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>voice channels play join/leave cues for other participants</small></td>
|
||||
<td><span class="yes">✓</span><small>Element Call (calls up to 8 people)</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Group calls</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>via Element Call embed</small></td>
|
||||
<td><span class="yes">✓</span><small>via Element Call embed</small></td>
|
||||
<td><span class="yes">✓</span><small>MatrixRTC</small></td>
|
||||
<td><span class="yes">✓</span><small>via embedded Element Call</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>no E2EE voice rooms</small></td>
|
||||
<td><span class="part">~</span><small>MatrixRTC voice channels; E2EE experimental (v0.5.0)</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="part">~</span><small>partial</small></td>
|
||||
<td><span class="no">✗</span><small>1:1 only; no MatrixRTC/Element Call or Jitsi</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Incoming call notification<small>ring + Answer/Decline</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>DMs & group chats;<br>ring tone, auto-dismiss</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>DMs & group chats;<br>ring tone, auto dismiss</small></td>
|
||||
<td><span class="yes">✓</span><small>rings for DM calls (Answer/Reject); silent prompt for group calls</small></td>
|
||||
<td><span class="yes">✓</span><small>native push</small></td>
|
||||
<td><span class="part">~</span><small>experimental</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span><small>desktop</small></td>
|
||||
<td><span class="part">~</span><small>partial</small></td>
|
||||
<td><span class="yes">✓</span><small>ringing toast with Accept/Decline (web & desktop)</small></td>
|
||||
<td><span class="yes">✓</span><small>ringtone (selectable) + Accept/Decline bar</small></td>
|
||||
</tr>
|
||||
<tr class="section-header"><td colspan="8">Core Features</td></tr>
|
||||
<tr>
|
||||
<td>Spaces</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>best-in-class sub-space nav</small></td>
|
||||
<td><span class="yes">✓</span><small>best-in-class sub-space nav</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>best in class subspace nav</small></td>
|
||||
<td><span class="yes">✓</span><small>best in class subspace nav</small></td>
|
||||
<td><span class="yes">✓</span><small>dedicated spaces tab,<br>full management</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span><small>Discord-like categories</small></td>
|
||||
<td><span class="yes">✓</span><small>sub-spaces clunky</small></td>
|
||||
<td><span class="yes">✓</span><small>Discord like categories</small></td>
|
||||
<td><span class="yes">✓</span><small>subspaces clunky</small></td>
|
||||
<td><span class="part">~</span><small>limited</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Threads</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>side panel + Slack-style per-thread notifications</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>side panel + Slack style per thread notifications</small></td>
|
||||
<td><span class="part">~</span><small>basic, no dedicated view</small></td>
|
||||
<td><span class="part">~</span><small>Labs flag</small></td>
|
||||
<td><span class="no">✗</span><small>shows as regular messages</small></td>
|
||||
<td><span class="yes">✓</span><small>thread view since v2.3.0</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>since v0.11.0</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Polls</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>create, vote & display;<br>single or multiple choice</small></td>
|
||||
<td><span class="part">~</span><small>display only</small></td>
|
||||
<td><span class="no">✗</span><small>not rendered (no m.poll support)</small></td>
|
||||
<td><span class="yes">✓</span><small>create, vote & end</small></td>
|
||||
<td><span class="yes">✓</span><small>added v2.3.0</small></td>
|
||||
<td><span class="yes">✓</span><small>added v0.4.2</small></td>
|
||||
@@ -1071,21 +1077,21 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td><span class="yes">✓</span><small>record & play,<br>pause support</small></td>
|
||||
<td><span class="part">~</span><small>playback confirmed;<br>recording unclear</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>playback only (inline audio player); no recording</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pinned messages</td>
|
||||
<td class="ours"><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span><small>dedicated pins view</small></td>
|
||||
<td><span class="part">~</span><small>view only</small></td>
|
||||
<td><span class="yes">✓</span><small>pin/unpin + pinned banner</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Custom emoji & stickers</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>best-in-class</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>best in class</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="part">~</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
@@ -1095,7 +1101,7 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GIF search / picker</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>Giphy, Terminal TDS themed,<br>click-outside to close</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>Giphy, Terminal TDS themed,<br>click outside to close</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -1105,31 +1111,31 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Message search (encrypted)</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>local cache scan; load-more<br>buttons extend history per room</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>local cache scan; load more<br>buttons extend history per room</small></td>
|
||||
<td><span class="part">~</span><small>server search only;<br>no E2EE support</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>cache scan only</small></td>
|
||||
<td><span class="yes">✓</span><small>client-side; auto-fetches +<br>decrypts history during search</small></td>
|
||||
<td><span class="part">~</span><small>per room; downloads & decrypts history client side</small></td>
|
||||
<td><span class="yes">✓</span><small>client side; auto fetches +<br>decrypts history during search</small></td>
|
||||
<td><span class="part">~</span><small>desktop only, not web</small></td>
|
||||
<td><span class="part">~</span><small>local DB scan</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Widgets</td>
|
||||
<td class="ours"><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>room widgets; asks before a widget may read or send in the room</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>added v0.5.0 (Widgets API, native runner on Android/Windows)</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>listed in room header, open externally</small></td>
|
||||
</tr>
|
||||
<tr class="section-header"><td colspan="8">UX & Extras</td></tr>
|
||||
<tr>
|
||||
<td>Multi-account</td>
|
||||
<td>Multi account</td>
|
||||
<td class="ours"><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>supported but clunky</small></td>
|
||||
<td><span class="yes">✓</span><small>account switcher; multi account push since v2.6.0</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span><small>CLI profiles only</small></td>
|
||||
@@ -1137,20 +1143,20 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<tr>
|
||||
<td>Image captions<small>(text + image as one event)</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>caption field on<br>image & video upload</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>shows captions from other clients; cannot send</small></td>
|
||||
<td><span class="yes">✓</span><small>scrollable captions<br>on media (v26.04.2)</small></td>
|
||||
<td><span class="yes">✓</span><small>unique feature</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>shows captions from other clients; cannot send</small></td>
|
||||
<td><span class="part">~</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Discord-like UI</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>best-in-class for web</small></td>
|
||||
<td>Discord like UI</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>best in class for web</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span><small>WhatsApp/Telegram style</small></td>
|
||||
<td><span class="yes">✓</span><small>most Discord-like overall</small></td>
|
||||
<td><span class="yes">✓</span><small>Discord like layout</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
@@ -1166,7 +1172,7 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Night Light / Blue Light Filter<small>warm overlay, adjustable intensity</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>5–80% intensity slider,<br>Settings → Appearance</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>5 to 80% intensity slider,<br>Settings → Appearance</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -1175,7 +1181,7 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Animated chat backgrounds<small>CSS-only, GPU-accelerated</small></td>
|
||||
<td>Animated chat backgrounds<small>CSS only, GPU accelerated</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>5 animated wallpapers (rain,<br>stars, grid pulse, aurora,<br>fireflies); pause toggle</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -1187,17 +1193,17 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<tr>
|
||||
<td>Deleted message visibility<small>(redacted events)</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>"Message deleted" with reason<br>if provided</small></td>
|
||||
<td><span class="no">✗</span><small>redacted messages hidden</small></td>
|
||||
<td><span class="part">~</span><small>hidden by default; shown with "Show Hidden Events"</small></td>
|
||||
<td><span class="yes">✓</span><small>"Message deleted"<br>placeholder shown</small></td>
|
||||
<td><span class="yes">✓</span><small>shows redaction notice</small></td>
|
||||
<td><span class="yes">✓</span><small>shows redaction notice</small></td>
|
||||
<td><span class="no">✗</span><small>redacted events are hidden from the timeline</small></td>
|
||||
<td><span class="yes">✓</span><small>"Message deleted"<br>placeholder shown</small></td>
|
||||
<td><span class="yes">✓</span><small>shows redaction notice</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Location sharing</td>
|
||||
<td class="ours"><span class="part">~</span><small>map embed view +<br>static share button</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>shows received locations; cannot send</small></td>
|
||||
<td><span class="yes">✓</span><small>live & static,<br>map rendering</small></td>
|
||||
<td><span class="part">~</span><small>basic static</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -1208,16 +1214,16 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td>Message forwarding</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>forward to any room</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>via share menu</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="part">~</span></td>
|
||||
<td><span class="yes">✓</span><small>Forward action; multi room on Android</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Per-message read receipts<small>who read each message</small></td>
|
||||
<td>Per message read receipts<small>who read each message</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>avatar pill below message,<br>click for list + timestamps</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>'Read Receipts' in message menu lists readers</small></td>
|
||||
<td><span class="yes">✓</span><small>avatar thumbnails</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
@@ -1226,60 +1232,60 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Who reacted<small>see who reacted with each emoji</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>hover tooltip with names;<br>right-click for full avatar modal</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>tap reaction chip</small></td>
|
||||
<td><span class="part">~</span></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>hover tooltip with names;<br>right click for full avatar modal</small></td>
|
||||
<td><span class="yes">✓</span><small>hover tooltip + 'View Reactions' viewer</small></td>
|
||||
<td><span class="yes">✓</span><small>long press reaction for summary sheet</small></td>
|
||||
<td><span class="yes">✓</span><small>long press reaction</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span><small>tooltip + click for list</small></td>
|
||||
<td><span class="yes">✓</span><small>hover tooltip lists reactors</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Edit history viewer<small>see all prior versions of an edited message</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>click "(edited)" label → modal<br>with all versions + timestamps</small></td>
|
||||
<td><span class="no">✗</span><small>label shown, not clickable</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span><small>shows "(edited)" label only</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span><small>only an 'Edited' marker</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Custom status message<small>shown below username</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>emoji picker, auto-clear timer<br>(30 min – 7 days), 64-char limit</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>via profile settings</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>emoji picker, auto clear timer<br>(30 min to 7 days), 64 char limit</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>emoji + text status (needs server support)</small></td>
|
||||
<td><span class="yes">✓</span><small>Set status; shown under DM header & in profile</small></td>
|
||||
<td><span class="yes">✓</span><small>shown under name in user panels/profile</small></td>
|
||||
<td><span class="part">~</span><small>Labs; needs homeserver support (MSC4429)</small></td>
|
||||
<td><span class="yes">✓</span><small>shown next to sender name in timeline & in profile</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Online presence tracking<small>idle/away auto-detection</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>online on start, idle after 10 min,<br>unavailable when tab hidden,<br>offline on close; hide-status toggle</small></td>
|
||||
<td><span class="part">~</span><small>manual AFK only; auto idle<br>detection PR open, unmerged</small></td>
|
||||
<td><span class="part">~</span><small>basic online/offline only</small></td>
|
||||
<td><span class="part">~</span><small>basic online/offline only</small></td>
|
||||
<td><span class="part">~</span><small>inactivity monitor shipped Oct 2025;<br>no tab/close detection confirmed</small></td>
|
||||
<td><span class="part">~</span><small>3-min idle timer (shipped Nov 2023);<br>no tab detection, no offline on close,<br>no user-facing hide toggle</small></td>
|
||||
<td>Online presence tracking<small>idle/away auto detection</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>online on start, idle after 10 min,<br>unavailable when tab hidden,<br>offline on close; hide status toggle</small></td>
|
||||
<td><span class="part">~</span><small>shows others' status; no idle detection</small></td>
|
||||
<td><span class="part">~</span><small>reports own presence; doesn't show others'</small></td>
|
||||
<td><span class="part">~</span><small>basic online/offline only</small></td>
|
||||
<td><span class="part">~</span><small>sets 'unavailable' 15s after the app loses focus; no input idle timer</small></td>
|
||||
<td><span class="part">~</span><small>3 min idle → away; no hide toggle</small></td>
|
||||
<td><span class="part">~</span><small>auto: unavailable ~30 s after losing focus</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Media Gallery<small>browse room images/videos/files</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>right-side drawer;<br>Images/Videos/Files tabs</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>right side drawer;<br>Images/Videos/Files tabs</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>"Media and files" browser in room info</small></td>
|
||||
<td><span class="yes">✓</span><small>Gallery & Files tabs in chat search</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>Files panel lists room attachments; no grid gallery</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sidebar room filter<small>filter by name in real time</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>Home & DMs tabs</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>room list search + filter chips</small></td>
|
||||
<td><span class="yes">✓</span><small>search field filters chat list by name + filter chips</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -1288,30 +1294,30 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td>Favorite rooms<small>starred section in sidebar</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>m.favourite tag, syncs<br>across devices</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>Favourites filter chip (no separate section)</small></td>
|
||||
<td><span class="part">~</span><small>favourite (pin) floats to top; tag filter chips</small></td>
|
||||
<td><span class="yes">✓</span><small>'Favorites' section (v0.5.0)</small></td>
|
||||
<td><span class="yes">✓</span><small>favourites section</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>'Favourites' tag in community sidebar</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Invite link + QR code</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>matrix.to URL + QR code<br>in invite modal & room settings</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>share room link; no QR</small></td>
|
||||
<td><span class="yes">✓</span><small>share invite link + QR codes</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>Share room dialog: matrix.to link + QR code</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Custom notification sounds<small>per-category sound selector</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>per-category sound selector; ▶ preview</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td>Custom notification sounds<small>per category sound selector</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>per category sound selector; ▶ preview</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>iOS: choose alert tone (global)</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>per room, not per category</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -1329,15 +1335,15 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td class="ours"><span class="yes">✓</span><small>Recent / A→Z / Unread First</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>sort by activity only</small></td>
|
||||
<td><span class="part">~</span><small>alphabetical only</small></td>
|
||||
<td><span class="yes">✓</span><small>multiple sort options</small></td>
|
||||
<td><span class="part">~</span><small>limited</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>activity only (favourites first, low priority last)</small></td>
|
||||
<td><span class="part">~</span><small>manual drag reorder; no sort selector</small></td>
|
||||
<td><span class="yes">✓</span><small>Activity, A to Z or Unread first</small></td>
|
||||
<td><span class="yes">✓</span><small>by importance/unread or alphabetical</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Push notifications</td>
|
||||
<td class="ours"><span class="part">~</span><small>web push only</small></td>
|
||||
<td><span class="part">~</span><small>web push only</small></td>
|
||||
<td class="ours"><span class="part">~</span><small>OS notifications while the app is open; no background push yet</small></td>
|
||||
<td><span class="part">~</span><small>only while the tab/app is open; optional email</small></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
@@ -1346,7 +1352,7 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Export room history<small>download messages as file</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>txt/json/html, date range,<br>E2EE-aware</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>txt/json/html, date range,<br>E2EE aware</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -1361,31 +1367,31 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>partial / labs</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Message bookmarks / saved messages</td>
|
||||
<td class="ours"><span class="yes">✓</span><small>right-click bookmark,<br>sidebar panel, syncs across devices</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>right click bookmark,<br>sidebar panel, syncs across devices</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Collapsible long messages<small>auto-collapse >20 lines</small></td>
|
||||
<td>Collapsible long messages<small>auto collapse >20 lines</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>"Read more" toggle,<br>threshold configurable</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>collapses >25 lines (configurable), Show more/less</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Inline GIF preview<small>Giphy / Tenor links auto-embed</small></td>
|
||||
<td>Inline GIF preview<small>Giphy / Tenor links auto embed</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>via homeserver proxy,<br>no direct CDN contact</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -1410,23 +1416,23 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>leading emoji becomes the room icon when no avatar</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Quick emoji reactions on hover<small>1-click react, no menu needed</small></td>
|
||||
<td>Quick emoji reactions on hover<small>one click react, no menu needed</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>3 recent emoji in hover bar;<br>dismisses emoji picker</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>hover bar, no recents</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>hover bar shows up to 4 recent reactions, one click</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="yes">✓</span><small>hover bar shows recent reactions, one click</small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>In-app notification toasts<small>TDS-styled, when window focused</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>slides in bottom-right;<br>4 s auto-dismiss, click to jump</small></td>
|
||||
<td>In app notification toasts<small>TDS styled, when window focused</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>slides in bottom right;<br>4 s auto dismiss, click to jump</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -1435,10 +1441,10 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<td><span class="no">✗</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>On-device message translation<small>read foreign messages in your language</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>100% on-device browser AI;<br>works in E2EE rooms, no cloud;<br>Chromium desktop & Lotus app</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td>On device message translation<small>read foreign messages in your language</small></td>
|
||||
<td class="ours"><span class="yes">✓</span><small>100% on device browser AI;<br>works in E2EE rooms, no cloud;<br>Chromium desktop & Lotus app</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="part">~</span><small>iOS only (Apple Translation)</small></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
<td><span class="no">✗</span></td>
|
||||
@@ -1450,7 +1456,7 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
</div><!-- table-wrap -->
|
||||
|
||||
<div class="security-note" style="margin:14px 16px 6px;">
|
||||
<strong>Encryption architecture:</strong> Element X uses the native <strong>matrix-rust-sdk</strong> with Vodozemac. FluffyChat and Commet use <strong>matrix-dart-sdk</strong>, which also wraps Vodozemac for its crypto — all three benefit from Vodozemac's stronger security track record over the older JavaScript SDK. Cinny and Element Web/Desktop currently use <strong>matrix-js-sdk</strong>; Element is actively migrating to the Rust SDK. Clients using Vodozemac were not affected by historical js-sdk vulnerabilities.
|
||||
<strong>Encryption architecture:</strong> Element X uses the native <strong>matrix-rust-sdk</strong> with Vodozemac. FluffyChat and Commet use <strong>matrix-dart-sdk</strong>, which also wraps Vodozemac for its crypto, so all three benefit from Vodozemac's stronger security track record over the older JavaScript SDK. Cinny and Element Web/Desktop currently use <strong>matrix-js-sdk</strong>; Element is actively migrating to the Rust SDK. Clients using Vodozemac were not affected by historical js-sdk vulnerabilities.
|
||||
</div>
|
||||
|
||||
<div class="legend">
|
||||
@@ -1467,7 +1473,7 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<div class="info-grid">
|
||||
<div class="info-item">
|
||||
<div class="info-label">Access</div>
|
||||
<div class="info-value">Invite-only</div>
|
||||
<div class="info-value">Invite only</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div class="info-label">Max Upload</div>
|
||||
@@ -1493,16 +1499,16 @@ Client comparison last reviewed <time datetime="2026-09-23">2026-09-23</time>
|
||||
<div class="privacy-strip">
|
||||
<span class="privacy-badge">No ads or tracking</span>
|
||||
<span class="privacy-badge">No data sold</span>
|
||||
<span class="privacy-badge">E2EE — server cannot read encrypted rooms</span>
|
||||
<span class="privacy-badge">E2EE: the server cannot read encrypted rooms</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legal-note">
|
||||
This service is provided "as-is" with no uptime guarantee. Not for emergency use — do not use to contact emergency services (e.g. 911). Use is governed by our <a href="https://wiki.lotusguild.org/en/Legal/terms-of-service" target="_blank" rel="noopener">Terms of Service</a> and <a href="https://wiki.lotusguild.org/en/Legal/privacy-policy" target="_blank" rel="noopener">Privacy Policy</a>. Governing law: State of Ohio, United States.
|
||||
This service is provided "as is" with no uptime guarantee. Not for emergency use. Do not use to contact emergency services (e.g. 911). Use is governed by our <a href="https://wiki.lotusguild.org/en/Legal/terms-of-service" target="_blank" rel="noopener">Terms of Service</a> and <a href="https://wiki.lotusguild.org/en/Legal/privacy-policy" target="_blank" rel="noopener">Privacy Policy</a>. Governing law: State of Ohio, United States.
|
||||
</div>
|
||||
|
||||
<div class="contact">
|
||||
<p style="font-size:0.85rem;color:#777;margin-bottom:4px;">Questions or need a registration token?</p>
|
||||
<p style="font-size:0.85rem;color:#777;margin-bottom:4px;">Questions or need an account?</p>
|
||||
<p>Reach out to <code class="homeserver">@jared:matrix.lotusguild.org</code></p>
|
||||
</div>
|
||||
|
||||
|
||||
+2
-2
@@ -418,12 +418,12 @@ th:first-child {
|
||||
background: #111;
|
||||
}
|
||||
tr.section-header td {
|
||||
/* section headers span full width — override sticky bg */
|
||||
/* section headers span full width: override sticky bg */
|
||||
position: static;
|
||||
background: rgba(152,0,0,0.06);
|
||||
}
|
||||
|
||||
/* Scroll hint — visible only on mobile via JS class */
|
||||
/* Scroll hint: visible only on mobile via JS class */
|
||||
.scroll-hint {
|
||||
display: none;
|
||||
font-size: 0.72rem;
|
||||
|
||||
Reference in New Issue
Block a user