Commit Graph

81 Commits

Author SHA1 Message Date
jared 4a87588435 feat(calls): selectable incoming-call ringtone (#4)
Adds a ringtoneId setting (classic | chime | soft | retro | none) so the
incoming-call ring is no longer hardcoded to call.ogg. The three synth
styles are generated in-browser via a new utils/ringtones.ts module
(mirroring the existing callSounds.ts WebAudio pattern), so no new binary
assets are bundled; 'classic' keeps the existing call.ogg clip and 'none'
is a silent, visual-only incoming-call UI.

- ringtones.ts: startRingtone() loops until stopped; previewRingtone()
  plays a single non-looping preview and auto-cancels the prior preview.
- IncomingCall: ring driven by the setting; <audio> element removed.
- Settings > Calls: Ringtone selector with on-select preview, beside the
  existing Ringtone Volume slider.
- settings.ts: persisted value whitelisted back to a known id.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 17:25:32 -04:00
jared 4a4dede105 fix(media-gallery): dock as a flex sibling like MembersDrawer (was floating)
CI / Build & Quality Checks (push) Successful in 10m34s
CI / Trigger Desktop Build (push) Successful in 6s
The real reason the gallery didn't look or function like the Members drawer
or Saved Messages: it was a position:fixed overlay floating over the timeline,
mounted from RoomViewHeader. Now it docks into the room layout row exactly like
MembersDrawer.

- new mediaGalleryAtom (mirrors bookmarksPanelAtom) holds the open state
- RoomViewHeader toggles the atom instead of local useState and no longer
  renders the panel
- Room.tsx renders <MediaGallery> as a flex sibling of the timeline with a
  vertical Line separator on desktop and key={room.roomId} to reset per room
- MediaGallery.css: static width on desktop, position:fixed inset:0 full-screen
  only on mobile (identical strategy to MembersDrawer.css); root Box shrink="No"

The panel now shares the row with the timeline instead of overlapping it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 16:14:50 -04:00
jared a77c4b6db5 feat(calls): configurable ringtone volume in Settings (Bug #4 partial)
CI / Build & Quality Checks (push) Successful in 10m29s
CI / Trigger Desktop Build (push) Successful in 15s
Adds 'Ringtone Volume' slider (0–100, default 70%) to Settings → Calls.
The IncomingCall audio element reads the setting and applies it as
audioElement.volume before playing, replacing the implicit browser
default of 1.0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 18:56:04 -04:00
jared a6bf4eb7e7 feat(tauri): proactive update notifications via toast (P5-40)
TauriUpdateFeature component in ClientNonUIFeatures checks for updates
on mount and every 12h (skips if checked within the window). On update
available, fires a Lotus toast: "Lotus Chat vX.Y.Z is ready to install."
Clicking the toast calls install(). No-op on web (isTauri guard).

Also adds optional onClick to ToastNotif type and wires it in
LotusToastContainer so custom click handlers can skip hash navigation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 15:39:23 -04:00
jared 04b56ffacd feat(denoise): add self-hosted DeepFilterNet 3 ML noise-suppression model
Integrate DeepFilterNet 3 (deepfilternet3-noise-filter@1.2.1) as a new
client-side denoise model id 'deepfilternet', mirroring the DTLN pattern.

The npm package ships only an ESM whose AudioWorklet processor + wasm-bindgen
glue are inlined as a string (loaded via a Blob URL — no CDN for the worklet).
Its only runtime fetches are a single-threaded df_bg.wasm and an ONNX model
tarball, which previously loaded from an external CDN. We now VENDOR both
(build/denoise-vendor/deepfilternet/v2/...) and self-host them under
denoise/deepfilternet/, overriding the package's cdnUrl so nothing hits the
upstream CDN — keeping it self-hosted / Tauri-CSP safe.

The wasm is single-threaded (no SharedArrayBuffer / atomics / imported shared
memory), so it needs no COOP/COEP cross-origin isolation and runs fine in EC's
non-isolated iframe. Runs at 48 kHz fullband. Any init/runtime failure falls
back to the raw mic, like the other models.

- vite.config.js: copy ESM + vendored wasm/model into the EC denoise dir with a
  required-asset guard that aborts the build if any entry is missing.
- build/lotus-denoise.js: 'deepfilternet' branch — dynamic-import the ESM, build
  a DeepFilterNet3Core pointed at the self-hosted base, await init, return the
  worklet node; 48 kHz; raw-mic fail-safe preserved.
- denoisePipeline.ts: 'deepfilternet' branch for the in-app tester + sampleRate.
- settings.ts: add 'deepfilternet' to DenoiseModelId + getSettings whitelist.
- lotusDenoiseUtils.ts: add the comparison-chart row.
- General.tsx: add the "DeepFilterNet 3 (beta)" dropdown option.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 19:57:08 -04:00
jared 86272b6b08 fix(calls): wire DTLN ML denoise correctly via @workadventure JS API
CI / Build & Quality Checks (push) Successful in 10m25s
CI / Trigger Desktop Build (push) Successful in 6s
The prior DTLN attempt (89a2321d) broke the build (missing dep, wrong
`cinny/` asset paths) and typecheck (`'dtln'` not in DenoiseModelId), and was
wired against an API the package doesn't expose. @workadventure/noise-
suppression is not a flat AudioWorklet — it's a self-contained ES module whose
processor name is `workadventure-noise-suppression` and which resolves its own
LiteRT WASM + TFLite models via import.meta.url. Driving it by hand-rolled
addModule + processorOptions cannot work.

- Re-add @workadventure/noise-suppression@0.0.4 (package.json + lockfile).
- vite: copy the package's whole dist/ tree intact to
  denoise/workadventure/ (preserving assets/ + vendor/litert) so import.meta
  resolution works at runtime; fail the build if the entry module is missing.
- shim: for the DTLN model, dynamic-import denoise/workadventure/audio-worklet
  .js and use createNoiseSuppressionAudioWorklet(ctx, { bypassUntilReady })
  to build the node; RNNoise/Speex keep their direct flat-worklet path. Async
  init errors are logged + reported and fall back to the raw mic.
- Restore 'dtln' in DenoiseModelId (+ settings coercion), the model chart, and
  the settings dropdown, labelled "(beta)".

DTLN builds and is fully self-hosted, but its in-call audio is UNVERIFIED in
this environment — needs a real-call test. DeepFilterNet stays excluded (CDN
asset loading, incompatible with self-hosting / Tauri CSP).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 17:11:45 -04:00
jared 6634b2b8a2 fix(calls): make ML denoise build-honest + gate desktop trigger on CI
CI / Build & Quality Checks (push) Successful in 10m41s
CI / Trigger Desktop Build (push) Successful in 6s
Audit/repair of the multi-model denoise work so it actually builds and only
exposes working, self-hosted models.

- Complete the DTLN/DFN3 revert: uninstall @workadventure/noise-suppression
  and deepfilternet3-noise-filter (package.json + lockfile), drop the unused
  DTLN asset-copy block from vite.config.js (was shipping ~2MB of unused
  tflite/wasm), and narrow DenoiseModelId to the bundled models (rnnoise,
  speex). Coerce any retired persisted model value back to the default.
- Fix General.tsx CI typecheck failures introduced by the denoise UI: restore
  three imports the rewrite deleted (useDateFormatItems, SequenceCardStyle,
  useTauriUpdater), add the missing denoise/sound imports, and correct
  hallucinated Folds props (Text has no variant/bold; Box uses
  alignItems/justifyContent). tsc now passes with 0 errors.
- Harden the vite denoise plugin: required RNNoise/Speex/gate assets and the
  shim now fail the build loudly if missing (instead of a silent warn that
  shipped a broken ML feature), and the index.html shim injection is verified.
- CI: move the cinny-desktop submodule bump into ci.yml as a `trigger-desktop`
  job gated on `needs: build`, and delete the standalone trigger-desktop.yml.
  A failing push no longer kicks off the slow Tauri builds in parallel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 01:42:21 -04:00
jared 5d5f5f4516 feat(calls): implement advanced multi-model ML noise suppression system
CI / Build & Quality Checks (push) Failing after 4m49s
Trigger Desktop Build / trigger (push) Successful in 11s
Implement a flexible, multi-model noise suppression pipeline for Element Call/LiveKit integration:

- ML Engines: Added support for RNNoise, Speex, DTLN, and DeepFilterNet 3 models.
- Pipeline Architecture: Implemented modular audio processing in lotus-denoise.js, supporting 'Series Suppression' (running browser-native NSNet2 before ML) and a hardware-style Noise Gate.
- UI & UX Enhancements:
  - Settings UI: Added model comparison chart with CPU/Quality metadata.
  - Tuning: Added Live Microphone Meter for calibrating Noise Gate thresholds.
  - Reporting: Added LotusToast system to alert users when ML suppression fails or falls back to raw input.
- Robustness & Quality:
  - Capture Fidelity: Removed forced 48kHz capture constraints to allow native-rate capture (solving static issues with high-end audio interfaces).
  - Performance: Added WASM SIMD detection with transparent fallback.
  - Capability Detection: Added browser feature detection to disable unsupported ML modes.
- Build Integration: Updated Vite config to self-host all model WASM/tflite assets in /denoise/ directory.
2026-06-16 00:50:12 -04:00
jared 5deed79b42 feat(calls): 3-tier mic noise suppression with on-device ML (P5-30)
CI / Build & Quality Checks (push) Successful in 10m33s
Trigger Desktop Build / trigger (push) Successful in 6s
Replace the boolean call noise-suppression setting with a 3-way control
(Off / Browser-native / ML beta) in Settings -> General -> Calls.

- Off: noiseSuppression=false to Element Call
- Browser-native: EC's built-in WebRTC suppressor (prior default)
- ML (beta): on-device RNNoise (@sapphi-red/web-noise-suppressor)

Element Call captures the mic inside its iframe and publishes to LiveKit,
so the host can't reach that track; LiveKit's Krisp filter is Cloud-only
(we self-host the SFU) and EC's own RNNoise PR #3892 is unmerged. The ML
tier instead injects a same-origin pre-init shim into the vendored EC
index.html (build/lotus-denoise.js, wired by the lotusDenoise vite plugin)
that patches getUserMedia and routes the captured mic through an RNNoise
AudioWorklet before LiveKit sees it -- the same post-capture pipeline as
#3892, with no EC fork/AGPL/rebase burden. Falls back to the raw mic if
setup fails; keeps echoCancellation/AGC on the raw capture.

- settings.ts: callNoiseSuppression -> 'off'|'browser'|'ml' + legacy
  boolean migration (true->browser, false->off)
- CallEmbed/useCallEmbed: tier maps to noiseSuppression param and appends
  lotusDenoise=ml (native suppressor off in ML mode)
- vite.config.js: copy RNNoise worklet/wasm + shim into the EC bundle and
  inject the shim <script> before EC's module entry
- docs: LOTUS_FEATURES.md, LOTUS_TODO.md (P5-30 done)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 20:29:59 -04:00
jared 10f6544e2e fix: avatar decoration centering, animation flickering, scheduled message persistence
CI / Build & Quality Checks (push) Successful in 10m32s
Trigger Desktop Build / trigger (push) Successful in 7s
- UserHero: move AvatarDecoration inside AvatarPresence so the decoration
  inline-flex container sizes to the avatar only, not the presence badge
- SidebarNav: add will-change: background-position, background-size on
  document.body for animated backgrounds, promoting them to a compositor
  layer so overlaid text/UI doesn't repaint on every animation frame
- scheduledMessages: back the atom with atomWithStorage so the scheduled
  message tray survives page refreshes via localStorage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 00:32:04 -04:00
jared 6db07f1371 feat: seasonal theme overlays + improved animated chat backgrounds
Adds 11 CSS-only seasonal overlays (Halloween, Christmas, New Year, Autumn,
April Fool's, Lunar New Year, Valentine's Day, St. Patrick's Day, Earth Day,
Deep Space, Retro Arcade) with date-based auto-detection and a manual override
dropdown in Settings → Appearance → Seasonal Theme. All themes respect
prefers-reduced-motion. SeasonalEffect mounts at z-index 9997 in App.tsx.

Also rewrites all 5 animated chat background keyframes for smoother, more
organic motion: Digital Rain gains a phosphor glow flicker; Star Drift now
loops each layer by exactly its own tile size (no more seam); Grid Pulse adds
an independent brightness oscillation at a prime period; Aurora Flow drives
all four gradient layers through distinct paths; Fireflies adds glow-pulse and
opacity-blink animations at prime periods for unsynchronised bioluminescence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 00:33:04 -04:00
jared 702e2e00eb feat: voice channel user limit (P5-10) + call join/leave sounds (P5-16)
CI / Build & Quality Checks (push) Successful in 10m54s
Trigger Desktop Build / trigger (push) Successful in 6s
P5-10 Voice Channel User Limit:
- New StateEvent.LotusVoiceLimit (io.lotus.voice_limit) with { max_users }
- RoomVoiceLimit admin control in Room Settings > General > Voice
  (power-level gated via permissions.stateEvent)
- CallPrescreen reads the limit reactively and disables Join with a
  'Channel Full (N/N)' message at capacity; existing members can rejoin

P5-16 Custom Join/Leave Sound Effects:
- useCallJoinLeaveSounds hook wired into CallUtils; detects participant
  join/leave via MatrixRTCSession membership changes (sender|deviceId),
  filters out self, only fires while joined
- Sounds synthesized in-browser with Web Audio (callSounds.ts) - no
  assets bundled; styles Off/Chime/Soft/Retro
- 'Join & Leave Sounds' selector in Settings > Calls (previews on change)

Docs: LOTUS_FEATURES.md, README.md, LOTUS_TODO.md (P5-10/P5-16 marked done)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 22:20:22 -04:00
jared 362f4943d4 feat: knock notifications for admins + AFK auto-mute in calls
CI / Build & Quality Checks (push) Successful in 10m26s
Trigger Desktop Build / trigger (push) Successful in 14s
P4-3 — Knock-to-join Notifications for Admins:
- usePendingKnocks() hook reactively tracks knocking members via
  RoomMemberEvent.Membership; returns empty array if user lacks invite power
- Members icon in RoomViewHeader shows a Warning badge with the knock count
  when there are pending requests; badge updates in real time without
  needing to open the drawer; aria-label updated to describe pending count

P5-11 — AFK Auto-Mute in Voice:
- useAfkAutoMute() hook opens a monitoring-only getUserMedia stream,
  connects it to an AnalyserNode, and polls RMS every 500ms
- If mic is on and RMS stays below threshold for the configured timeout,
  calls callEmbed.control.setMicrophone(false) and shows an in-app toast
- Hook is called inside CallControls so monitoring is only active during calls
- Settings: afkAutoMute toggle + afkTimeoutMinutes select (1/5/10/20/30 min,
  default 10) added to Settings → Calls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 19:53:19 -04:00
jared 5469740f4c feat: P5-21 mention color, P5-22 font selector, P5-27 notification presets; update docs
CI / Build & Quality Checks (push) Successful in 10m27s
Trigger Desktop Build / trigger (push) Successful in 7s
- P5-21: Custom @mention highlight color picker in Settings → Appearance.
  CSS vars with luminance-computed text color; resets cleanly to theme default.
- P5-22: Font selector (System, Inter, JetBrains Mono, Fira Code) in
  Settings → Appearance. Fira Code added to Google Fonts preload.
- P5-27: Gaming/Work/Sleep preset buttons at top of Settings → Notifications.
  Each atomically applies a group of notification settings.
- AppearanceEffects component in App.tsx applies CSS vars on settings change.
- LOTUS_BUGS.md: mark presence + manifest icon bugs as resolved.
- LOTUS_TODO.md: mark P3-6, P5-21, P5-22, P5-27 as [x].
- LOTUS_FEATURES.md: document all four completed features.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 15:39:35 -04:00
jared 891f2daf99 feat(P3-6): configurable composer toolbar buttons
CI / Build & Quality Checks (push) Successful in 10m24s
Trigger Desktop Build / trigger (push) Successful in 7s
Each button (Format, Emoji, Sticker, GIF, Location, Poll, Voice,
Schedule) can be individually hidden in Settings → Editor.
All default to on, stored in composerToolbarButtons object.
getSettings deep-merges the nested object so new buttons default
to true for existing users with saved settings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 13:20:29 -04:00
jared 9447e64e5e feat(P5-4): animated chat backgrounds + pause toggle
5 new CSS-only animated backgrounds in the chat background picker:
- Digital Rain: two-layer vertical stripe scroll with parallax (wide
  stripes at 8s, narrow at 4s via single keyframe with split positions)
- Star Drift: three-layer radial-gradient star field drifting diagonally
- Grid Pulse: neon grid lines that expand/contract (backgroundSize keyframe)
- Aurora Flow: large radial gradient bands sweeping across 200% canvas
- Fireflies: three layers of glowing dots drifting across the viewport

All use vanilla-extract keyframes (GPU-composited transforms/positions,
no canvas, no JS timers). prefers-reduced-motion is respected in
getChatBg() by stripping the animation property at call time. A "Pause
Background Animations" toggle in Settings → Appearance provides an
in-app override for the same purpose.

BG labels de-duplicated ("Digital Rain", "Star Drift", "Aurora Flow")
to avoid the duplicate "Stars" and "Aurora" entries that had appeared.
LIGHT anim-fireflies background corrected from near-black #0a0a10 to
warm white #fffdf0. Four unused keyframe exports removed from
Animations.css.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:46:16 -04:00
jared c6932b45fb feat: glassmorphism sidebar toggle (P5-3)
Settings → Appearance: "Glassmorphism Sidebar" toggle (off by default).
When enabled, applies backdrop-filter: blur(12px) and a semi-transparent
background to the left sidebar so chat background patterns show through.
SidebarGlass vanilla-extract class in Sidebar.css.ts; wired in
SidebarNav.tsx via classNames conditional.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:02:18 -04:00
jared 517e992dec fix: prettier formatting in toast.ts (trailing commas)
Fixes CI Prettier check failure on commit 4876c2e4.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:01:54 -04:00
jared 4876c2e4ca feat: quick emoji reactions on hover, in-app notification toasts, mention pulse audit
P5-17: MessageQuickReactions moved from 3-dots menu to hover toolbar;
shows 5 recent emoji directly on hover. Clicking a quick-reaction also
closes any open emoji picker (setEmojiBoardAnchor). Line separator
removed from component.

P5-7: LotusToastContainer slides in from bottom-right when window is
focused — replaces OS notification for in-focus events. Correct room
path (DM vs home) derived from mDirectAtom. Invite toast routes to
inbox. 4s auto-dismiss. Full TDS styling via CSS custom properties.

P5-8: Confirmed already implemented upstream (MentionHighlightPulse,
0.6s scale+glow, one-shot, prefers-reduced-motion). Marked complete.

Code-review fixes: toast navigation used nonexistent /room/ route;
emoji picker stayed open after toolbar quick-reaction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 21:32:37 -04:00
jared 657ca3a5ca feat: GIF previews, room context menu, policy lists, mention pulse, collapsible messages, send animation, D&D fix
P3-5: Giphy/Tenor URL preview cards — full-width thumbnail from og:image
mxc URL, GIF badge overlay, site badge + title footer; GifCard shared by
both; BadgeGiphy (teal) and BadgeTenor (blue) CSS classes

P3-9: Policy list viewer — read-only panel in Room Settings + Space
Settings (admin/50+ PL only); enter room ID or alias; tabs for Users /
Rooms / Servers; glob pattern warning color; Ban badge; entity + reason

P5-8: Mention highlight pulse — 0.6s scale+glow keyframe on incoming
@mention messages; prefers-reduced-motion aware; only fires on new
incoming messages (isNewRef), not on history load; onAnimationEnd cleanup

P5-19: Collapsible long messages — ResizeObserver clamps text bodies
>320px with gradient fade + "Read more ↓" / "Show less ↑" button; resets
on eventId change; skips images/video/audio/file; smooth CSS transition

P5-23: Message send animation — own messages fade+scale in (0.97→1,
0.4→1 opacity, 150ms ease-out); prefers-reduced-motion aware; one-shot
via isNewRef + onAnimationEnd clear

P5-26: Room context menu — Copy Link (matrix.to URL, 1.5s Copied!
feedback), Mute with duration (15m/1h/8h/24h/indefinite, localStorage
timer key io.lotus.mute_timers), Mark as read; Icons.Link + Icons.BellMute

BUG D&D: dragCounter ref replaces fragile dragState machine — enter
increments, leave decrements (hides at 0), drop resets to 0; fixes
spurious dragleave from child element boundary crossings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 15:51:18 -04:00
jared 9273eb5f2e feat: bookmarks, message scheduling, image compression, room insights
P3-1: Message Bookmarks — right-click any message to bookmark; saved to
io.lotus.bookmarks account data (max 500, syncs across devices); star
icon in sidebar opens BookmarksPanel with filter, Jump-to-message, and
remove buttons; reactive to AccountData events

P3-2: Message Scheduling (MSC4140) — clock button next to send opens
ScheduleMessageModal with datetime-local picker; validates ≥1 min future;
calls PUT org.matrix.msc4140 delayed event API; collapsible
ScheduledMessagesTray above composer lists pending messages with cancel;
local Jotai atom tracks scheduled messages per room

P3-3: File Upload Compression — opt-in checkbox per JPEG/PNG file ≥200KB
in upload preview; canvas API compresses at 0.82 quality; shows before/
after size estimate; compressed blob used in upload when checked

P3-7: Room Insights — new Insights tab in room settings; top 5 active
members (bar chart), top 5 reactions (chips), media breakdown (4 tiles),
24-hour activity heatmap (CSS bar chart); all from local cache only with
disclaimer banner; never the first tab shown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 10:26:08 -04:00
jared 51a355fe77 feat: extended profile fields, push rule editor, server ACL editor
P2-8: Pronouns (m.pronouns) and Timezone (m.tz) fields in Settings →
Account → Profile; saved via MSC4133 PUT /profile/{userId}/{field};
useExtendedProfile hook fetches both in parallel; UserHero displays
pronouns below display name and timezone string below username

P2-11: Full push rule editor in Settings → Notifications below keyword
rules; covers override/room/sender/underride rule kinds; enable/disable
toggle per rule, human-readable labels for built-in rules, delete button
for custom rules, add-rule form for room and sender rules

P2-12: Server ACL viewer/editor in room settings (Server ACL tab);
reads m.room.server_acl state event; allow/deny server lists with
wildcard validation; allow IP literals toggle; power-level gated
(edit requires sufficient PL, otherwise read-only view)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 23:13:33 -04:00
jared ee717e8361 feat: PiP mute indicator, export history, activity log, unverified device warning
- PiP call window: mute overlay using MutationObserver on EC iframe's
  [data-testid="incall_mute"] button (data-kind="primary" = muted),
  same pattern as screenshare detection in CallControl.ts

- P2-4 Export Room History: new tab in room settings — Plain Text / JSON /
  HTML formats, optional date range, progress counter, paginated via
  paginateEventTimeline, blob download; E2EE-aware (skips failed decryptions)

- P2-6 Room Activity Log: new tab in room settings — filterable log of
  m.room.member, m.room.power_levels, m.room.name/topic/avatar/server_acl
  events with human-readable descriptions, relative timestamps, Load More
  pagination

- P2-10 Unverified Device Warning: warnOnUnverifiedDevices setting (default
  off); Warning.Container banner above composer in encrypted rooms with
  unverified devices; toggle in Settings → General → Privacy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 22:13:22 -04:00
jared 5ae84cbeaf feat: P2-3 sort rooms, P2-5 quiet hours, P2-2 custom notification sounds
P2-3 — Sort Non-Space Rooms:
- homeRoomSort: 'recent' | 'alpha' | 'unread' setting (default 'recent')
- factoryRoomIdByUnread comparator: unread rooms first, tie-break by count
- Sort icon button in Rooms NavCategoryHeader opens PopOut menu with
  three options (Recent Activity / A→Z / Unread First), checkmark on active
- Collapsed state still filters to unread-only regardless of sort choice

P2-5 — Notification Quiet Hours:
- quietHoursEnabled / quietHoursStart / quietHoursEnd added to settings
  (defaults: false, '23:00', '08:00')
- isInQuietHours() helper handles both normal and overnight spans;
  start===end treated as zero-length window (disabled) to avoid silent no-op
- Both InviteNotifications and MessageNotifications gate notify() and
  playSound() behind the quiet-hours check
- Settings → Notifications: new Quiet Hours card with Switch + two
  <input type="time"> fields (only shown when enabled)

P2-2 — Custom Notification Sounds:
- messageSoundId / inviteSoundId settings: 'notification'|'invite'|'call'|'none'
- notificationSounds.ts: shared NOTIFICATION_SOUND_MAP (removes duplication
  between ClientNonUIFeatures and SystemNotification — code review fix)
- Audio source updated reactively via useEffect when sound ID changes
- Settings → Notifications: Message Sound + Invite Sound selects expand
  when the master sound toggle is on; each has a ▶ preview button
- playPreview() catches audio.play() rejections (code review fix)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 19:41:02 -04:00
jared e18e089043 revert: remove redundant QuickSwitcher (Ctrl+K already does this better)
The existing SearchModalRenderer (Ctrl+K) is already a polished room/DM
switcher with avatars, unread badges, fuzzy search, and keyboard nav.
Our QuickSwitcher was an inferior duplicate. Removing it entirely:
- Delete QuickSwitcher.tsx
- Remove QuickSwitcherFeature from ClientNonUIFeatures
- Remove quickSwitcherKey from settingsAtom
- Remove Keyboard Shortcuts section from General settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 01:03:50 -04:00
jared 9d4679d260 feat: configurable keybindings for push-to-deafen and quick switcher
- Add deafenKey (default M) and quickSwitcherKey (default P) to settingsAtom
- Settings → Calls: Push to Deafen keybind tile using shared useKeyBind hook
- Settings → Keyboard Shortcuts: new section with Quick Room Switcher keybind
- Extract useKeyBind + keyLabel helpers to reduce duplication in Calls section
- CallControls reads deafenKey from settings (reactive, re-registers on change)
- ClientNonUIFeatures reads quickSwitcherKey from settings (same pattern)
- QuickSwitcher now toggles open/closed on repeat press (Ctrl+key again closes)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 00:45:43 -04:00
jared afe957015b feat: P1 features — voice speed, private receipts, room filter, favorites, invite link, poll creation
P1-5: Voice message playback speed toggle (0.75×/1×/1.5×/2×) in AudioContent.tsx
P1-10: Private read receipts toggle in Privacy settings; wired to notifications.ts
P1-3: Room filter input on Home tab and DMs tab (client-side, clears on tab switch)
P1-8: Favorite rooms via m.favourite tag — Favorites section in Home sidebar, star/unstar in right-click menu
P1-9: Room invite link + QR code in room settings (Share Room tile, api.qrserver.com QR)
P1-6: Poll creation modal in composer (PollCreator.tsx, sends m.poll.start)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 19:31:30 -04:00
jared dedbd54199 feat: typing indicator orange dots, push-to-deafen hotkey, night light filter, message length counter
- #108: TypingIndicator reads lotusTerminal setting; applies var(--lt-accent-orange)
  to container so dots inherit via backgroundColor:currentColor
- #100: CallControls registers KeyM as push-to-deafen (e.code, e.repeat guard,
  ownerDocument.body iframe-safe editable check, [callEmbed] dep array)
- P5-5: nightLightEnabled/nightLightOpacity settings; position:fixed rgba(255,140,0)
  overlay inside JotaiProvider; Night Light tile + intensity slider (5–80%) in
  Settings → Appearance
- #101: RoomInput charCount state via Slate onChange + toPlainText; resets on
  room switch; displayed before send button when count > 0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 15:36:45 -04:00
jared 572bc6a4c0 feat: add Report Room (MSC4151) and fix URL preview default for encrypted rooms
- Report Room: new ReportRoomModal with reason + category, POST /rooms/{id}/report
- URL preview: encUrlPreview default changed to true; security note added to settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 17:11:21 -04:00
jared bd8e116cf3 feat: Discord-style presence status selector
Adds a manual presence picker to the sidebar user avatar. Clicking the
avatar opens a popout menu with Online, Idle, Do Not Disturb, Invisible,
and Auto (activity-based) options. The selected status is shown as a
colored badge on the avatar and stored in settings (survives reloads).

usePresenceUpdater now short-circuits for manual states and only runs
the full activity-tracking logic in Auto mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 23:29:29 -04:00
jared 08b1a5c2a3 feat: full Discord-style presence tracking
- Announce online immediately on app startup
- Idle detection: unavailable after 10 min of no input, online on return
- Tab visibility: unavailable when hidden, online when focused again
- Page close: offline via fetch+keepalive (survives unload without bfcache penalty)
- hidePresence setting: broadcasts offline and stops all tracking
- Added 'Hide Online Status' toggle in General settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 19:28:52 -04:00
Lotus Bot 266e47f240 chore: upgrade TypeScript 4.9 to 5.9, ESLint 8.29 to 8.57, @typescript-eslint 5 to 7
Resolves all TS2345/TS2347/TS7006 type errors introduced by stricter TypeScript 5.x.
Fix Icons.Settings to Icons.Setting, cast account data returns, fix implicit any.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 11:16:11 -04:00
Lotus Bot 61a1f008d0 chore: upgrade i18next 26, prettier 3, fontsource-variable, domhandler 6, lint-staged 17
- i18next 23->26 + react-i18next 15->17
- prettier 2->3, reformat all files
- replace @fontsource/inter with @fontsource-variable/inter 5, update import path
- domhandler 5->6 (aligns with transitive deps)
- lint-staged 16->17
2026-05-21 23:30:50 -04:00
Lotus Bot d32055ee3d chore: bulk dependency updates + fix immer v11 default import + sentry test
Package updates (safe minor/major bumps, all build-verified):
- @tanstack/react-query 5.24->5.100, react-virtual 3.2->3.13
- jotai 2.6->2.20, immer 9->11, dayjs, chroma-js, classnames, blurhash
- slate/slate-dom/slate-react 0.123->0.124
- focus-trap-react 10->12, react-error-boundary 4->6
- html-dom-parser 4->7, html-react-parser 4->6
- pdfjs-dist 4->5, ua-parser-js 1->2
- i18next-http-backend 3->4, i18next-browser-languagedetector 8.0->8.2
- react-aria 3.29->3.48, matrix-widget-api 1.16->1.17
- @atlaskit/pragmatic-drag-and-drop* minor bumps
- @rollup/plugin-inject 5.0.3->5.0.5, @rollup/plugin-wasm 6.1->6.2
- @element-hq/element-call-embedded 0.19.3->0.19.4
- @types/* patches, eslint-plugin-* minors

Breaking change fix:
- immer v11 removed default export; updated 11 files to named import

Temporary: add Sentry test button to WelcomePage for verification.
Remove after confirming errors reach the dashboard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 22:23:19 -04:00
Lotus Bot 42b9cc2b64 chore: prettier format all files, brotli, Sentry release tagging, CI gates
Prettier: auto-formatted 103 files to fix baseline. Prettier check in CI
  is now a hard gate (removed continue-on-error).

Brotli: installed libnginx-mod-http-brotli-filter/static. Enabled in nginx
  with brotli_static on for pre-compressed assets and comp_level 6.

Sentry releases: deploy script now exports VITE_APP_VERSION=<git-short-sha>
  before building so each Sentry release maps to an exact commit.
  CI also passes github.sha as VITE_APP_VERSION.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 20:49:33 -04:00
Lotus Bot ff7c2ed941 Bug fixes, security hardening, and performance improvements
- BUG-16: Fixed pagination deadlock (fetching flag stuck on error path)
- BUG-17: Fixed absoluteIndex===0 falsy check skipping unread jump
- BUG-19: Fixed mEvt.getRoomId()! non-null assertion crash
- BUG-20: Wrapped getSettings()/setSettings() in try/catch for corrupt localStorage
- SEC: Replaced randomStr() Math.random() with crypto.getRandomValues() CSPRNG
- SEC: Fixed afterLoginRedirectPath open redirect validation
- SEC: Narrowed OSM iframe sandbox to scripts-only (removed allow-same-origin)
- Perf-2: Memoized selectAtom in useSetting (prevented new atom ref per render)
- Perf-4: Fixed typingMembers setTimeout leak (tracked timers per user/room)
- Perf-8: Memoized getChatBg() result in RoomView (not inline in JSX)
- Perf-12: Replaced body.class * font-family with body.class (inherited)
- Perf-15: Memoized typingNames array chain in RoomViewTyping
- Perf-9: Added blob URL cleanup useEffect in AudioContent
- BUG: Fixed forEach(async) -> Promise.all in useCommands join handler
- BUG: Fixed useCompositionEndTracking missing dependency array
- A11y: Fixed spoiler button aria-pressed + keyboard handler
- A11y: Added aria-label to Send message button
- Build: Set sourcemap:false, removed netlify.toml from copyFiles

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 21:11:38 -04:00
root 4c4d61600d feat: reaction TDS styling, debounce read receipts, Escape to skip boot, type fixes
- lotus-terminal.css.ts: add reaction chip styles for dark + light TDS modes
  (cyan border/bg for unselected, orange accent for own/pressed reactions)
- useRoomReadPositions: debounce receipt handler at 150ms (M-3)
- lotus-boot.ts: Escape key skips boot animation (I-3)
- RoomInput.tsx: replace (uploadRes as any) with typed assertion (M-7)
- CallEmbedProvider: call mention detection, audio cleanup, display name (C-1, C-2, M-5)
- EventReaders: timestamps in seen-by modal, filter self, TDS styling
- ReadReceiptAvatars: StackedAvatar pill, TDS visual treatment
- chatBackground: add waves/neon/aurora backgrounds
- RoomView: auto-apply tactical bg when TDS active and bg is none
- settings: extend ChatBackground union type
2026-05-16 01:34:20 -04:00
root d81c3c8721 fix: call system bugs and security hardening
- CallEmbed: fix memory leak — mx event listeners were never removed
  because dispose() called .bind(this) again, creating new function
  objects. Now uses arrow class fields so start()/dispose() share the
  exact same reference.
- callPreferences: toggleVideo is a no-op when cameraOnJoin=false,
  preventing internal state drift from the returned value.
- CallControls: PTT key guard now blocks on SELECT elements and walks
  the DOM for inherited contentEditable to prevent key interception
  inside dropdowns and custom editors.
- RoomInput: GIF fetch validates Giphy CDN domain allow-list,
  HTTP Content-Type header, and enforces 20 MB size cap.
2026-05-15 15:08:55 -04:00
root 8ebb1a8d8c chore: merge v4.12.1 — security, calling, editor, media fixes
Key v4.12.1 changes merged:
- Security: sanitize-html updated to v2.17.4
- Calling: video calls in DMs/rooms, user avatars during calls, right-click to start
- Calling: IncomingCallListener with ring sound and answer/reject UI
- Editor: list crash fixes (Firefox + empty headings), codeblock filename support
- Media: URL preview hover state, keyboard nav, click-to-open, OGG audio support
- Date: ISO 8601 (YYYY-MM-DD) date format option
- Misc: stable mutual rooms endpoint, Android notification crash fix

Lotus customisations preserved:
- PiP drag/resize, DM call ring notification, PTT, GIF picker, noise suppression
- Poll voting, message forwarding, image captions, location sharing
- Lotus Terminal design theme
2026-05-15 13:43:04 -04:00
root 86464f4981 feat: poll voting, location sharing, image captions, message forwarding
- Poll voting: PollContent sends m.poll.response on answer click
- Location: MLocation shows OSM map embed + share-location button in toolbar
- Image captions: caption field on media uploads sets message body
- Message forwarding: ForwardMessageDialog with searchable room picker
- Also includes ring timeout fix and earlier session patches
2026-05-15 13:37:03 -04:00
root 038bde8b62 feat(call): PTT, deafen label, camera default off, screenshare confirm, noise suppression setting
- Push to Talk: keydown/keyup binds mic to configurable key (default Space)
  with visual PTT indicator and key-binding UI in Settings > General > Calls
- Camera always defaults OFF on join; cameraOnJoin setting for explicit opt-in
- Deafen button tooltip corrected to Deafen/Undeafen instead of Turn Off/On Sound
- Screenshare confirmation dialog before broadcasting to call participants
- Noise suppression toggle wired from settings through CallEmbed URL params
- CallControl.setMicrophone() public method for programmatic mic control
- Calls settings section added to General settings page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:14:04 -04:00
root 893aa92b38 Deepen TDS integration: full terminal CSS coverage + 3 new backgrounds
Terminal Mode:
- Text selection: orange highlight rgba(255,107,0,0.28)
- Links: cyan (#00D4FF) with orange hover glow (#FF6B00)
- Code/pre: TDS green (#00FF88) on terminal bg, left green border
- Strong/b → orange, em/i → cyan, mark → amber, del → red
- Blockquote: orange left border (matches chat reply quotes)
- HR: cyan border with dim glow
- Input/textarea/[contenteditable] focus: orange glow ring
- Tables: TDS headers (orange+uppercase), cyan borders, hover rows
- List markers: cyan ▸ for ul, orange for ol
- Boot box-drawing alignment fixed (51→52 ═)
- data-theme=\"dark\" set on html element when terminal active
- Updated description: correct TDS palette names
- ▶ Boot replay button in settings (visible when terminal on)

Chat backgrounds (+3):
- Tactical: LotusGuild TDS exact cyan dot-grid (28px)
- Circuit: green grid + node dots on dark terminal bg
- Hex Grid: isometric cyan hexagonal outlines

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:44:34 -04:00
root f3ec49fe88 Add Lotus Terminal Mode + fix all remaining Cinny branding
- New: Lotus Terminal Mode toggle in Appearance settings
  - Red phosphor color scheme (bg #0a0000, primary #ff3300, accent #00dd66)
  - Monospace font override (JetBrains Mono / Fira Code / Cascadia Code)
  - Retro CRT scanline overlay via CSS pseudo-element
  - Wired into ThemeManager with dedicated lotusTerminalBodyClass
- Branding: replace all user-visible Cinny references with Lotus Chat
  - WelcomePage, AuthLayout, SplashScreen, index.html meta tags
  - Device display names in login/register/token flows
  - System notification brand field
  - (Preserved internal Matrix protocol CinnySpaces event type)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:22:06 -04:00
root 5f0aa5c887 Add chevron, polka, triangles, plaid backgrounds 2026-05-13 22:01:16 -04:00
root 0df997eecf Redesign chat backgrounds: blueprint, carbon, stars, topographic, herringbone, crosshatch 2026-05-13 21:42:12 -04:00
root dcb3ff3129 Phase 2+3: Chat backgrounds and per-message profiles settings 2026-05-13 21:17:59 -04:00
ranidspace 955f1f89a1 feat: add YYYY-MM-DD (ISO 8601) date format to presets (#2712)
* Add YYYY-MM-DD (ISO 8601) date format to presets

* Fix formatting due to added date format
2026-03-27 21:20:10 +11:00
Krishan a0e9ba0f55 feat: Add voice/video room support (#2680)
* Add users on the nav to showcase call activity and who is in the call

* add check to prevent DCing from the call you're currently in...

* Add avatar and username for the space (needs to be moved into RoomNavItem proper)

* Add background variant to buttons

* Update hook to keep method signature (accepting an array of Rooms instead) to support multiple room event tracking of the same event

* Add state listener so the call activity is real time updated on joins/leaves within the space

* Add RoomNavUser for displaying the user avatar + name in the nav for a visual of call activity and participants

* rename CallNavBottom to CallNavStatus

* Rename callnavbottom and fix linking implementation to actually be correct

* temp fix to allow the status to be cleared in some way

* re-add background to active call link button

* prepare to feed this to child elements for visibility handling

* loosely provide nav handling for testing refactoring

* Add CallView

* Update to funnel Outlet context through for Call handling (might not be the best approach, but removes code replication in PersistentCallContainer where we were remaking the roomview entirely)

* update client layout to funnel outlet the iframes for the call container

* funnel through just iframe for now for testing sake

* Update room to use CallView

* Pass forward the backupIframeRef now

* remove unused params

* Add backupIframeRef so we can re-add the lobby screen for non-joined calls (for viewing their text channels)

* Remove unused imports and restructure to support being parent to clientlayout

* Re-add layout as we're no longer oddly passing outlet context

* swap to using ref provider context from to connect to persistentcallcontainer more directly

* Revert to original code as we've moved calling to be more inline with design

* Revert to original code as we've moved the outlet context passing out and made more direct use of the ref

* Fix unexpected visibility in non-room areas

* correctly provide visibility

* re-add mobile chat handling

* Improve call room view stability

* split into two refs

* add ViewedRoom usage

* Disable

* add roomViewId and related

* (broken) juggle the iframe states proper... still needs fixing

* Conditionals to manage the active iframe state better

* add navigateRoom to be in both conditions for the nav button

* Fix the view to correctly display the active iframe based on which is currently hosting the active call (juggling views)

* Testing the iframe juggling. Seems to work for the first and second joins... so likely on the right path with this

* add url as a param for widget url

* fix backup iframe visibility

* Much closer to the call state handling we want w/ hangups and joins

* Fix the position of the member drawer to its correct location

* Ensure drawer doesn't appear in call room

* Better handling of the isCallActive in the join handler

* Add ideal call room join behavior where text rooms to call room simply joins, but doesn't swap current view

* Fix mobile call room default behavior from auto-join to displaying lobby

* swap call status to be bound to call state and not active call id

* Remove clean room ID and add default handler for if no active call has existed yet, but user clicks on show chat

* Applies the correct changes to the call state and removes listeners of old active widget so we don't trigger hang ups on the new one (the element-call widget likes to spam the hang up response back several times for some reason long after you tell it to hang up)

* Remove superfluous comments and Date.now() that was causing loading... bug when widgetId desynced

* Remove Date.now() that was causing widgetId desync

* add listener clearing, camel case es lint rule exception, remove unneeded else statements

* Remove unused

* Add widgetId as a getWidgetUrl param

* Remove no longer needed files

* revert ternary expression change and add to dependency array

* add widgetId to correct pos in getWidgetUrl usage

* Remove CallActivation

* Move and rename RoomCallNavStatus

* update imports and dependency array

* Rename and clean up

* Moved CallProvider

* Fix spelling mistake

* Fix to use shorthand prop

* Remove unneeded logger.errors

* Fixes element-call embedded support (but it seems to run poorly)

* null the default url so that we fallback to the embedded version (would recommend hosting it until performance issue is determined)

* Fix vite build to place element-call correctly for embedded npm package support

* add vite preview as an npm script

* Move files to more correct location

* Add package-lock changes

* Set dep version to exact

* Fix path issue from moving file locations

* Sets initial states so the iframes don't cause the other to fail with the npm embedded package

* Revert navitem change

* Just check for state on both which should only occur at initial

* Fixes call initializing by default on mobile

* Provides correct behavior when call isn't active and no activeClientWidgetApi exists yet

* Corrects the state for the situations where both iframes are "active" (not necessarily visible)

* Reduce code reuse in handleJoin

* Seems to sort out the hangup status button bug the occurred after joining a call via lobby

* Re-add the default view current active room behavior

* Remove repetitive check

* Add storing widget for comparing with (since we already store room id and the clientWidgetApi anyway)

* Update rendering logic to clear up remaining rendering bug (straight to call -> lobby of another room and joining call from that interface -> lobby of that previous room and joining was leading to duplication of the user in lobbies. This was actually from listening to and acknowledging hangups from the viewed widget in CallProvider)

* Prevent null rooms from ever rendering

* This seems to manage the hangup state with the status bar button well enough that black screens should never be encountered

* Remove viewed room setting here and pass the room to hang up (seems state doesn't update fast enough otherwise)

* Remove unused

* Properly declare new hangup method sig

* Seems to avoid almost all invalid states (hang up while viewing another lobby and hitting join seems to black screen, sets the active call as the previous active room id, but does join the viewed room correctly)

* Fix for cases where you're viewing a lobby and hang up your existing call and try to join lobby (was not rendering for the correct room id, but was joining the correct call prior)

* Re-add intended switching behavior

* More correct filter (viewedRoom can return false on that compare in some cases)

* Seems to shore up the remaining state issues with the status bar hangup

* Fix formatting

* In widget hang up button should be handled correct now

* Solves the CHCH sequence issue, CLJH remains

* Fixes CLJH, found CCH

* Solves CCH. Looks like CLCH left

* A bit of an abomination, but adds a state counter to iteratively handle the diverse potential states (where a user can join from the nav bar or the join button, hang up from either as well, and account for the juggling iframes)
Black screens shouldn't be occurring now.

* Fix dependency array

* Technically corrects the hangup button in the widget, should be more precise though

* Bind the on messaging iframe for easier access in hangup/join handling

* Far cleaner and more sensible handling of the call window... I just really don't like the idea of sending a click event, but right now the element-call code treats preload/skipLobby hangups (sent from our end) as if they had no lobby at all and thus black screens. Other implementation was working around that without just sending a click event on the iframe's hangup button.

* Fixes a bug where if you left a call then went to a lobby and joined it didn't update the actual activeCallRoomId

* Fixes complaints of null contentDocument in iframe

* Update to use new icons (thank you)

* Remove unneeded prop

* Re-arrange more options and add checks for each option to see if it is a call room (probably should manage a state to see if a header is already on screen and provide a slightly modified visual based on that for call rooms)

* Invert icons to show the state instead of the action they will perform (more visual clarity)

* Update src/app/features/room-nav/RoomCallNavStatus.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomCallNavStatus.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomCallNavStatus.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomCallNavStatus.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomCallNavStatus.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomCallNavStatus.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomNavItem.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room/RoomViewHeader.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomNavItem.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomNavItem.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomNavItem.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomNavItem.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomNavItem.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomNavItem.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomNavUser.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomNavUser.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room-nav/RoomNavUser.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/pages/client/space/Space.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/call/CallView.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/call/CallView.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/call/CallView.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room/RoomView.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room/RoomView.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* adjust room header for calling

* Remove No Active Call text when not in a call

* update element-call version

* Update src/app/features/room/RoomViewHeader.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room/RoomViewHeader.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room/RoomViewHeader.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room/RoomViewHeader.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Update src/app/features/room/RoomViewHeader.tsx

Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>

* Revert most changes to Space.tsx

* Show call room even if category is collapsed

* changes to RoomNavItem, RoomNavUser and add useCallMembers

* Rename file, sprinkle in the magic one line for matrixRTCSession. and remove comment block

* swap userId to callMembership as a prop and add a nullchecked userId that uses the membership sender

* update references to use callMembership instead

* Simplify RoomNavUser

Discard future functionality since it probably won't exist in time for merging this PR

* Simplify RoomViewHeader.tsx

Remove unused UI elements that don't have implemented functionality. Replace custom function for checking if a room is direct with a standard hook.

* Update Room.tsx to accomodate restructuring of Room, RoomView and CallView

* Update RoomView.tsx to accomodate restructuring of Room, RoomView and CallView

* Update CallView.tsx to accomodate restructuring of Room, RoomView and CallView + suggested changes

* add call related permissions to room permissions

* bump element call to 0.16.3, apply cinny theme to element call ui, replace element call lobby (backup iframe) with custom ui and only use element call for the in-call ui

* update text spacing

* redo roomcallnavstatus ui, force user preferred mute/video states when first joining calls, update variable names and remove unnecessary logic

* set default mic state to enabled

* clean up ts/eslint errors

* remove debug logs

* format using prettier rules from project prettierrc

* fix: show call nav status while active call is ongoing

* fix: clean up call nav/call view console warnings

* fix: keep call media controls visible before joining

* fix: restore header icon button fill behavior

Fixes regression from b074d421b66eb4d8b600dfa55b967e6c4f783044.

* style: blend header and room input button styles in call nav

* fix page header background color on room view header

* fix: permissions and room icon resolution (#2)

* Initialize call state upon room creation for call rooms, remove subsequent useless permission

* handle case of missing call permissions

* use call icon for room item summary when room is call room

* replace previous icon src resolution function with a more robust approach

* replace usages of previous icon resolution function with new implementation

* fix room name not updating for a while when changed

* set up framework for room power level overrides upon room creation

* override join call permission to all members upon room creation

* fix broken usages of RoomIcon

* remove unneeded import

* remove unnecessary logic

* format with prettier

* feat: show connected/connecting call status

* fix: preserve navigation context when opening non-call rooms

* fix: reset room name state when room instance changes

* feat: Disable webcam by default using callIntent='audio'

* Add channel type selecor

* Add option for voice rooms, which for now sets the default selected
option in the creation modal

* Add proper support for room selection from the enu

* Move enums to `types.ts` and change icons selection to use
`getRoomIconSrc`

* fix: group duplicate conditions into one

* fix: typo

* refactor: rename kind/voice to access/type and simplify room creation

- rename CreateRoomVoice to CreateRoomType and modal voice state to type
- rename CreateRoomKind to CreateRoomAccess and KindSelector to AccessSelector
- propagate access/defaultAccess through create room and create space forms
- set voice room power levels via createRoom power_level_content_override

* refactor: unify join rule icon mapping and update call/space icons

- bump folds from 2.5.0 to 2.6.0
- replace separate room/space join-rule icon hooks with useJoinRuleIcons(roomType)
- route join-rule icons through getRoomIconSrc for consistent room type handling
- simplify getRoomIconSrc by removing the locked override path
- use VolumeHighGlobe for public call rooms and VolumeHighLock for private call rooms

* chore(deps): bump matrix-widget-api to 1.17 and remove react-sdk-module-api

* fix: adapt SmallWidget to matrix-widget-api 1.17.0 API

* fix: render call room chat only when chat panel is open

* fix(permissions): show call settings permissions only for call rooms

* refactor: remove redundant room-nav props/guards and minor naming cleanup

* fix: use PhoneDown icon for hang up action

* chore(hooks): remove unused useStateEvents hook

* fix(room): enable members drawer toggle in desktop call rooms

- show filled User icon when the drawer is open

* Revert "fix: adapt SmallWidget to matrix-widget-api 1.17.0 API"

This reverts commit a4c34eff8a.

* fix: semi-revert matrix-widget-api 1.17 bump and migrate to 1.13 API

* fix(call): wait for Element Call contentLoaded before widget handshake

- fixes not working on firefox

* fix missing imports

* improve create room type design and add beta badge for voice room

* add beta badge for voice room in space lobby

* fix create room modal title

* pass missing roomType param to roomicon component

* add roomtype

* Add deafen functionality (#2695)

* feat:(deafen functionality)

* feat:(reworked voice controls for deafen)

* ref:(use muted instead of volume for deafen)

* fix:(backpedal audio_enabled rename)

* ref:(renaming of deafened vars)

* add stack avatar component

* add call status bar - WIP

* remove call status from navigation drawer

* fix deprecated method use in use call members hook

* render new call status bar

* move call widget driver to plugins

* remove old status bar usage from navigation drawer

* add call session and joined hook

* remove unknown changes

* upgrade widget api

* add element call embed plugin

* remove unknown change

* add call embed atom

* add call embed hooks and context

* add call embed provider

* replace old call implementation

* stop joining other call on second click if already in a call

* refactor embed placement hook

* add merge border prop to sequence card

* add call preferences

* add prescreen to call view - WIP

* prevent joining new call if already in call

* make call layout adaptive

* render call chat as right panel

* show call members in prescreen

* render call join leave event in timeline

* remove unknown rewrite in docker-nginx file

* render call event without hidden event enable

---------

Co-authored-by: Gigiaj <gigiaboone@yahoo.com>
Co-authored-by: Jaggar <18173108+GigiaJ@users.noreply.github.com>
Co-authored-by: Gimle Larpes <97182804+GimleLarpes@users.noreply.github.com>
Co-authored-by: Gimle Larpes <gimlelarpes@gmail.com>
Co-authored-by: YoJames2019 <jamesclark1700@gmail.com>
Co-authored-by: YoJames2019 <yobiscuit0@gmail.com>
Co-authored-by: hazre <mail@haz.re>
Co-authored-by: haz <37149950+hazre@users.noreply.github.com>
Co-authored-by: Ajay Bura <32841439+ajbura@users.noreply.github.com>
Co-authored-by: James <49845975+YoJames2019@users.noreply.github.com>
Co-authored-by: James Reilly <jreilly1821@gmail.com>
Co-authored-by: Tymek <vonautymek@gmail.com>
Co-authored-by: Thedustbuster <92692948+Thedustbustr@users.noreply.github.com>
2026-03-07 18:03:32 +11:00
Mari e92295f930 fix: Prevent IME-exiting Enter press from sending message on Safari (#2175)
On most browsers, pressing Enter to end IME composition produces this
sequence of events:
* keydown (keycode 229, key Processing/Unidentified, isComposing true)
* compositionend
* keyup (keycode 13, key Enter, isComposing false)

On Safari, the sequence is different:
* compositionend
* keydown (keycode 229, key Enter, isComposing false)
* keyup (keycode 13, key Enter, isComposing false)

This causes Safari users to mistakenly send their messages when they
press Enter to confirm their choice in an IME.

The workaround is to treat the next keydown with keycode 229 as if it
were part of the IME composition period if it occurs within a short time
of the compositionend event.

Fixes #2103, but needs confirmation from a Safari user.
2025-09-25 09:05:42 +05:30
Ajay Bura 1b89475fa7 Remove unused javascript (#2470) 2025-08-29 19:34:52 +10:00