Skip to content

Commit c979e04

Browse files
Cleanup, fixes and adjustments
1 parent f97451e commit c979e04

File tree

7 files changed

+62
-58
lines changed

7 files changed

+62
-58
lines changed

examples/vite/src/App.tsx

-18
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,4 @@ const Threads = () => {
9292
);
9393
};
9494

95-
/* {activeThread && (
96-
<ThreadProvider thread={activeThread}>
97-
<ThreadHeader />
98-
<MessageList />
99-
<MessageInput />
100-
</ThreadProvider>
101-
)} */
102-
103-
// const Wrapper = () => {
104-
// const { activeThread } = useThreadContext();
105-
106-
// console.log({ activeThread });
107-
108-
// if (!activeThread) return;
109-
110-
// return <VirtualizedMessageList />;
111-
// };
112-
11395
export default App;

examples/vite/src/index.scss

+19-12
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ body,
1616
display: flex;
1717
height: 100%;
1818

19-
.str-chat__thread-list {
20-
width: 50%;
21-
height: 100%;
22-
}
19+
// .str-chat__thread-list {
20+
// width: 50%;
21+
// height: 100%;
22+
// }
2323

2424
.str-chat__thread-list-item {
2525
all: unset;
@@ -99,7 +99,7 @@ body,
9999
.str-chat__thread {
100100
width: 100%;
101101
height: 100%;
102-
position: fixed;
102+
position: absolute;
103103
z-index: 1;
104104
}
105105

@@ -122,6 +122,18 @@ body,
122122
}
123123
}
124124

125+
.str-chat.threads {
126+
display: flex;
127+
height: 100%;
128+
width: 100%;
129+
130+
.vml {
131+
display: flex;
132+
flex-direction: column;
133+
width: 70%;
134+
}
135+
}
136+
125137
@media screen and (min-width: 768px) {
126138
//.str-chat-channel-list.thread-open {
127139
// &.menu-open {
@@ -146,11 +158,6 @@ body,
146158
position: initial;
147159
z-index: 0;
148160
}
149-
150-
.str-chat__thread {
151-
position: initial;
152-
z-index: 0;
153-
}
154161
}
155162

