@@ -74,6 +74,8 @@ export function useGetMessagesProvider() {
7474 const loadingNewMessages = ref ( false )
7575 const isInitialisingMessages = ref ( true )
7676 const stopFetchingOldMessages = ref ( false )
77+ let chatRelayEnabled = false
78+ let chatRelaySupported = false
7779
7880 /**
7981 * Returns whether the current participant is a participant of current conversation.
@@ -144,6 +146,7 @@ export function useGetMessagesProvider() {
144146 }
145147 if ( oldToken && oldToken !== newToken ) {
146148 store . dispatch ( 'cancelPollNewMessages' , { requestId : oldToken } )
149+ stopChatRelay ( )
147150 }
148151
149152 if ( newToken && canGetMessages ) {
@@ -162,6 +165,7 @@ export function useGetMessagesProvider() {
162165 subscribe ( 'networkOnline' , handleNetworkOnline )
163166 EventBus . on ( 'route-change' , onRouteChange )
164167 EventBus . on ( 'set-context-id-to-bottom' , setContextIdToBottom )
168+ EventBus . on ( 'signaling-supported-features' , checkChatRelaySupport )
165169
166170 /** Every 30 seconds we remove expired messages from the store */
167171 expirationInterval = setInterval ( ( ) => {
@@ -173,6 +177,8 @@ export function useGetMessagesProvider() {
173177 unsubscribe ( 'networkOnline' , handleNetworkOnline )
174178 EventBus . off ( 'route-change' , onRouteChange )
175179 EventBus . off ( 'set-context-id-to-bottom' , setContextIdToBottom )
180+ EventBus . off ( 'chat-relay-message-received' , addMessageFromChatRelay )
181+ EventBus . off ( 'signaling-supported-features' , checkChatRelaySupport )
176182
177183 store . dispatch ( 'cancelPollNewMessages' , { requestId : currentToken . value } )
178184 clearInterval ( pollingTimeout )
@@ -482,6 +488,10 @@ export function useGetMessagesProvider() {
482488 * @param token token of conversation where a method was called
483489 */
484490 async function pollNewMessages ( token : string ) {
491+ if ( chatRelayEnabled ) {
492+ // Stop polling if chat relay is supported
493+ return
494+ }
485495 // Check that the token has not changed
486496 if ( currentToken . value !== token ) {
487497 console . debug ( `token has changed to ${ currentToken . value } , breaking the loop for ${ token } ` )
@@ -499,6 +509,7 @@ export function useGetMessagesProvider() {
499509 requestId : token ,
500510 } )
501511 debugTimer . end ( `${ token } | long polling` , 'status 200' )
512+ tryChatRelay ( )
502513 } catch ( exception ) {
503514 if ( Axios . isCancel ( exception ) ) {
504515 debugTimer . end ( `${ token } | long polling` , 'cancelled' )
@@ -512,6 +523,7 @@ export function useGetMessagesProvider() {
512523 // This is not an error, so reset error timeout and poll again
513524 pollingErrorTimeout = 1_000
514525 clearTimeout ( pollingTimeout )
526+ tryChatRelay ( )
515527 pollingTimeout = setTimeout ( ( ) => {
516528 pollNewMessages ( token )
517529 } , 500 )
@@ -539,6 +551,66 @@ export function useGetMessagesProvider() {
539551 } , 500 )
540552 }
541553
554+ /**
555+ * Try to start chat relay
556+ */
557+ function tryChatRelay ( ) {
558+ if ( chatRelaySupported && isChatEndReached . value ) {
559+ startChatRelay ( )
560+ }
561+ }
562+
563+ /**
564+ * Check whether chat relay is supported
565+ *
566+ * @param features
567+ */
568+ function checkChatRelaySupport ( features : string [ ] ) {
569+ if ( features . includes ( 'chat-relay' ) ) {
570+ chatRelaySupported = true
571+ }
572+ }
573+
574+ /**
575+ * Initialize chat relay support by stopping polling and listening to chat relay messages
576+ */
577+ function startChatRelay ( ) {
578+ if ( currentToken . value ) {
579+ // it might have been set already, ensure we cancel it
580+ store . dispatch ( 'cancelPollNewMessages' , { requestId : currentToken . value } )
581+ }
582+ chatRelayEnabled = true
583+ EventBus . on ( 'chat-relay-message-received' , addMessageFromChatRelay )
584+ }
585+
586+ /**
587+ *
588+ * Chat relay sends one message at a time, we update our stores directly
589+ *
590+ * @param payload
591+ * @param payload.token
592+ * @param payload.message
593+ */
594+ function addMessageFromChatRelay ( payload : { token : string , message : ChatMessage } ) {
595+ const { token, message } = payload
596+ if ( token !== currentToken . value ) {
597+ // Guard: Message is for another conversation
598+ // e.g., user switched conversation while messages were in-flight
599+ return
600+ }
601+
602+ chatStore . processChatBlocks ( token , [ message ] , { mergeBy : conversationLastMessageId . value } )
603+ store . dispatch ( 'processMessage' , { token, message } )
604+ }
605+
606+ /**
607+ * Stop chat relay and remove listener
608+ */
609+ function stopChatRelay ( ) {
610+ chatRelayEnabled = false
611+ EventBus . off ( 'chat-relay-message-received' , addMessageFromChatRelay )
612+ }
613+
542614 provide ( GET_MESSAGES_CONTEXT_KEY , {
543615 contextMessageId,
544616 loadingOldMessages,
0 commit comments