Skip to content

Commit 6ced10f

Browse files
wip: compositionContext
1 parent 58854a4 commit 6ced10f

File tree

1 file changed

+42
-71
lines changed

1 file changed

+42
-71
lines changed

src/components/MessageInput/hooks/messageComposer/useMessageComposer.ts

Lines changed: 42 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,33 @@
11
import { useEffect, useMemo, useRef, useState } from 'react';
2-
import { MessageComposer } from 'stream-chat';
2+
import { FixedSizeQueueCache, MessageComposer } from 'stream-chat';
33
import { useThreadContext } from '../../../Threads';
4-
import { useChannelStateContext, useMessageInputContext } from '../../../../context';
4+
import { useChatContext, useMessageInputContext } from '../../../../context';
55
import type { LocalMessage } from 'stream-chat';
66
import { useLegacyThreadContext } from '../../../Thread';
77

8-
class FixedSizeQueueCache<K, T> {
9-
private keys: Array<K>;
10-
private size: number;
11-
private valueByKey: Map<K, T>;
12-
constructor(size: number) {
13-
if (!size) throw new Error('Size must be greater than 0');
14-
this.keys = [];
15-
this.size = size;
16-
this.valueByKey = new Map();
17-
}
18-
19-
add(key: K, value: T) {
20-
const index = this.keys.indexOf(key);
21-
22-
if (index > -1) {
23-
this.keys.splice(this.keys.indexOf(key), 1);
24-
} else if (this.keys.length >= this.size) {
25-
const elementKey = this.keys.shift();
26-
27-
if (elementKey) {
28-
this.valueByKey.delete(elementKey);
29-
}
30-
}
31-
32-
this.keys.push(key);
33-
this.valueByKey.set(key, value);
34-
}
35-
36-
peek(key: K) {
37-
const value = this.valueByKey.get(key);
38-
39-
return value;
40-
}
41-
42-
get(key: K) {
43-
const foundElement = this.peek(key);
44-
45-
if (foundElement && this.keys.indexOf(key) !== this.size - 1) {
46-
this.keys.splice(this.keys.indexOf(key), 1);
47-
this.keys.push(key);
48-
}
49-
50-
return foundElement;
51-
}
52-
}
53-
548
export type UseMessageComposerParams = unknown;
559

5610
const queueCache = new FixedSizeQueueCache<string, MessageComposer>(64);
5711

58-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
59-
export const useMessageComposer = (_unused: UseMessageComposerParams = {}) => {
60-
const { channel } = useChannelStateContext();
12+
export const useMessageComposer = () => {
13+
const { channel, client } = useChatContext();
6114
const { message: editedMessage } = useMessageInputContext();
6215
// legacy thread will receive new composer
6316
const { legacyThread: parentMessage, messageDraft } = useLegacyThreadContext();
6417
const threadInstance = useThreadContext();
6518
const detachedMessageComposerRef = useRef<MessageComposer>(
66-
new MessageComposer({ channel, tag: 'detached' }),
19+
new MessageComposer({
20+
client,
21+
compositionContext: {
22+
created_at: new Date(),
23+
deleted_at: null,
24+
id: 'detached',
25+
pinned_at: null,
26+
status: '',
27+
type: 'regular',
28+
updated_at: new Date(),
29+
},
30+
}),
6731
);
6832

6933
const [cachedEditedMessage, setCachedEditedMessage] = useState<
@@ -86,34 +50,35 @@ export const useMessageComposer = (_unused: UseMessageComposerParams = {}) => {
8650
// editedMessage ?? thread ?? parentMessage ?? channel;
8751
const messageComposer = useMemo(() => {
8852
if (cachedEditedMessage) {
89-
const tag = `edited-message-${cachedEditedMessage.id}`;
53+
const tag = MessageComposer.constructTag(cachedEditedMessage);
9054

91-
const element = queueCache.get(tag);
92-
if (element) return element;
55+
const cachedComposer = queueCache.get(tag);
56+
if (cachedComposer) return cachedComposer;
9357

94-
const c = new MessageComposer({
95-
channel,
58+
return new MessageComposer({
59+
client,
9660
composition: cachedEditedMessage,
97-
tag,
61+
compositionContext: cachedEditedMessage,
9862
});
99-
100-
return c;
10163
} else if (threadInstance) {
10264
return threadInstance.messageComposer;
10365
} else if (cachedParentMessage) {
104-
const tag = `parent-message-${cachedParentMessage.id}`;
66+
const compositionContext = {
67+
...cachedParentMessage,
68+
legacyThreadId: cachedParentMessage.id,
69+
};
10570

106-
const element = queueCache.get(tag);
107-
if (element) return element;
71+
const tag = MessageComposer.constructTag(compositionContext);
10872

109-
const c = new MessageComposer({
110-
channel,
73+
const cachedComposer = queueCache.get(tag);
74+
if (cachedComposer) return cachedComposer;
75+
76+
// FIXME: draft won't be applied on second render
77+
return new MessageComposer({
78+
client,
11179
composition: messageDraft,
112-
tag,
113-
threadId: cachedParentMessage.id,
80+
compositionContext,
11481
});
115-
116-
return c;
11782
} else if (channel) {
11883
return channel.messageComposer;
11984
} else {
@@ -124,11 +89,17 @@ export const useMessageComposer = (_unused: UseMessageComposerParams = {}) => {
12489
cachedEditedMessage,
12590
cachedParentMessage,
12691
channel,
127-
messageDraft, // TODO: set message draft after the fact
92+
client,
93+
messageDraft,
12894
threadInstance,
12995
]);
13096

131-
if (!queueCache.peek(messageComposer.tag)) {
97+
if (
98+
(['legacy_thread', 'message'] as MessageComposer['contextType'][]).includes(
99+
messageComposer.contextType,
100+
) &&
101+
!queueCache.peek(messageComposer.tag)
102+
) {
132103
queueCache.add(messageComposer.tag, messageComposer);
133104
}
134105

0 commit comments

Comments
 (0)