156163
@media screen and (min-width: 1024px) {
@@ -162,8 +169,8 @@ body,
162169

163170
.str-chat__thread {
164171
width: 45%;
165-
//position: initial;
166-
//z-index: 0;
172+
position: initial;
173+
z-index: 0;
167174
}
168175

169176
.str-chat__channel-header .str-chat__header-hamburger {

src/components/Channel/Channel.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import type { URLEnrichmentConfig } from '../MessageInput/hooks/useLinkPreviews'
9898
import { defaultReactionOptions, ReactionOptions } from '../Reactions';
9999
import { EventComponent } from '../EventComponent';
100100
import { DateSeparator } from '../DateSeparator';
101+
import { useThreadContext } from '../Threads';
101102

102103
type ChannelPropsForwardedToComponentContext<
103104
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
@@ -401,6 +402,8 @@ const ChannelInner = <
401402
windowsEmojiClass,
402403
} = useChannelContainerClasses({ customClasses });
403404

405+
const thread = useThreadContext();
406+
404407
const [channelConfig, setChannelConfig] = useState(channel.getConfig());
405408
const [notifications, setNotifications] = useState<ChannelNotifications>([]);
406409
const [quotedMessage, setQuotedMessage] = useState<StreamMessage<StreamChatGenerics>>();
@@ -1057,20 +1060,22 @@ const ChannelInner = <
10571060
channel.state.filterErrorMessages();
10581061

10591062
const messagePreview = {
1060-
__html: text,
10611063
attachments,
10621064
created_at: new Date(),
10631065
html: text,
10641066
id: customMessageData?.id ?? `${client.userID}-${nanoid()}`,
10651067
mentioned_users,
1068+
parent_id: parent?.id,
10661069
reactions: [],
10671070
status: 'sending',
10681071
text,
10691072
type: 'regular',
10701073
user: client.user,
1071-
...(parent?.id ? { parent_id: parent.id } : null),
10721074
};
10731075

1076+
// @ts-expect-error
1077+
if (thread.channel) thread.upsertReply({ message: messagePreview });
1078+
10741079
updateMessage(messagePreview);
10751080

10761081
await doSendMessage(messagePreview, customMessageData, options);

src/components/Message/hooks/useReactionHandler.ts

+6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import type { Reaction, ReactionResponse } from 'stream-chat';
1111

1212
import type { DefaultStreamChatGenerics } from '../../../types/types';
1313

14+
import { useThreadContext } from '../../Threads';
15+
1416
export const reactionHandlerWarning = `Reaction handler was called, but it is missing one of its required arguments.
1517
Make sure the ChannelAction and ChannelState contexts are properly set and the hook is initialized with a valid message.`;
1618

@@ -19,6 +21,7 @@ export const useReactionHandler = <
1921
>(
2022
message?: StreamMessage<StreamChatGenerics>,
2123
) => {
24+
const thread = useThreadContext();
2225
const { updateMessage } = useChannelActionContext<StreamChatGenerics>('useReactionHandler');
2326
const { channel, channelCapabilities } = useChannelStateContext<StreamChatGenerics>(
2427
'useReactionHandler',
@@ -93,15 +96,18 @@ export const useReactionHandler = <
9396

9497
try {
9598
updateMessage(tempMessage);
99+
if (thread.channel) thread.upsertReply({ message: tempMessage });
96100

97101
const messageResponse = add
98102
? await channel.sendReaction(id, { type } as Reaction<StreamChatGenerics>)
99103
: await channel.deleteReaction(id, type);
100104

105+
// seems useless as we're expecting WS event to come in and replace this anyway
101106
updateMessage(messageResponse.message);
102107
} catch (error) {
103108
// revert to the original message if the API call fails
104109
updateMessage(message);
110+
if (thread.channel) thread.upsertReply({ message });
105111
}
106112
}, 1000);
107113

src/components/Thread/Thread.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ const ThreadInner = <
110110
thread,
111111
threadHasMore,
112112
threadLoadingMore,
113-
threadMessages,
113+
threadMessages = [],
114114
threadSuppressAutoscroll,
115115
} = useChannelStateContext<StreamChatGenerics>('Thread');
116116
const { closeThread, loadMoreThread } = useChannelActionContext<StreamChatGenerics>('Thread');
@@ -172,7 +172,7 @@ const ThreadInner = <
172172
loadMore={parentMessage ? threadInstance.loadPreviousPage : loadMoreThread}
173173
Message={MessageUIComponent}
174174
messageActions={messageActions}
175-
messages={threadInstance.channel ? latestReplies : threadMessages ?? []}
175+
messages={parentMessage ? latestReplies : threadMessages}
176176
suppressAutoscroll={threadSuppressAutoscroll}
177177
threadList
178178
{...(virtualized ? additionalVirtualizedMessageListProps : additionalMessageListProps)}

src/components/Threads/ThreadContext.tsx

+12-13
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import React, { createContext, useContext } from 'react';
1+
import React, { createContext, useContext, useMemo } from 'react';
22

33
import { Channel } from '../../components';
44

55
import type { PropsWithChildren } from 'react';
66
import { Thread } from 'stream-chat';
77
import { useChatContext } from '../../context';
88

9+
/**
10+
* TODO:
11+
* - make it easier for current state of the SDK to use thread methods (meaning thread should be fully initialized and checks like `thread.channel && ...` shouldn't exist (these checks are due to a "placeholder" which is used anytime components are utilised under normal circumstances - not under ThreadContext)
12+
*/
13+
914
export type ThreadContextValue = Thread | undefined;
1015

