Commit Graph

23 Commits

Author SHA1 Message Date
jared d46b91b1b8 feat(rooms): Mark as Unread (MSC2867) + Low Priority rooms
Two Matrix protocol gaps (Phase A), gate-green (683 tests):
- Mark as Unread: m.marked_unread room account data (+ com.famedly.marked_unread
  fallback), a new markedUnreadAtom binder that seeds from account data and
  clears on our own read receipt (MSC2867). RoomNavItem gains Mark as Unread /
  Read menu items and lights the row dot for a marked room. Tested.
- Low Priority: m.lowpriority room tag mirroring favourites — a context-menu
  toggle (mutually exclusive with Favorite) and a collapsed Low Priority
  category sorted to the bottom of the Home room list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 00:04:47 -04:00
jared b7788cc79c docs: mark D6 Windows rich-toast AUMID fixed + add runtime test
CI / Build & Quality Checks (push) Successful in 10m41s
CI / Trigger Desktop Build (push) Successful in 7s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 22:32:31 -04:00
jared a899d7d3a8 fix(privacy): generate invite QR locally instead of api.qrserver.com (H5)
The Share Room QR was fetched from the third-party api.qrserver.com, leaking
which rooms a user shares (and failing offline / under strict CSP). Now rendered
locally via qrcode.react (QRCodeSVG) — no network request, works offline. Added a
white quiet-zone container so the code scans on any theme; dropped the qrError
fallback (local generation can't fail the same way). Removed api.qrserver.com
from the prod CSP img-src (matrix repo). Build verified (rolldown interop OK).
Verification steps added to LOTUS_TESTING.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 22:19:22 -04:00
jared abd0753148 fix(notifications): safe thread receipts on mark-read (fixes read-receipt regression)
CI / Build & Quality Checks (push) Failing after 35m56s
CI / Trigger Desktop Build (push) Has been skipped
The prior thread-receipt change (8192da5a) broke read receipts globally. Exact
cause: markAsRead used `thread.lastReply() ?? thread.rootEvent`. When a thread's
replies weren't loaded (lastReply() null — common on room open), it sent a
receipt for the thread ROOT. Since roots are "in the main timeline",
threadIdForReceipt() makes that a MAIN receipt at an old event; when the root
isn't in the loaded timeline the SDK's backward-guard falls back to timestamp
and applies it, moving the main read receipt onto an event we don't have, so
getEventReadUpTo() returns null and roomHaveUnread() reports the room unread —
re-broken on every mark-read, amplified by the bulk mark-all-orphan-rooms-read
callers.

Fix: main unthreaded receipt unchanged; the thread loop now sends a threaded
receipt ONLY for a genuine loaded thread reply (thread.lastReply()), never the
root — if replies aren't loaded, skip. New notifications.test.ts locks the
regression (null lastReply → no root receipt) + the main/threaded/no-op cases.

Gates: tsc/eslint/prettier clean, build OK, 672 tests (7 new).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 17:09:28 -04:00
jared 8192da5a12 fix(notifications): clear thread receipts on mark-read; cap avatar-decoration refetch
CI / Build & Quality Checks (push) Successful in 10m41s
CI / Trigger Desktop Build (push) Successful in 29s
Two federated-room bugs surfaced by the desktop build:

1. markAsRead only sent one unthreaded receipt at the main-timeline tail. With
   threadSupport enabled, thread replies leave the main timeline, so a reply
   newer than that tail was never covered — its per-thread notification count
   (which the room dot sums) lingered, so the unread dot never cleared even
   after reading. It also early-returned when the main timeline was already
   read. Now also send a threaded receipt at each unread thread's latest reply.

2. useAvatarDecoration never cached non-404 failures, so every avatar mount
   re-requested io.lotus.avatar_decoration for federated users whose homeserver
   403s/502s the field — a refetch storm that spammed the console and hammered
   our homeserver's federation. Now cache definitive rejections (400/403/404)
   and give up after ~2 transient (429/5xx) attempts per session.

Gates: tsc/eslint/prettier clean, build OK, 665 tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 16:31:10 -04:00
jared 6dc478e989 fix(desktop): Custom Window Chrome toggle breaks the timeline (P5-47)
CI / Build & Quality Checks (push) Successful in 10m35s
CI / Trigger Desktop Build (push) Successful in 9s
Toggling custom chrome expanded the screen and sent the message feed
auto-scrolling into the past. Two causes:
- DesktopChrome used height:100vh while html/#root use 100dvh; in the Tauri
  webview 100vh can exceed the visible height after decorations are stripped,
  making the timeline's scroll container taller than the viewport → the virtual
  paginator runs away paginating backwards. Switched to 100dvh.
- Toggling live reflowed the whole app while the timeline was mounted. The
  setting now persists + reloads so the layout is rebuilt cleanly (description
  updated: "reloads to apply").

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 16:16:52 -04:00
jared 049472e25f feat(crypto) + docs: request persistent storage; consolidate docs to 3
CI / Build & Quality Checks (push) Successful in 10m54s
CI / Trigger Desktop Build (push) Successful in 12s
- index.tsx: request navigator.storage.persist() for logged-in sessions so the
  browser can't evict the IndexedDB rust-crypto store (eviction while the
  localStorage session survives resurrects the device with a blank store → the
  KE-1 "one time key already exists" upload storm). Guarded, checks persisted()
  first, best-effort.
