From 4000bde857a3c7b03719eb2f9c0eab392bafa84a Mon Sep 17 00:00:00 2001 From: lockbitchat Date: Fri, 11 Sep 2026 22:58:20 -0400 Subject: [PATCH] v6.8.1: the downloads point at desktop 1.0.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Desktop 1.0.3 fixes video on a call placed after a group call — the two shared one peer connection, the second call opened a second video section, and the two H264 profiles collided, so the call carried sound and no picture. It also ships the STUN and TURN list this client uses, which is what lets a browser and a desktop agree on a path instead of one of them offering no relay at all. The version lives in two places on this side (the landing page and the download grid), and the consistency test also reads the README badge, the changelog and the cryptography document, so all of them move together. Riding along: the group status dot now takes its colour from the theme in the call and group views, which is what the desktop's copy of groupsStore.js was compared against. Claude-Session: https://claude.ai/code/session_019RCW2Fm7dkAaU2zeHDksei --- CHANGELOG.md | 11 +++++++ README.md | 2 +- ar/index.html | 38 ++++++++++++------------ de/index.html | 38 ++++++++++++------------ dist/app-boot.js | 6 ++-- dist/app-boot.js.map | 4 +-- dist/app.js | 12 ++++---- dist/app.js.map | 6 ++-- doc/CRYPTOGRAPHY.md | 4 +-- docs/cryptography/index.html | 4 +-- es/index.html | 38 ++++++++++++------------ fa/index.html | 38 ++++++++++++------------ fr/index.html | 38 ++++++++++++------------ he/index.html | 38 ++++++++++++------------ hi/index.html | 38 ++++++++++++------------ index.html | 36 +++++++++++------------ ko/index.html | 38 ++++++++++++------------ meta.json | 14 ++++----- package.json | 2 +- ru/index.html | 38 ++++++++++++------------ sitemap.xml | 46 +++++++++++++++--------------- src/app.jsx | 22 +++++++------- src/components/ui/CallUI.jsx | 12 ++++---- src/components/ui/DownloadApps.jsx | 2 +- src/components/ui/GroupCallUI.jsx | 12 ++++---- src/components/ui/GroupChat.jsx | 25 ++++++++++------ sw.js | 2 +- tests/theme-switching.test.mjs | 31 ++++++++++++++++++-- uk/index.html | 38 ++++++++++++------------ ur/index.html | 38 ++++++++++++------------ zh/index.html | 38 ++++++++++++------------ 31 files changed, 381 insertions(+), 328 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62305a6..ccf040f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## v6.8.1 — Desktop 1.0.3 + +The download buttons point at desktop 1.0.3. That release fixes video on a call +placed after a group call — the two shared one connection, opened a second video +section, and the call carried sound with no picture — and it carries the same +STUN and TURN servers this web client uses, so a desktop and a browser can agree +on a path instead of one of them offering no relay at all. + +Light theme colours: the group status dot now reads its colour from the theme in +the call and group views as well. + ## v6.8.0 — Light theme Added a light theme. The switch is in the header next to the language menu, with three diff --git a/README.md b/README.md index 66fb95e..2b06078 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ No accounts. No servers storing your messages. No installation required. [![License: MIT](https://img.shields.io/badge/License-MIT-f0892a.svg)](LICENSE) -[![Version](https://img.shields.io/badge/version-6.8.0-3ecf8e.svg)](CHANGELOG.md) +[![Version](https://img.shields.io/badge/version-6.8.1-3ecf8e.svg)](CHANGELOG.md) [![Get it from the Snap Store](https://snapcraft.io/securebit-chat/badge.svg)](https://snapcraft.io/securebit-chat) [![PWA](https://img.shields.io/badge/PWA-installable-3ecf8e.svg)](#install-as-an-app) [![Encryption](https://img.shields.io/badge/crypto-ECDH%20P--384%20%C2%B7%20AES--256--GCM-blue.svg)](#security-model) diff --git a/ar/index.html b/ar/index.html index 04a39be..245dac8 100644 --- a/ar/index.html +++ b/ar/index.html @@ -30,18 +30,18 @@ - + - + - + @@ -116,7 +116,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -264,7 +264,7 @@ - + - - + + - + - + - + - - + + - + - + - + @@ -116,7 +116,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -264,7 +264,7 @@ - + - - + + - + - + - + - - + + ';\n }\n\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n dirty = stringifyValue(dirty);\n\n if (typeof dirty !== 'string') {\n throw typeErrorCreate('dirty is not a string, aborting');\n }\n }\n\n /* Return dirty HTML if DOMPurify cannot run */\n if (!DOMPurify.isSupported) {\n return dirty;\n }\n\n /* Assign config vars */\n if (!SET_CONFIG) {\n _parseConfig(cfg);\n }\n\n /* Clean up removed elements */\n DOMPurify.removed = [];\n\n /* Resolve IN_PLACE for this call without mutating persistent config.\n Writing the IN_PLACE closure variable here leaks under setConfig(),\n where _parseConfig is skipped on later calls: a single string call would\n disable in-place mode for every subsequent node call, returning a\n sanitized copy while leaving the caller's node \u2014 which in-place callers\n keep using and whose return value they ignore \u2014 unsanitized. REPORT-2. */\n const inPlace = IN_PLACE && typeof dirty !== 'string' && _isNode(dirty);\n\n if (inPlace) {\n /* Do some early pre-sanitization to avoid unsafe root nodes.\n Read nodeName through the cached prototype getter \u2014 a clobbering\n child named \"nodeName\" on the form root would otherwise shadow\n the property and let this check skip the root-allowlist\n validation entirely. */\n const nn = getNodeName\n ? getNodeName(dirty as Node)\n : (dirty as Node).nodeName;\n if (typeof nn === 'string') {\n const tagName = transformCaseFunc(nn);\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n throw typeErrorCreate(\n 'root node is forbidden and cannot be sanitized in-place'\n );\n }\n }\n\n /* Pre-flight the root through _isClobbered. The iterator-driven\n removal path can not detach a parent-less root: _forceRemove\n falls through to Element.prototype.remove(), which per spec\n is a no-op on a node with no parent. A clobbered root would\n then survive the main loop with its attributes uninspected,\n because _sanitizeAttributes early-returns on _isClobbered. The\n result would be an attacker-controlled form, complete with any\n event-handler attributes the caller passed in, handed back to\n the application unsanitized. Refuse to sanitize such a root\n the same way we refuse a forbidden tag. GHSA-r47g-fvhr-h676. */\n if (_isClobbered(dirty as Element)) {\n throw typeErrorCreate(\n 'root node is clobbered and cannot be sanitized in-place'\n );\n }\n\n /* Sanitize attached shadow roots before the main iterator runs.\n The iterator does not descend into shadow trees. Same fail-closed\n barrier as the main walk (campaign-3 F2): a custom-element reaction\n inside a shadow root could abort this pre-pass before the walk runs,\n which would otherwise leave the entire live tree unsanitized. */\n try {\n _sanitizeAttachedShadowRoots(dirty as Node);\n } catch (error) {\n _neutralizeRoot(dirty as Node);\n\n throw error;\n }\n } else if (_isNode(dirty)) {\n /* If dirty is a DOM element, append to an empty document to avoid\n elements being stripped by the parser */\n body = _initDocument('');\n importedNode = body.ownerDocument.importNode(dirty, true);\n if (\n importedNode.nodeType === NODE_TYPE.element &&\n importedNode.nodeName === 'BODY'\n ) {\n /* Node is already a body, use as is */\n body = importedNode;\n } else if (importedNode.nodeName === 'HTML') {\n body = importedNode;\n } else {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n body.appendChild(importedNode);\n }\n\n /* Clonable shadow roots are deep-cloned by importNode(); sanitize\n them before the main iterator runs, since the iterator does not\n descend into shadow trees. The walk routes every read through a\n cached prototype getter so clobbering descendants on a form root\n cannot hide a shadow host from this pass. */\n _sanitizeAttachedShadowRoots(importedNode);\n } else {\n /* Exit directly if we have nothing to do */\n if (\n !RETURN_DOM &&\n !SAFE_FOR_TEMPLATES &&\n !WHOLE_DOCUMENT &&\n // eslint-disable-next-line unicorn/prefer-includes\n dirty.indexOf('<') === -1\n ) {\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE\n ? _createTrustedHTML(dirty)\n : dirty;\n }\n\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n }\n }\n\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (body && FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n\n /* Get node iterator */\n const nodeIterator = _createNodeIterator(inPlace ? dirty : body);\n\n /* Now start iterating over the created document.\n The walk runs inside an exception barrier (campaign-3 F2): a re-entrant\n engine/custom-element mutation can detach a node mid-walk so\n `_forceRemove`'s parentless guard throws, aborting the loop. Without the\n barrier the caller's in-place tree would be left half-sanitized with the\n unvisited tail still armed. On any throw we fail closed \u2014 strip the\n in-place root bare \u2014 then rethrow so the existing throw contract is\n preserved. (String/DOM-copy paths never return the partial body, so the\n propagating throw is already fail-closed there.) */\n try {\n while ((currentNode = nodeIterator.nextNode())) {\n /* Sanitize tags and elements */\n _sanitizeElements(currentNode);\n\n /* Check attributes next */\n _sanitizeAttributes(currentNode);\n\n /* Shadow DOM detected, sanitize it.\n Realm-safe check (GHSA-hpcv-96wg-7vj8): nodeType-based detection\n instead of instanceof, so foreign-realm