Skip to content

Commit 386105c

Browse files
Cleanup, fixes and adjustments
1 parent 959e9fb commit 386105c

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
@@ -96,22 +96,4 @@ const Threads = () => {
9696
);
9797
};
9898

99-
/* {activeThread && (
100-
<ThreadProvider thread={activeThread}>
101-
<ThreadHeader />
102-
<MessageList />
103-
<MessageInput />
104-
</ThreadProvider>
105-
)} */
106-
107-
// const Wrapper = () => {
108-
// const { activeThread } = useThreadContext();
109-
110-
// console.log({ activeThread });
111-
112-
// if (!activeThread) return;
113-
114-
// return <VirtualizedMessageList />;
115-
// };
116-
11799
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
@@ -399,6 +400,8 @@ const ChannelInner = <
399400
windowsEmojiClass,
400401
} = useChannelContainerClasses({ customClasses });
401402

403+
const thread = useThreadContext();
404+
402405
const [channelConfig, setChannelConfig] = useState(channel.getConfig());
403406
const [notifications, setNotifications] = useState<ChannelNotifications>([]);
404407
const [quotedMessage, setQuotedMessage] = useState<StreamMessage<StreamChatGenerics>>();
@@ -1055,20 +1058,22 @@ const ChannelInner = <
10551058
channel.state.filterErrorMessages();
10561059

10571060
const messagePreview = {
1058-
__html: text,
10591061
attachments,
10601062
created_at: new Date(),
10611063
html: text,
10621064
id: customMessageData?.id ?? `${client.userID}-${nanoid()}`,
10631065
mentioned_users,
1066+
parent_id: parent?.id,
10641067
reactions: [],
10651068
status: 'sending',
10661069
text,
10671070
type: 'regular',
10681071
user: client.user,
1069-
...(parent?.id ? { parent_id: parent.id } : null),
10701072
};
10711073

1074+
// @ts-expect-error
1075+
if (thread.channel) thread.upsertReply({ message: messagePreview });
1076+
10721077
updateMessage(messagePreview);
10731078

10741079
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
@@ -105,7 +105,7 @@ const ThreadInner = <
105105
thread,
106106
threadHasMore,
107107
threadLoadingMore,
108-
threadMessages,
108+
threadMessages = [],
109109
threadSuppressAutoscroll,
110110
} = useChannelStateContext<StreamChatGenerics>('Thread');
111111
const { closeThread, loadMoreThread } = useChannelActionContext<StreamChatGenerics>('Thread');
@@ -164,7 +164,7 @@ const ThreadInner = <
164164
loadMore={parentMessage ? threadInstance.loadPreviousPage : loadMoreThread}
165165
Message={MessageUIComponent}
166166
messageActions={messageActions}
167-
messages={threadInstance.channel ? latestReplies : threadMessages ?? []}
167+
messages={parentMessage ? latestReplies : threadMessages}
168168
suppressAutoscroll={threadSuppressAutoscroll}
169169
threadList
170170
{...(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)