- Docs: remove HANDOFF_ELEMENT_CALL_FORK.md, LOTUS_E2EE_INVESTIGATION.md, and
  LOTUS_BUGS.md. Port their live content into the three kept docs — verification
  backlog → LOTUS_TESTING; open bugs + E2EE (KE-1..4) + an Element Call fork
  operational reference (publish steps + io.lotus action catalog) → LOTUS_TODO.
  Fix all dangling references (README, code comments, cross-doc links). Full
  history of the removed docs remains in git.

Gates: tsc/eslint/prettier clean, build OK, 665 tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 15:28:09 -04:00
jared 899a14c119 docs: P3-4 accessibility — features section, TODO/BUGS, LOTUS_TESTING §P
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 11:45:22 -04:00
jared 8ab1ec254b docs(testing): add July batch — threads, per-thread notifs, math, search cache, session, audit wave, desktop CSP (§O)
Fills the gap where LOTUS_BUGS referenced test IDs (P3-8/P4-1/P4-4/P4-8/N97a/
AW-1..4) with no matching procedures in the testing guide.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 10:15:48 -04:00
jared 7c06b27c73 feat(call): in-call soundboard, quality controls, room call-permissions
CI / Build & Quality Checks (push) Successful in 10m49s
CI / Trigger Desktop Build (push) Successful in 8s
Element Call is now consumed as our self-built fork
(@lotusguild/element-call-embedded); wire up its previously-dormant
capabilities and document the fork as live.

Soundboard (P5-15): a call-bar button plays user-uploaded audio clips into the
call as a real published track (io.lotus.inject_audio) plus local playback.
Clips are uploadable like emoji/sticker packs, stored in io.lotus.soundboard
account data (synced across devices). Gated by a Settings toggle + volume.

Quality controls (P5-31): per-user mic/screenshare bitrate + screenshare
framerate (Settings -> Calls), applied via io.lotus.set_quality clamped to any
room cap. Room admins set caps and hard call-permissions (allow_screenshare /
allow_camera) in Room Settings -> Voice; the call bar hides blocked buttons.

- New: CallSoundboard, useSoundboard, soundboardClips; RoomQuality,
  useCallQuality, callQuality (+ unit tests).
- Optimistic-write RoomQuality admin UI (no stale-state clobber).
- Docs: mark EC fork live across README/FEATURES/TODO/BUGS/TESTING; add D2
  manual-test steps.

