@@ -66,14 +66,15 @@ import { TypingProvider } from '../../context/TypingContext';
66
66
67
67
import {
68
68
DEFAULT_INITIAL_CHANNEL_PAGE_SIZE ,
69
+ DEFAULT_JUMP_TO_PAGE_SIZE ,
69
70
DEFAULT_NEXT_CHANNEL_PAGE_SIZE ,
70
71
DEFAULT_THREAD_PAGE_SIZE ,
71
72
} from '../../constants/limits' ;
72
73
73
74
import type { UnreadMessagesNotificationProps } from '../MessageList' ;
74
75
import { hasMoreMessagesProbably , UnreadMessagesSeparator } from '../MessageList' ;
75
76
import { useChannelContainerClasses } from './hooks/useChannelContainerClasses' ;
76
- import { makeAddNotifications } from './utils' ;
77
+ import { findInMsgSetByDate , findInMsgSetById , makeAddNotifications } from './utils' ;
77
78
import { getChannel } from '../../utils' ;
78
79
79
80
import type { MessageProps } from '../Message/types' ;
@@ -554,6 +555,10 @@ const ChannelInner = <
554
555
} ;
555
556
} ) ;
556
557
558
+ if ( event . type === 'channel.truncated' && event . cid === channel . cid ) {
559
+ _setChannelUnreadUiState ( undefined ) ;
560
+ }
561
+
557
562
throttledCopyStateFromChannel ( ) ;
558
563
} ;
559
564
@@ -709,7 +714,7 @@ const ChannelInner = <
709
714
return queryResponse . messages . length ;
710
715
} ;
711
716
712
- const loadMoreNewer = async ( limit = 100 ) => {
717
+ const loadMoreNewer = async ( limit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE ) => {
713
718
if ( ! online . current || ! window . navigator . onLine || ! state . hasMoreNewer ) return 0 ;
714
719
715
720
const newestMessage = state ?. messages ?. [ state ?. messages ?. length - 1 ] ;
@@ -744,7 +749,7 @@ const ChannelInner = <
744
749
745
750
const clearHighlightedMessageTimeoutId = useRef < ReturnType < typeof setTimeout > | null > ( null ) ;
746
751
747
- const jumpToMessage = async ( messageId : string , messageLimit = 100 ) => {
752
+ const jumpToMessage = async ( messageId : string , messageLimit = DEFAULT_JUMP_TO_PAGE_SIZE ) => {
748
753
dispatch ( { loadingMore : true , type : 'setLoadingMore' } ) ;
749
754
await channel . state . loadMessageIntoState ( messageId , undefined , messageLimit ) ;
750
755
@@ -783,56 +788,118 @@ const ChannelInner = <
783
788
} ;
784
789
785
790
const jumpToFirstUnreadMessage = useCallback (
786
- async ( queryMessageLimit = 100 ) => {
787
- if ( ! ( client . user && channelUnreadUiState ?. unread_messages ) ) return ;
788
- if ( ! channelUnreadUiState ?. last_read_message_id ) {
789
- addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
790
- return ;
791
- }
792
-
793
- let indexOfLastReadMessage ;
791
+ async ( queryMessageLimit = DEFAULT_JUMP_TO_PAGE_SIZE ) => {
792
+ if ( ! channelUnreadUiState ?. unread_messages ) return ;
793
+ let lastReadMessageId = channelUnreadUiState ?. last_read_message_id ;
794
+ let firstUnreadMessageId = channelUnreadUiState ?. first_unread_message_id ;
795
+ let isInCurrentMessageSet = false ;
796
+ let hasMoreMessages = true ;
797
+
798
+ if ( firstUnreadMessageId ) {
799
+ const result = findInMsgSetById ( firstUnreadMessageId , channel . state . messages ) ;
800
+ isInCurrentMessageSet = result . index !== - 1 ;
801
+ } else if ( lastReadMessageId ) {
802
+ const result = findInMsgSetById ( lastReadMessageId , channel . state . messages ) ;
803
+ isInCurrentMessageSet = ! ! result . target ;
804
+ firstUnreadMessageId =
805
+ result . index > - 1 ? channel . state . messages [ result . index + 1 ] ?. id : undefined ;
806
+ } else {
807
+ const lastReadTimestamp = channelUnreadUiState . last_read . getTime ( ) ;
808
+ const { index : lastReadMessageIndex , target : lastReadMessage } = findInMsgSetByDate (
809
+ channelUnreadUiState . last_read ,
810
+ channel . state . messages ,
811
+ true ,
812
+ ) ;
813
+
814
+ if ( lastReadMessage ) {
815
+ firstUnreadMessageId = channel . state . messages [ lastReadMessageIndex + 1 ] ?. id ;
816
+ isInCurrentMessageSet = ! ! firstUnreadMessageId ;
817
+ lastReadMessageId = lastReadMessage . id ;
818
+ } else {
819
+ dispatch ( { loadingMore : true , type : 'setLoadingMore' } ) ;
820
+ let messages ;
821
+ try {
822
+ messages = (
823
+ await channel . query (
824
+ {
825
+ messages : {
826
+ created_at_around : channelUnreadUiState . last_read . toISOString ( ) ,
827
+ limit : queryMessageLimit ,
828
+ } ,
829
+ } ,
830
+ 'new' ,
831
+ )
832
+ ) . messages ;
833
+ } catch ( e ) {
834
+ addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
835
+ loadMoreFinished ( hasMoreMessages , channel . state . messages ) ;
836
+ return ;
837
+ }
794
838
795
- const currentMessageSet = channel . state . messages ;
796
- for ( let i = currentMessageSet . length - 1 ; i >= 0 ; i -- ) {
797
- const { id } = currentMessageSet [ i ] ;
798
- if ( id === channelUnreadUiState . last_read_message_id ) {
799
- indexOfLastReadMessage = i ;
800
- break ;
839
+ const firstMessageWithCreationDate = messages . find ( ( msg ) => msg . created_at ) ;
840
+ if ( ! firstMessageWithCreationDate ) {
841
+ addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
842
+ loadMoreFinished ( hasMoreMessages , channel . state . messages ) ;
843
+ return ;
844
+ }
845
+ const firstMessageTimestamp = new Date (
846
+ firstMessageWithCreationDate . created_at as string ,
847
+ ) . getTime ( ) ;
848
+ if ( lastReadTimestamp < firstMessageTimestamp ) {
849
+ // whole channel is unread
850
+ firstUnreadMessageId = firstMessageWithCreationDate . id ;
851
+ hasMoreMessages = false ;
852
+ } else {
853
+ const result = findInMsgSetByDate ( channelUnreadUiState . last_read , messages ) ;
854
+ lastReadMessageId = result . target ?. id ;
855
+ hasMoreMessages = result . index >= Math . floor ( queryMessageLimit / 2 ) ;
856
+ }
857
+ loadMoreFinished ( hasMoreMessages , channel . state . messages ) ;
801
858
}
802
859
}
803
860
804
- if ( typeof indexOfLastReadMessage === 'undefined' ) {
861
+ if ( ! firstUnreadMessageId && ! lastReadMessageId ) {
862
+ addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
863
+ return ;
864
+ }
865
+
866
+ if ( ! isInCurrentMessageSet ) {
805
867
dispatch ( { loadingMore : true , type : 'setLoadingMore' } ) ;
806
- let hasMoreMessages = true ;
807
868
try {
808
- await channel . state . loadMessageIntoState (
809
- channelUnreadUiState . last_read_message_id ,
810
- undefined ,
811
- queryMessageLimit ,
812
- ) ;
869
+ const targetId = ( firstUnreadMessageId ?? lastReadMessageId ) as string ;
870
+ await channel . state . loadMessageIntoState ( targetId , undefined , queryMessageLimit ) ;
813
871
/**
814
872
* if the index of the last read message on the page is beyond the half of the page,
815
873
* we have arrived to the oldest page of the channel
816
874
*/
817
- indexOfLastReadMessage = channel . state . messages . findIndex (
818
- ( message ) => message . id === channelUnreadUiState . last_read_message_id ,
875
+ const indexOfTarget = channel . state . messages . findIndex (
876
+ ( message ) => message . id === targetId ,
819
877
) as number ;
820
- hasMoreMessages = indexOfLastReadMessage >= Math . floor ( queryMessageLimit / 2 ) ;
878
+ hasMoreMessages = indexOfTarget >= Math . floor ( queryMessageLimit / 2 ) ;
879
+ loadMoreFinished ( hasMoreMessages , channel . state . messages ) ;
880
+ firstUnreadMessageId =
881
+ firstUnreadMessageId ?? channel . state . messages [ indexOfTarget + 1 ] ?. id ;
821
882
} catch ( e ) {
822
883
addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
823
884
loadMoreFinished ( hasMoreMessages , channel . state . messages ) ;
824
885
return ;
825
886
}
826
-
827
- loadMoreFinished ( hasMoreMessages , channel . state . messages ) ;
828
887
}
829
888
830
- const firstUnreadMessage = channel . state . messages [ indexOfLastReadMessage + 1 ] ;
831
- const jumpToMessageId = firstUnreadMessage ?. id ?? channelUnreadUiState . last_read_message_id ;
889
+ if ( ! firstUnreadMessageId ) {
890
+ addNotification ( t ( 'Failed to jump to the first unread message' ) , 'error' ) ;
891
+ return ;
892
+ }
893
+ if ( ! channelUnreadUiState . first_unread_message_id )
894
+ _setChannelUnreadUiState ( {
895
+ ...channelUnreadUiState ,
896
+ first_unread_message_id : firstUnreadMessageId ,
897
+ last_read_message_id : lastReadMessageId ,
898
+ } ) ;
832
899
833
900
dispatch ( {
834
901
hasMoreNewer : channel . state . messages !== channel . state . latestMessages ,
835
- highlightedMessageId : jumpToMessageId ,
902
+ highlightedMessageId : firstUnreadMessageId ,
836
903
type : 'jumpToMessageFinished' ,
837
904
} ) ;
838
905
@@ -845,7 +912,7 @@ const ChannelInner = <
845
912
dispatch ( { type : 'clearHighlightedMessage' } ) ;
846
913
} , 500 ) ;
847
914
} ,
848
- [ addNotification , channel , client , loadMoreFinished , t , channelUnreadUiState ] ,
915
+ [ addNotification , channel , loadMoreFinished , t , channelUnreadUiState ] ,
849
916
) ;
850
917
851
918
const deleteMessage = useCallback (
0 commit comments