11import { useEffect , useMemo , useRef , useState } from 'react' ;
2- import { MessageComposer } from 'stream-chat' ;
2+ import { FixedSizeQueueCache , MessageComposer } from 'stream-chat' ;
33import { useThreadContext } from '../../../Threads' ;
4- import { useChannelStateContext , useMessageInputContext } from '../../../../context' ;
4+ import { useChatContext , useMessageInputContext } from '../../../../context' ;
55import type { LocalMessage } from 'stream-chat' ;
66import { 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-
548export type UseMessageComposerParams = unknown ;
559
5610const 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