fix: resilience, speaker animation, CSS variable fixes
- 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:
@@ -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} />
|
||||
|
||||
@@ -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}`,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user