12e62db76fd9b12795ae75091959699c70020f8f
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
12e62db76f |
v6.8.2: the keyboard no longer pushes the chat off the screen on iOS
Reported from an iPhone, with a screenshot: tap the message box, the keyboard comes up, and the whole app has slid off the top — header gone, only the bottom edge of the composer left, black underneath it down to the keyboard. That is the visual viewport being panned. WebKit shrinks it for the keyboard and then moves it down inside the layout viewport (which it does not shrink) to reveal the focused field. The shell had shrunk correctly, to the top --sb-vh of the layout viewport; the window had simply moved off it. No CSS declines that pan, and it is not a document scroll, so there is no scrollTop to put back. So the shell is pinned to the visible rect: fixed to the layout viewport and translated by visualViewport.offsetTop. The earlier objection to pinning is kept where it was right — HEIGHT still moves on resize only, which is what stopped the layout twitching under the finger, and the offset rides a transform rather than `top`. The first cut of this had a guard that silently disabled it: the pan was only followed when window.innerHeight was much taller than the visual viewport, i.e. "a keyboard is covering us". That assumes iOS never resizes the layout viewport, which stopped being safe once WebKit started honouring interactive-widget. Only a pinch-zoomed page switches the pan off now, by scale, and offsetTop is believed whenever it is non-zero. The offset is also re-read across the keyboard's animation on focusin/focusout: on iOS 26 the viewport is documented not to settle back immediately on dismissal. The message list stays at the newest message across a keyboard open or close, instead of holding a scroll position from the taller layout and leaving the last few messages under the composer. Two smaller things on the same screen: The QR code closes itself once the safety number appears. It was only dismissed when both exchange flags cleared, and those stay set through verification, so a one-time credential sat on top of the code the user was meant to be reading. The disconnect button's label is hidden wherever the button becomes a 40px square. Its own rule stopped at 560px while the square starts at 768px, so between the two the word was still inside the box, pushing the icon off centre. ?vvdebug=1 paints the viewport numbers over the app — visible rect height, offset, scale, what the shell resolved to. A phone cannot be put on a debugger and none of those numbers show up in a screenshot of the result; this one is how the guard above was caught. Off unless named in the URL. Claude-Session: https://claude.ai/code/session_01R63J7dexujFQCJpDAeKxr9 |
||
|
|
4000bde857 |
v6.8.1: the downloads point at desktop 1.0.3
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 |
||
|
|
9e63cf65a4 |
v6.8.0: light theme
The palette lived as ~620 hex literals in inline styles plus a few hundred more in
the stylesheets, so there was no single thing to change. It is now 113 custom
properties in src/styles/theme.css, in two blocks.
src/scripts/theme-boot.js decides the theme before first paint — blocking, in <head>,
above the stylesheet, because a deferred script paints dark first and corrects itself.
It stores the mode ('system' | 'light' | 'dark'), never the colour it resolved to, and
stamps data-theme so an explicit choice can beat the media query. The switcher in the
header is a view onto it.
A filled accent stays the brand colour in both themes — the ink on it is near-black
either way — while an accent used as text darkens to clear 4.5:1 on white. A colour
reaches a fill by four routes (a style property, a constant, a helper argument, an SVG
source string), and tests/theme-switching.test.mjs covers all four.
The dark theme is unchanged: every colour declaration the previous build produced comes
out of this one identically once the properties are resolved.
Also: the roadmap drops its status chips on mobile, and Roadmap.jsx no longer splits a
colour with parseInt at runtime, which a var() reference cannot survive.
|
||
|
|
414c27fda6 |
v6.7.3: faster loading, and pages search engines can read
The bundles carried all thirteen translations at once and a page fetched them a third time as raw source; each page now loads only its own language. Alongside that: JavaScript is minified, the eight stylesheets are served as one file, the QR scanner is fetched after the app is up instead of on every visit, Inter ships once rather than five copies of the same file, and Font Awesome is subset to the 82 icons this app draws instead of all 2468. 1.85 MB across 43 requests becomes under 700 KB across 33. On mobile the page starts drawing in 1.6 s instead of 6.3 s and is usable in 4.5 s instead of 11 s. Pages also carry their text in the HTML now. Everything was drawn by JavaScript into an empty div, so crawlers saw correct metadata around nothing, and twelve of the thirteen language pages had never been shown to anyone. The documentation is published under /docs/ with a new FAQ, and unknown addresses return a real 404. Separately: the localized shells were served with the year-long immutable cache header meant for static assets, which pinned anyone who opened /de/ or /ru/ to that build. The header is fixed and the service worker refreshes what it cached. Claude-Session: https://claude.ai/code/session_014KjzTXxrhzYoDDWChYQ4u2 |
||
|
|
3212138a0d |
docs: reorganise documentation; derive header version from package.json; release v5.7.2
No protocol or message-protection changes. The version in the application header was a literal and had fallen behind, showing v5.6.0 while running 5.7.1. It now comes from package.json, and a test fails if a hard-coded one reappears or if meta.json, the README badge, the changelog and the docs disagree about the release. Documentation reorganised so that everything technical lives in doc/ with an index, and the root keeps only what belongs there by convention: README, SECURITY, CHANGELOG and LICENSE. - SECURITY.md rewritten. It listed a supported release line three major versions out of date and made claims the software does not make. It now states what is guaranteed, what is not, and how to report a problem. - SECURITY_DISCLAIMER.md and RESPONSIBLE_USE.md merged into doc/USE-POLICY.md, which says what the software cannot protect against rather than listing generic advice. - doc/SECURITY-ARCHITECTURE.md renamed to doc/ARCHITECTURE.md and rewritten around the session lifecycle, what verification gates, and how recovery works. - doc/CRYPTOGRAPHY.md rewritten: key schedule, the Double Ratchet, framing, and memory handling, with values taken from the source rather than restated. - doc/CONFIGURATION.md rewritten with the real file-type policy, ICE and TURN guidance, and the deployment caching rules that matter. - docs/webrtc-config.md moved to doc/CALLS.md and rewritten; the obsolete docs/webrtc-audit.md, a working document full of stale line numbers, removed along with the docs/ directory. - doc/CONTRIBUTING.md records what the recent regressions taught us about writing tests that can actually fail. - doc/README.md added as an index. Internal security review notes are excluded from the repository via .gitignore. Those describe attack paths against specific releases in enough detail to reproduce them, which is useful privately and harmful in public while users are still updating. |
||
|
|
b3fcf54670 |
feat(webrtc): end-to-end encrypted voice & video calls with adaptive codecs
Add 1:1 voice and video calling over the existing SAS-verified peer connection. Audio and video tracks ride the same RTCPeerConnection as the chat, bundled onto one DTLS-SRTP transport, so media inherits the session's end-to-end encryption. SDP offer/answer is renegotiated in-band over the verified data channel — no signalling server, so the media's DTLS fingerprints are authenticated end-to-end. Calls are gated on a connected, SAS-verified session. Codecs & adaptation: - Opus tuned for lossy links (in-band FEC, DTX, RED redundancy); audio is bandwidth-prioritised and never throttled. - VP9/AV1 single-encoding SVC with H.264/VP8 fallback; video degrades by spatial/temporal layer. - Runtime NetworkAdaptationController trims video bitrate on loss/RTT and recovers as the link clears — no renegotiation. Live connection-quality indicator (Excellent/Good/Fair/Weak) in the call UI. In-call controls: mute, camera on/off (voice→video upgrade in-band), camera flip, minimize-to-widget, hang up, and accept/decline for incoming calls. Production logging disabled (DEBUG_MODE=false); temporary call diagnostic logger removed. Codec rationale in docs/webrtc-config.md. |