Skip to content

Commit c7c1e73

Browse files
authored
chore: add loading screen to the demo app (#3058)
1 parent 9b22555 commit c7c1e73

2 files changed

Lines changed: 112 additions & 1 deletion

File tree

examples/vite/src/App.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
getSelectedChannelIdFromUrl,
4848
getSelectedChatViewFromUrl,
4949
} from './ChatLayout/Sync.tsx';
50+
import { LoadingScreen } from './LoadingScreen/LoadingScreen.tsx';
5051
import { chatViewSelectorItemSet } from './Sidebar/ChatViewSelectorItemSet.tsx';
5152
import {
5253
CustomAttachmentActions,
@@ -182,6 +183,10 @@ const App = () => {
182183
const { mode: themeMode } = useAppSettingsSelector((state) => state.theme);
183184
const initialChannelId = useMemo(() => getSelectedChannelIdFromUrl(), []);
184185
const initialChatView = useMemo(() => getSelectedChatViewFromUrl(), []);
186+
const initialThreadOpen = useMemo(
187+
() => Boolean(new URLSearchParams(window.location.search).get('thread')),
188+
[],
189+
);
185190
const initialPanelLayout = useMemo(
186191
() => appSettingsStore.getLatestValue().panelLayout,
187192
[],
@@ -289,7 +294,15 @@ const App = () => {
289294
[initialPanelLayout.leftPanel.width, initialPanelLayout.threadPanel.width],
290295
);
291296

292-
if (!chatClient) return <>Loading...</>;
297+
if (!chatClient) {
298+
return (
299+
<LoadingScreen
300+
initialAppLayoutStyle={initialAppLayoutStyle}
301+
initialNavOpen={initialNavOpen}
302+
initialThreadOpen={initialThreadOpen}
303+
/>
304+
);
305+
}
293306

294307
const messageUiOverrides: Record<string, unknown> = {};
295308
if (MessageUiOverride) {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import clsx from 'clsx';
2+
import { type CSSProperties } from 'react';
3+
import { LoadingChannel, LoadingChannels } from 'stream-chat-react';
4+
5+
// This component renders before the chat client is created. ChatView depends on ChatContext
6+
// provided by <Chat>, so using ChatView here would run outside its provider and produce
7+
// incomplete behavior/warnings. We intentionally mirror ChatView structure/classes to keep
8+
// loading dimensions aligned with the final loaded layout.
9+
// Update this layout every time layout in App.tsx is updated.
10+
type LoadingScreenProps = {
11+
initialAppLayoutStyle: CSSProperties;
12+
initialNavOpen: boolean;
13+
initialThreadOpen: boolean;
14+
};
15+
16+
const selectorButtonCount = 4;
17+
18+
export const LoadingScreen = ({
19+
initialAppLayoutStyle,
20+
initialNavOpen,
21+
initialThreadOpen,
22+
}: LoadingScreenProps) => (
23+
<div className='app-chat-layout' style={initialAppLayoutStyle}>
24+
<div className='str-chat'>
25+
<div className='str-chat__chat-view'>
26+
<div
27+
className={clsx('str-chat__chat-view__selector', {
28+
'str-chat__chat-view__selector--nav-closed': !initialNavOpen,
29+
'str-chat__chat-view__selector--nav-open': initialNavOpen,
30+
})}
31+
>
32+
{Array.from({ length: selectorButtonCount }).map((_, index) => (
33+
<div className='str-chat__chat-view__selector-button-container' key={index}>
34+
<div className='str-chat__chat-view__selector-button'>
35+
<span className='str-chat__loading-channels-avatar' />
36+
</div>
37+
</div>
38+
))}
39+
</div>
40+
<div className='str-chat__chat-view__channels'>
41+
<div
42+
className={clsx('app-chat-view__channels-layout', {
43+
'app-chat-view__channels-layout--sidebar-collapsed': !initialNavOpen,
44+
})}
45+
>
46+
<div className='str-chat__channel-list'>
47+
<LoadingChannels />
48+
</div>
49+
<div
50+
aria-orientation='vertical'
51+
className='app-chat-resize-handle'
52+
role='separator'
53+
>
54+
<div className='app-chat-resize-handle__hitbox'>
55+
<div className='app-chat-resize-handle__line' />
56+
</div>
57+
</div>
58+
<div className='str-chat__channel'>
59+
<div className='str-chat__container'>
60+
<div className='str-chat__main-panel'>
61+
<div className='str-chat__main-panel-inner'>
62+
<div className='str-chat__window'>
63+
<LoadingChannel />
64+
</div>
65+
</div>
66+
</div>
67+
<div
68+
aria-orientation='vertical'
69+
className={clsx(
70+
'app-chat-resize-handle app-chat-resize-handle--thread',
71+
{
72+
'app-chat-resize-handle--thread-hidden': !initialThreadOpen,
73+
},
74+
)}
75+
role='separator'
76+
>
77+
<div className='app-chat-resize-handle__hitbox'>
78+
<div className='app-chat-resize-handle__line' />
79+
</div>
80+
</div>
81+
<div
82+
className={clsx(
83+
'str-chat__dropzone-root--thread app-chat-thread-panel',
84+
{
85+
'app-chat-thread-panel--open': initialThreadOpen,
86+
},
87+
)}
88+
>
89+
<LoadingChannel />
90+
</div>
91+
</div>
92+
</div>
93+
</div>
94+
</div>
95+
</div>
96+
</div>
97+
</div>
98+
);

0 commit comments

Comments
 (0)