@@ -70,7 +70,7 @@ import {
70
70
import type { UnreadMessagesNotificationProps } from '../MessageList' ;
71
71
import { hasMoreMessagesProbably , UnreadMessagesSeparator } from '../MessageList' ;
72
72
import { useChannelContainerClasses } from './hooks/useChannelContainerClasses' ;
73
- import { makeAddNotifications } from './utils' ;
73
+ import { findInMsgSetByDate , findInMsgSetById , makeAddNotifications } from './utils' ;
74
74
import { getChannel } from '../../utils' ;
75
75
76
76
import type { MessageProps } from '../Message/types' ;
@@ -770,54 +770,113 @@ const ChannelInner = <
770
770
const jumpToFirstUnreadMessage = useCallback (
771
771
async ( queryMessageLimit = 100 ) => {
772
772
if ( ! ( client . user && channelUnreadUiState ?. unread_messages ) ) return ;
773
- if ( ! channelUnreadUiState ?. last_read_message_id ) {
774
- addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
775
- return ;
773
+ let lastReadMessageId = channelUnreadUiState ?. last_read_message_id ;
774
+ let firstUnreadMessageId = channelUnreadUiState ?. first_unread_message_id ;
775
+ let isInCurrentMessageSet = false ;
776
+ let hasMoreMessages = true ;
777
+
778
+ if ( firstUnreadMessageId ) {
779
+ const result = findInMsgSetById ( firstUnreadMessageId , channel . state . messages ) ;
780
+ isInCurrentMessageSet = result . index !== - 1 ;
781
+ } else if ( lastReadMessageId ) {
782
+ const result = findInMsgSetById ( lastReadMessageId , channel . state . messages ) ;
783
+ isInCurrentMessageSet = ! ! result . target ;
784
+ firstUnreadMessageId =
785
+ result . index > - 1 ? channel . state . messages [ result . index + 1 ] ?. id : undefined ;
786
+ } else {
787
+ const lastReadTimestamp = channelUnreadUiState . last_read . getTime ( ) ;
788
+ const { index : lastReadMessageIndex , target : lastReadMessage } = findInMsgSetByDate (
789
+ channelUnreadUiState . last_read ,
790
+ channel . state . messages ,
791
+ true ,
792
+ ) ;
793
+
794
+ if ( lastReadMessage ) {
795
+ firstUnreadMessageId = channel . state . messages [ lastReadMessageIndex + 1 ] ?. id ;
796
+ isInCurrentMessageSet = ! ! firstUnreadMessageId ;
797
+ lastReadMessageId = lastReadMessage . id ;
798
+ } else {
799
+ dispatch ( { loadingMore : true , type : 'setLoadingMore' } ) ;
800
+ let messages ;
801
+ try {
802
+ messages = (
803
+ await channel . query (
804
+ {
805
+ messages : {
806
+ created_at_around : channelUnreadUiState . last_read . toISOString ( ) ,
807
+ limit : queryMessageLimit ,
808
+ } ,
809
+ } ,
810
+ 'new' ,
811
+ )
812
+ ) . messages ;
813
+ } catch ( e ) {
814
+ addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
815
+ loadMoreFinished ( hasMoreMessages , channel . state . messages ) ;
816
+ return ;
817
+ }
818
+ const firstMessageWithCreationDate = messages . find ( ( msg ) => msg . created_at ) ;
819
+ if ( ! ( messages . length && firstMessageWithCreationDate ) ) {
820
+ addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
821
+ return ;
822
+ }
823
+ const firstMessageTimestamp = new Date (
824
+ firstMessageWithCreationDate . created_at as string ,
825
+ ) . getTime ( ) ;
826
+ if ( lastReadTimestamp < firstMessageTimestamp ) {
827
+ // whole channel is unread
828
+ firstUnreadMessageId = firstMessageWithCreationDate . id ;
829
+ hasMoreMessages = false ;
830
+ } else {
831
+ const result = findInMsgSetByDate ( channelUnreadUiState . last_read , messages ) ;
832
+ lastReadMessageId = result . target ?. id ;
833
+ hasMoreMessages = result . index >= Math . floor ( queryMessageLimit / 2 ) ;
834
+ }
835
+ }
776
836
}
777
837
778
- let indexOfLastReadMessage ;
779
-
780
- const currentMessageSet = channel . state . messages ;
781
- for ( let i = currentMessageSet . length - 1 ; i >= 0 ; i -- ) {
782
- const { id } = currentMessageSet [ i ] ;
783
- if ( id === channelUnreadUiState . last_read_message_id ) {
784
- indexOfLastReadMessage = i ;
785
- break ;
786
- }
838
+ if ( ! firstUnreadMessageId && ! lastReadMessageId ) {
839
+ addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
840
+ return ;
787
841
}
788
842
789
- if ( typeof indexOfLastReadMessage === 'undefined' ) {
843
+ if ( ! isInCurrentMessageSet ) {
790
844
dispatch ( { loadingMore : true , type : 'setLoadingMore' } ) ;
791
- let hasMoreMessages = true ;
792
845
try {
793
- await channel . state . loadMessageIntoState (
794
- channelUnreadUiState . last_read_message_id ,
795
- undefined ,
796
- queryMessageLimit ,
797
- ) ;
846
+ const targetId = ( firstUnreadMessageId ?? lastReadMessageId ) as string ;
847
+ await channel . state . loadMessageIntoState ( targetId , undefined , queryMessageLimit ) ;
798
848
/**
799
849
* if the index of the last read message on the page is beyond the half of the page,
800
850
* we have arrived to the oldest page of the channel
801
851
*/
802
- indexOfLastReadMessage = channel . state . messages . findIndex (
803
- ( message ) => message . id === channelUnreadUiState . last_read_message_id ,
852
+ const indexOfTarget = channel . state . messages . findIndex (
853
+ ( message ) => message . id === targetId ,
804
854
) as number ;
805
- hasMoreMessages = indexOfLastReadMessage >= Math . floor ( queryMessageLimit / 2 ) ;
855
+ hasMoreMessages = indexOfTarget >= Math . floor ( queryMessageLimit / 2 ) ;
856
+ loadMoreFinished ( hasMoreMessages , channel . state . messages ) ;
857
+ firstUnreadMessageId =
858
+ firstUnreadMessageId ?? channel . state . messages [ indexOfTarget + 1 ] ?. id ;
806
859
} catch ( e ) {
807
860
addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
808
861
loadMoreFinished ( hasMoreMessages , channel . state . messages ) ;
809
862
return ;
810
863
}
811
-
812
- loadMoreFinished ( hasMoreMessages , channel . state . messages ) ;
813
864
}
814
865
815
- const firstUnreadMessage = channel . state . messages [ indexOfLastReadMessage + 1 ] ;
816
- const jumpToMessageId = firstUnreadMessage ?. id ?? channelUnreadUiState . last_read_message_id ;
866
+ if ( ! firstUnreadMessageId ) {
867
+ addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
868
+ return ;
869
+ }
870
+ if ( ! channelUnreadUiState . first_unread_message_id )
871
+ _setChannelUnreadUiState ( {
872
+ ...channelUnreadUiState ,
873
+ first_unread_message_id : firstUnreadMessageId ,
874
+ last_read_message_id : lastReadMessageId ,
875
+ } ) ;
817
876
818
877
dispatch ( {
819
878
hasMoreNewer : channel . state . messages !== channel . state . latestMessages ,
820
- highlightedMessageId : jumpToMessageId ,
879
+ highlightedMessageId : firstUnreadMessageId ,
821
880
type : 'jumpToMessageFinished' ,
822
881
} ) ;
823
882
0 commit comments