fix: sent messages not appearing + add Lobby/Auth skeleton loaders

- Fix timelineSegments useMemo stale cache: the Perf-5 optimization used
  timeline.linkedTimelines as its only dep, but that reference never changes
  when events are added in-place; adding eventsLength as a dep makes it
  recompute on every new live event so the binary search always finds the
  new item
- Add LobbySkeleton: shimmer placeholder for space lobby (header + hero +
  room list rows) shown while the Lobby chunk lazy-loads
- Add AuthSkeleton: shimmer placeholder for auth pages (logo + server
  picker + form fields) shown while AuthLayout chunk lazy-loads
- Wire both into Router.tsx fallback props

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lotus Bot
2026-05-22 18:52:12 -04:00
parent 574f71d082
commit e76f1f0ccb
4 changed files with 185 additions and 3 deletions
+69
View File
@@ -0,0 +1,69 @@
import React, { useId } from 'react';
export function AuthSkeleton() {
const id = useId().replace(/:/g, '');
const shimmerKeyframes = `
@keyframes shimmer-${id} {
0% { background-position: -400px 0; }
100% { background-position: 400px 0; }
}
`;
const shimmer = {
background:
'linear-gradient(90deg, var(--skeleton-base) 25%, var(--skeleton-shine) 50%, var(--skeleton-base) 75%)',
backgroundSize: '800px 100%',
animation: `shimmer-${id} 1.6s ease-in-out infinite`,
borderRadius: '4px',
} as React.CSSProperties;
return (
<>
<style>{shimmerKeyframes}</style>
<div
style={
{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
minHeight: '100dvh',
padding: '16px',
'--skeleton-base': 'color-mix(in srgb, currentColor 8%, transparent)',
'--skeleton-shine': 'color-mix(in srgb, currentColor 15%, transparent)',
} as React.CSSProperties
}
>
{/* Card */}
<div
style={{
width: '100%',
maxWidth: '360px',
display: 'flex',
flexDirection: 'column',
gap: '24px',
}}
>
{/* Logo + app name */}
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '12px' }}>
<div style={{ ...shimmer, width: '64px', height: '64px', borderRadius: '50%' }} />
<div style={{ ...shimmer, width: '100px', height: '20px' }} />
</div>
{/* Server picker */}
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
<div style={{ ...shimmer, width: '80px', height: '12px' }} />
<div style={{ ...shimmer, width: '100%', height: '40px', borderRadius: '8px' }} />
</div>
{/* Form fields */}
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
<div style={{ ...shimmer, width: '100%', height: '40px', borderRadius: '8px' }} />
<div style={{ ...shimmer, width: '100%', height: '40px', borderRadius: '8px' }} />
<div style={{ ...shimmer, width: '100%', height: '40px', borderRadius: '8px' }} />
</div>
</div>
</div>
</>
);
}