@@ -98,6 +98,19 @@ import {
9898import type { URLEnrichmentConfig } from '../MessageInput/hooks/useLinkPreviews' ;
9999import { useThreadContext } from '../Threads' ;
100100import { CHANNEL_CONTAINER_ID } from './constants' ;
101+ import {
102+ DefaultSearchSources ,
103+ SearchControllerState ,
104+ SearchSource ,
105+ } from '../Search/SearchController' ;
106+ import { useStateStore } from '../../store' ;
107+
108+ const searchControllerStateSelector = <
109+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics ,
110+ Sources extends SearchSource [ ] = DefaultSearchSources < StreamChatGenerics >
111+ > (
112+ nextValue : SearchControllerState < StreamChatGenerics , Sources > ,
113+ ) => ( { jumpToMessageFromSearch : nextValue . focusedMessage } ) ;
101114
102115export type ChannelPropsForwardedToComponentContext <
103116 StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
@@ -363,6 +376,7 @@ const ChannelInner = <
363376 customClasses,
364377 latestMessageDatesByChannels,
365378 mutes,
379+ searchController,
366380 } = useChatContext < StreamChatGenerics > ( 'Channel' ) ;
367381 const { t } = useTranslationContext ( 'Channel' ) ;
368382 const chatContainerClass = getChatContainerClass ( customClasses ?. chatContainer ) ;
@@ -387,12 +401,19 @@ const ChannelInner = <
387401 } ,
388402 ) ;
389403
404+ const { jumpToMessageFromSearch } = useStateStore (
405+ searchController . state ,
406+ searchControllerStateSelector ,
407+ ) ;
408+
390409 const isMounted = useIsMounted ( ) ;
391410
392411 const originalTitle = useRef ( '' ) ;
393412 const lastRead = useRef < Date | undefined > ( ) ;
394413 const online = useRef ( true ) ;
395414
415+ const clearHighlightedMessageTimeoutId = useRef < ReturnType < typeof setTimeout > | null > ( null ) ;
416+
396417 const channelCapabilitiesArray = channel . data ?. own_capabilities as string [ ] ;
397418
398419 const throttledCopyStateFromChannel = throttle (
@@ -632,6 +653,38 @@ const ChannelInner = <
632653 if ( message ) dispatch ( { message, type : 'setThread' } ) ;
633654 } , [ state . messages , state . thread ] ) ;
634655
656+ const handleHighlightedMessageChange = useCallback (
657+ ( {
658+ highlightDuration,
659+ highlightedMessageId,
660+ } : {
661+ highlightedMessageId : string ;
662+ highlightDuration ?: number ;
663+ } ) => {
664+ dispatch ( {
665+ channel,
666+ highlightedMessageId,
667+ type : 'jumpToMessageFinished' ,
668+ } ) ;
669+ if ( clearHighlightedMessageTimeoutId . current ) {
670+ clearTimeout ( clearHighlightedMessageTimeoutId . current ) ;
671+ }
672+ clearHighlightedMessageTimeoutId . current = setTimeout ( ( ) => {
673+ if ( searchController . state . getLatestValue ( ) . focusedMessage ) {
674+ searchController . state . partialNext ( { focusedMessage : undefined } ) ;
675+ }
676+ clearHighlightedMessageTimeoutId . current = null ;
677+ dispatch ( { type : 'clearHighlightedMessage' } ) ;
678+ } , highlightDuration ?? DEFAULT_HIGHLIGHT_DURATION ) ;
679+ } ,
680+ [ channel , searchController ] ,
681+ ) ;
682+
683+ useEffect ( ( ) => {
684+ if ( ! jumpToMessageFromSearch ?. id ) return ;
685+ handleHighlightedMessageChange ( { highlightedMessageId : jumpToMessageFromSearch . id } ) ;
686+ } , [ jumpToMessageFromSearch , handleHighlightedMessageChange ] ) ;
687+
635688 /** MESSAGE */
636689
637690 // Adds a temporary notification to message list, will be removed after 5 seconds
@@ -718,8 +771,6 @@ const ChannelInner = <
718771 return queryResponse . messages . length ;
719772 } ;
720773
721- const clearHighlightedMessageTimeoutId = useRef < ReturnType < typeof setTimeout > | null > ( null ) ;
722-
723774 const jumpToMessage : ChannelActionContextValue < StreamChatGenerics > [ 'jumpToMessage' ] = useCallback (
724775 async (
725776 messageId ,
@@ -730,22 +781,9 @@ const ChannelInner = <
730781 await channel . state . loadMessageIntoState ( messageId , undefined , messageLimit ) ;
731782
732783 loadMoreFinished ( channel . state . messagePagination . hasPrev , channel . state . messages ) ;
733- dispatch ( {
734- hasMoreNewer : channel . state . messagePagination . hasNext ,
735- highlightedMessageId : messageId ,
736- type : 'jumpToMessageFinished' ,
737- } ) ;
738-
739- if ( clearHighlightedMessageTimeoutId . current ) {
740- clearTimeout ( clearHighlightedMessageTimeoutId . current ) ;
741- }
742-
743- clearHighlightedMessageTimeoutId . current = setTimeout ( ( ) => {
744- clearHighlightedMessageTimeoutId . current = null ;
745- dispatch ( { type : 'clearHighlightedMessage' } ) ;
746- } , highlightDuration ) ;
784+ handleHighlightedMessageChange ( { highlightDuration, highlightedMessageId : messageId } ) ;
747785 } ,
748- [ channel , loadMoreFinished ] ,
786+ [ channel , handleHighlightedMessageChange , loadMoreFinished ] ,
749787 ) ;
750788
751789 const jumpToLatestMessage : ChannelActionContextValue < StreamChatGenerics > [ 'jumpToLatestMessage' ] = useCallback ( async ( ) => {
@@ -864,23 +902,19 @@ const ChannelInner = <
864902 first_unread_message_id : firstUnreadMessageId ,
865903 last_read_message_id : lastReadMessageId ,
866904 } ) ;
867-
868- dispatch ( {
869- hasMoreNewer : channel . state . messagePagination . hasNext ,
905+ handleHighlightedMessageChange ( {
906+ highlightDuration,
870907 highlightedMessageId : firstUnreadMessageId ,
871- type : 'jumpToMessageFinished' ,
872908 } ) ;
873-
874- if ( clearHighlightedMessageTimeoutId . current ) {
875- clearTimeout ( clearHighlightedMessageTimeoutId . current ) ;
876- }
877-
878- clearHighlightedMessageTimeoutId . current = setTimeout ( ( ) => {
879- clearHighlightedMessageTimeoutId . current = null ;
880- dispatch ( { type : 'clearHighlightedMessage' } ) ;
881- } , highlightDuration ) ;
882909 } ,
883- [ addNotification , channel , loadMoreFinished , t , channelUnreadUiState ] ,
910+ [
911+ addNotification ,
912+ channel ,
913+ handleHighlightedMessageChange ,
914+ loadMoreFinished ,
915+ t ,
916+ channelUnreadUiState ,
917+ ] ,
884918 ) ;
885919
886920 const deleteMessage = useCallback (
0 commit comments