fix: resilience, speaker animation, CSS variable fixes
CI / Build & Quality Checks (push) Successful in 10m39s
CI / Trigger Desktop Build (push) Successful in 6s

- 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>
This commit is contained in:
2026-06-18 19:19:54 -04:00
parent abf15391f6
commit e2b957b6bd
3 changed files with 65 additions and 19 deletions
@@ -1,4 +1,4 @@
import { Box, Button, config, Icon, IconButton, Icons, Spinner, Text, toRem } from 'folds';
import { Box, Button, color, config, Icon, IconButton, Icons, Spinner, Text, toRem } from 'folds';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { VerificationRequest } from 'matrix-js-sdk/lib/crypto-api';
@@ -197,7 +197,7 @@ function UserDeviceSessions({ userId }: UserDeviceSessionsProps) {
style={{
paddingTop: config.space.S100,
paddingBottom: config.space.S100,
borderTop: `${toRem(1)} solid var(--border-surface-variant)`,
borderTop: `${toRem(1)} solid ${color.SurfaceVariant.ContainerLine}`,
}}
>
<UserDeviceRow userId={userId} device={device} />
+16 -3
View File
@@ -1,4 +1,4 @@
import { style } from '@vanilla-extract/css';
import { keyframes, style } from '@vanilla-extract/css';
import { color, config, toRem } from 'folds';
export const LiveChipText = style({
@@ -16,6 +16,19 @@ export const ControlDivider = style({
height: toRem(16),
});
export const SpeakerAvatarOutline = style({
boxShadow: `0 0 0 ${config.borderWidth.B600} ${color.Success.Main}`,
const speakerPulse = keyframes({
'0%': { boxShadow: `0 0 0 ${config.borderWidth.B600} ${color.Success.Main}` },
'50%': { boxShadow: `0 0 0 ${toRem(4)} ${color.Success.ContainerActive}` },
'100%': { boxShadow: `0 0 0 ${config.borderWidth.B600} ${color.Success.Main}` },
});
export const SpeakerAvatarOutline = style({
'@media': {
'(prefers-reduced-motion: no-preference)': {
animation: `${speakerPulse} 1200ms ease-in-out infinite`,
},
'(prefers-reduced-motion: reduce)': {
boxShadow: `0 0 0 ${config.borderWidth.B600} ${color.Success.Main}`,
},
},
});
+47 -14
View File
@@ -1,4 +1,5 @@
import React, { useCallback, useMemo, useRef } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { Box, Text, config } from 'folds';
import { EventType } from 'matrix-js-sdk';
import { ReactEditor } from 'slate-react';
@@ -109,13 +110,31 @@ export function RoomView({ eventId }: { eventId?: string }) {
return (
<Page ref={roomViewRef} style={chatBgStyle}>
<Box grow="Yes" direction="Column">
<RoomTimeline
key={roomId}
room={room}
eventId={eventId}
roomInputRef={roomInputRef}
editor={editor}
/>
<ErrorBoundary
fallback={
<Box
grow="Yes"
direction="Column"
alignItems="Center"
justifyContent="Center"
gap="400"
style={{ padding: config.space.S400, opacity: 0.7 }}
>
<Text size="H4">Timeline unavailable</Text>
<Text size="T300" align="Center">
An error occurred while rendering messages. Try refreshing the page.
</Text>
</Box>
}
>
<RoomTimeline
key={roomId}
room={room}
eventId={eventId}
roomInputRef={roomInputRef}
editor={editor}
/>
</ErrorBoundary>
<RoomViewTyping room={room} />
</Box>
<Box shrink="No" direction="Column">
@@ -129,13 +148,27 @@ export function RoomView({ eventId }: { eventId?: string }) {
) : (
<>
{canMessage && (
<RoomInput
room={room}
editor={editor}
roomId={roomId}
fileDropContainerRef={roomViewRef}
ref={roomInputRef}
/>
<ErrorBoundary
fallback={
<RoomInputPlaceholder
style={{ padding: config.space.S200 }}
alignItems="Center"
justifyContent="Center"
>
<Text align="Center">
Message composer encountered an error. Try refreshing.
</Text>
</RoomInputPlaceholder>
}
>
<RoomInput
room={room}
editor={editor}
roomId={roomId}
fileDropContainerRef={roomViewRef}
ref={roomInputRef}
/>
</ErrorBoundary>
)}
{!canMessage && (
<RoomInputPlaceholder