Numeric quality caps are client-cooperative; screenshare/camera permissions are
hard-enforced server-side (see LotusGuild/matrix voice-limit-guard).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 22:34:17 -04:00
jared 5af024f7e7 docs: consolidate EC test checklist into LOTUS_TESTING.md (§D2)
CI / Build & Quality Checks (push) Successful in 11m28s
CI / Trigger Desktop Build (push) Successful in 20s
Fold the Element Call fork Phase-2 feature tests into the canonical testing
guide as §D2 (denoise reconnect/device-switch/4 models, event-driven
speaker/mute, focus-during-screenshare, in-call decorations, transparency,
+ the dormant #3/#7). Each item keeps a plain / outcome for non-dev
testers, so the standalone ELEMENT_CALL_TEST_CHECKLIST.md is removed — all
in one place.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 17:40:02 -04:00
jared efcee88f05 docs(test): add OIDC/MSC3861 test section + local MAS dev loop
CI / Build & Quality Checks (push) Successful in 13m42s
CI / Trigger Desktop Build (push) Successful in 33s
LOTUS_TESTING.md section N (N1-N6): OIDC login flow, session-persist-on-reload,
token refresh, logout revocation, account-management link, and the non-OIDC
regression check. Backed by dev/oidc-test/ — a runnable local Matrix
Authentication Service + Synapse(msc3861) loop (compose skeleton, the Synapse
experimental_features delta, and the public/config.json override) so the flow
can be verified without a mozilla.org tester.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 17:04:24 -04:00
jared cbfd3e5632 docs: N108 -> Needs-Verification; add L2 maskable-icon test
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 21:27:57 -04:00
jared bab3a160c2 docs: move N95 to Needs-Verification (fixed); update L1 test to verify-mode
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 21:18:08 -04:00
jared 6218012d3f docs: mark P5-2 + pinned filter done; add M4/M5 test steps
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 16:58:22 -04:00
jared da545ba9b9 docs: mark P5-1 + search filters/recent done; add M1-M3 test steps
CI / Build & Quality Checks (push) Failing after 1h27m15s
CI / Trigger Desktop Build (push) Has been skipped
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 14:24:18 -04:00
jared 84a2e7a93e fix(settings): restore background swatch grid layout; verify N4 poll fix
CI / Build & Quality Checks (push) Successful in 10m30s
CI / Trigger Desktop Build (push) Successful in 11s
- Add grow="Yes" to ChatBgGrid and SeasonalBgGrid containers so they
  expand to fill their flex parent — without it the Box shrank to one
  column (~76px wide) because folds Box defaults to display:flex and
  the wrapper is a flex-row with no explicit width.
- Mark N4 (PollContent) FIXED  VERIFIED in LOTUS_BUGS.md after
  confirmed pass on default Cinny themes and Lotus TDS.
- Mark B1 and B4 PASS in LOTUS_TESTING.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 21:30:21 -04:00
jared 91c6f2f091 fix(calls): remove misleading Retry button from call load error overlay (N96)
Both Retry and Leave called the same dismiss function; Retry implied a
reconnect attempt that never happened. Collapsed to a single Back button
that honestly describes returning to the prescreen.

docs: correct Gemini audit entries — sanitize-html not DOMPurify (Claim A),
retract inaccurate LiveKit replaceTrack soundboard approach (Claim B,
contradicts confirmed cross-origin iframe constraint), expand N95 fix note
to clarify track-stop vs AudioContext-suspend distinction.

docs(testing): add L1 N95 reproduction guide; update A7 to reflect single Back button.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 16:24:33 -04:00
jared 31cf353463 docs(testing): note EC watchdog self-heal in A7
CI / Build & Quality Checks (push) Successful in 10m26s
CI / Trigger Desktop Build (push) Successful in 8s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 18:16:22 -04:00
jared 7b94eeaa60 docs: mark N53/N81/N82 fixed; add F3/G3 visual checks to testing guide
CI / Build & Quality Checks (push) Successful in 10m27s
CI / Trigger Desktop Build (push) Successful in 8s
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 16:29:37 -04:00
jared d39aef0aac docs: add backlog (E–K) of fixed-but-unverified items to testing guide
CI / Build & Quality Checks (push) Successful in 10m27s
CI / Trigger Desktop Build (push) Successful in 19s
Sweeps every remaining "FIXED ⚠️ UNTESTED" item from LOTUS_BUGS.md and
LOTUS_TODO.md into the testing guide, grouped by environment (mobile,
theming, calls, media/perf, accessibility/screen-reader, desktop/Tauri,
features) so each category can be verified in one pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 04:07:39 -04:00
jared 9f533b1077 docs: fix section C numbering in LOTUS_TESTING.md
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 04:04:42 -04:00
jared fdaba40ba9 docs: mark N4 fixed; add LOTUS_TESTING.md manual test guide
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 04:04:21 -04:00