- Wrap RoomTimeline in ErrorBoundary — a single bad event no longer
crashes the entire timeline; shows a graceful "Timeline unavailable"
message instead
- Wrap RoomInput in ErrorBoundary — composer crashes show a fallback
placeholder rather than a blank white section
- Animate SpeakerAvatarOutline with a 1.2s pulse keyframe so it's
visually distinct from a static ring; respects prefers-reduced-motion
- Fix var(--border-surface-variant) undefined variable in UserRoomProfile
device session rows; replaced with color.SurfaceVariant.ContainerLine
UNTESTED — verify at chat.lotusguild.org post-deploy.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add ReportUserModal.tsx — category dropdown + reason input, calls
POST /_matrix/client/v3/users/{userId}/report via mx.http.authedRequest,
inline success/error feedback, auto-closes 1500ms after success
- Wire Report User button into UserRoomProfile.tsx between UserModeration
and UserDeviceSessions (hidden for own profile)
- Bug #6: enforce mutual exclusion between chat backgrounds and seasonal
themes — ChatBgGrid clears seasonal→'off' on non-'none' pick;
SeasonalBgGrid clears chatBackground→'none' on real theme pick;
SeasonalEffect guards against legacy persisted state at render time
- TDS: strip all hardcoded hex/rgba fallbacks from LotusToastContainer.tsx
(var(--lt-bg-card), --lt-accent-orange, --lt-text-primary/secondary,
--lt-accent-orange-dim/border, --lt-box-glow-orange)
- Mark Bug #6 FIXED, MSC4260 DONE, toast TDS FIXED in LOTUS_BUGS.md and
LOTUS_TODO.md; note EventReaders + CallControls already compliant
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- usePresenceUpdater: replace stale closure with readStatus() called at
invocation time so changing custom status in Profile Settings is never
silently overwritten by subsequent activity events
- CallEmbedProvider: fix m.space.parent state-key lookup by switching
getStateEvent → getStateEvents (plural); space channel voice rooms no
longer trigger the incoming-call ring/animation
- Add useUserNotes hook (io.lotus.user_notes account data, reactive via
useAccountDataCallback, 500-char limit, cross-device sync)
- UserRoomProfile: add UserPrivateNotes textarea with 800ms debounced
auto-save, saving indicator, char counter when <100 chars remain;
shown only when viewing another user's profile
- LOTUS_FEATURES.md: add Private Notes section, Status Revert fix note,
animation improvements subsection, Seasonal Themes section
- LOTUS_BUGS.md: mark presence revert + voice ringing bugs as resolved
- README.md + landing/index.html: document all new June 2026 features
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
B1 - GIF upload progress: spinner on GIF button + disabled state while
fetch+upload is in flight; clears on success or error
B2 - PiP position persistence: drag end saves left/top to localStorage;
entering PiP restores saved position (clamped to current viewport)
B3 - PiP snap-to-corner: double-click the PiP overlay snaps to nearest
corner with a 180ms CSS transition; saves new position
B4 - Device sessions loading state: useOtherUserDevices now returns
{status:'loading'|'error'|'success', devices} instead of bare
array; UserDeviceSessions shows spinner while loading
B5 - Device sessions error state: catch in hook sets status:'error';
panel shows warning icon + 'Could not load sessions' message
B6 - Screenshare fullscreen Safari guard: hide button when
document.fullscreenEnabled is false (iOS Safari, some mobile)
B7 - Status save error: show critical-coloured error text below Save
button when saveState.status === AsyncStatus.Error
B9 - Encrypted search coverage counter: 'X / Y cached' badge next to
'Encrypted Rooms' heading using existing localResult fields
D2 - PiP screenshare spotlight: track auto-spotlight in a ref; release
spotlight when screenshare ends while in PiP mode
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- MembersDrawer: show presence.status as small muted text below
username in every member row (live via useUserPresence)
- UserHero/UserHeroName: accept optional status prop; render below
the @username handle in user profile popouts
- UserRoomProfile: pass presence?.status down to UserHeroName
- Profile settings: new ProfileStatus tile below Display Name
* Input with inline emoji picker (lazy-loaded EmojiBoard)
* Cursor-aware emoji insertion (preserves caret position)
* Save via mx.setPresence({ status_msg }) / Clear button
* Pre-fills from current presence; syncs on remote update
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a collapsible "Sessions" section to the user profile card that
appears when cross-signing is active and the profile belongs to another
user. Each session shows a colour-coded shield (green = verified, yellow
= unverified) and a "Verify" button for unverified devices that
initiates the SAS emoji flow via crypto.requestDeviceVerification.
New hook useOtherUserDevices fetches the target user's device list via
crypto.getUserDeviceInfo and reacts to CryptoEvent.DevicesUpdated.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Spaces and unencrypted rooms have hasEncryptionStateEvent() = false,
causing all badges to be hidden. Cross-signing verification is a user
identity property, not room-specific — show badges whenever
crossSigningActive, keep the E2EE banner gated on isEncrypted.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extract MemberVerificationBadge into a shared component and render it in:
- UserRoomProfile: shield badge beside the display name on the profile card
- common-settings Members: badge next to each member in the room/space
settings members page (accessible from the lobby)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* WIP - support room version 12
* add room creators hook
* revert changes from powerlevels
* improve use room creators hook
* add hook to get dm users
* add options to add creators in create room/space
* add member item component in member drawer
* remove unused import
* extract member drawer header component
* get room creators as set only if room version support them
* add room permissions hook
* support room v12 creators power
* make predecessor event id optional
* add info about founders in permissions
* allow to create infinite powers to room creators
* allow everyone with permission to create infinite power
* handle additional creators in room upgrade
* add option to follow space tombstone
* WIP - new profile view
* render common rooms in user profile
* add presence component
* WIP - room user profile
* temp hide profile button
* show mutual rooms in spaces, rooms and direct messages categories
* add message button
* add option to change user powers in profile
* improve ban info and option to unban
* add share user button in user profile
* add option to block user in user profile
* improve blocked user alert body
* add moderation tool in user profile
* open profile view on left side in member drawer
* open new user profile in all places