1116
export const ThreadContext = createContext<ThreadContextValue>(undefined);
@@ -14,7 +19,12 @@ export const useThreadContext = () => {
1419
const { client } = useChatContext();
1520
const thread = useContext(ThreadContext);
1621

17-
if (!thread) return new Thread({ client, registerEventHandlers: false, threadData: {} });
22+
const placeholder = useMemo(
23+
() => new Thread({ client, registerEventHandlers: false, threadData: {} }),
24+
[client],
25+
);
26+
27+
if (!thread) return placeholder;
1828

1929
return thread;
2030
};
@@ -25,17 +35,6 @@ export const ThreadProvider = ({ children, thread }: PropsWithChildren<{ thread?
2535
</ThreadContext.Provider>
2636
);
2737

28-
// export const ThreadFacilitator = ({
29-
// children,
30-
// thread,
31-
// }: PropsWithChildren<{
32-
// thread: Thread;
33-
// }>) => {
34-
// <ThreadProvider thread={thread}>
35-
// <Channel channel={thread.channel}>{children}</Channel>;
36-
// </ThreadProvider>;
37-
// };
38-
3938
/**
4039
*
4140
* client {

src/components/Threads/ThreadList/ThreadList.tsx

+16-11
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,38 @@
11
import React, { useEffect } from 'react';
22
import { ComputeItemKey, Virtuoso } from 'react-virtuoso';
3-
import { StreamChat } from 'stream-chat';
43

54
import type { ComponentType, PointerEvent } from 'react';
6-
import type { InferStoreValueType, Thread } from 'stream-chat';
5+
import type { InferStoreValueType, Thread, ThreadManager } from 'stream-chat';
76

87
import { ThreadListItem } from './ThreadListItem';
98
import { useChatContext } from '../../../context';
109
import { useSimpleStateStore } from '../hooks/useSimpleStateStore';
1110

1211
import type { ThreadListItemProps } from './ThreadListItem';
1312

14-
const selector = (v: InferStoreValueType<StreamChat['threads']>) => [v.threads] as const;
13+
/**
14+
* TODO:
15+
* - add virtuosoProps override \w support for supplying custom threads array (typed virtuoso props, Thread[] only)
16+
* - register event handlers of each of the threads (ThreadManager - threads.<de/register>EventHandlers(), maybe simplify API)
17+
* - add Header with re-query button + logic to ThreadManager
18+
* - add Footer with "Loading"
19+
* - move str-chat someplace else, think of a different name (str-chat__thread-list already used)
20+
* - move itemContent to a component instead
21+
*
22+
* NICE TO HAVE:
23+
* - probably good idea to move component context up to a Chat component
24+
*/
25+
26+
const selector = (nextValue: InferStoreValueType<ThreadManager>) => [nextValue.threads] as const;
1527

1628
const computeItemKey: ComputeItemKey<Thread, unknown> = (_, item) => item.id;
1729

1830
type ThreadListProps = {
1931
onItemPointerDown?: (event: PointerEvent<HTMLButtonElement>, thread: Thread) => void;
2032
ThreadListItem?: ComponentType<ThreadListItemProps>;
21-
// TODO: should support supplying custom threads array
2233
// threads?: Thread[]
2334
};
2435

25-
// TODO: probably good idea to move component context up to a Chat component
26-
2736
export const ThreadList = ({
2837
ThreadListItem: PropsThreadListItem = ThreadListItem,
2938
onItemPointerDown,
@@ -37,11 +46,7 @@ export const ThreadList = ({
3746

3847
return (
3948
<Virtuoso
40-
atBottomStateChange={(atBottom) =>
41-
// TODO: figure out - handle next page load blocking client-side or here?
42-
atBottom && client.threads.loadNextPage()
43-
}
44-
// TODO: str-chat class name does not belong here, str-chat__thread-list is already used (FUCK ME SIDEWAYS)
49+
atBottomStateChange={(atBottom) => atBottom && client.threads.loadNextPage()}
4550
className='str-chat str-chat__thread-list'
4651
computeItemKey={computeItemKey}
4752
data={threads}

0 commit comments

Comments
 (0)