Skip to content

Commit 44eab3c

Browse files
committed
Merge branch 'release-v11'
# Conflicts: # CHANGELOG.md # package.json # yarn.lock
2 parents afcd40f + 1802418 commit 44eab3c

File tree

5 files changed

+70
-51
lines changed

5 files changed

+70
-51
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@ TypingIndicator is rendered as a child of MessageListMainPanel
110110

111111
* remove legacy style components ([#2394](https://github.com/GetStream/stream-chat-react/issues/2394)) ([9410153](https://github.com/GetStream/stream-chat-react/commit/94101535d1de9de23a1ab8913423af0e7009bab9))
112112

113+
## [11.23.7](https://github.com/GetStream/stream-chat-react/compare/v11.23.6...v11.23.7) (2024-08-22)
114+
115+
116+
### Bug Fixes
117+
118+
* use the client pagination indicators for ChannelStateContext's hasMore and hasMoreNewer flags ([#2478](https://github.com/GetStream/stream-chat-react/issues/2478)) ([eb13bd5](https://github.com/GetStream/stream-chat-react/commit/eb13bd51ec296f36f9a09edd28704ea2d22f3ed1))
119+
120+
## [11.23.6](https://github.com/GetStream/stream-chat-react/compare/v11.23.5...v11.23.6) (2024-08-15)
121+
122+
123+
### Bug Fixes
124+
125+
* **deps:** drop remark-gfm version ([#2471](https://github.com/GetStream/stream-chat-react/issues/2471)) ([1b359f7](https://github.com/GetStream/stream-chat-react/commit/1b359f7e4a5d4cca6edc3abbd97dee42b55c4a79))
126+
113127
## [11.23.5](https://github.com/GetStream/stream-chat-react/compare/v11.23.4...v11.23.5) (2024-08-08)
114128

115129

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@
239239
"react-dom": "^18.1.0",
240240
"react-test-renderer": "^18.1.0",
241241
"semantic-release": "^19.0.5",
242-
"stream-chat": "^8.33.1",
242+
"stream-chat": "8.39.0",
243243
"ts-jest": "^29.1.4",
244244
"typescript": "^5.4.5"
245245
},

src/components/Channel/Channel.tsx

Lines changed: 21 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,11 @@ const ChannelInner = <
411411
channelReducer,
412412
// channel.initialized === false if client.channel().query() was not called, e.g. ChannelList is not used
413413
// => Channel will call channel.watch() in useLayoutEffect => state.loading is used to signal the watch() call state
414-
{ ...initialState, loading: !channel.initialized },
414+
{
415+
...initialState,
416+
hasMore: channel.state.messagePagination.hasPrev,
417+
loading: !channel.initialized,
418+
},
415419
);
416420

417421
const isMounted = useIsMounted();
@@ -569,7 +573,6 @@ const ChannelInner = <
569573
useLayoutEffect(() => {
570574
let errored = false;
571575
let done = false;
572-
let channelInitializedExternally = true;
573576

574577
(async () => {
575578
if (!channel.initialized && initializeOnMount) {
@@ -595,7 +598,6 @@ const ChannelInner = <
595598
await getChannel({ channel, client, members, options: channelQueryOptions });
596599
const config = channel.getConfig();
597600
setChannelConfig(config);
598-
channelInitializedExternally = false;
599601
} catch (e) {
600602
dispatch({ error: e as Error, type: 'setError' });
601603
errored = true;
@@ -608,12 +610,7 @@ const ChannelInner = <
608610
if (!errored) {
609611
dispatch({
610612
channel,
611-
hasMore:
612-
channelInitializedExternally ||
613-
hasMoreMessagesProbably(
614-
channel.state.messages.length,
615-
channelQueryOptions.messages.limit,
616-
),
613+
hasMore: channel.state.messagePagination.hasPrev,
617614
type: 'initStateFromChannel',
618615
});
619616

@@ -688,7 +685,8 @@ const ChannelInner = <
688685
);
689686

690687
const loadMore = async (limit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE) => {
691-
if (!online.current || !window.navigator.onLine || !state.hasMore) return 0;
688+
if (!online.current || !window.navigator.onLine || !channel.state.messagePagination.hasPrev)
689+
return 0;
692690

693691
// prevent duplicate loading events...
694692
const oldestMessage = state?.messages?.[0];
@@ -714,14 +712,14 @@ const ChannelInner = <
714712
return 0;
715713
}
716714

717-
const hasMoreMessages = queryResponse.messages.length === perPage;
718-
loadMoreFinished(hasMoreMessages, channel.state.messages);
715+
loadMoreFinished(channel.state.messagePagination.hasPrev, channel.state.messages);
719716

720717
return queryResponse.messages.length;
721718
};
722719

723720
const loadMoreNewer = async (limit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE) => {
724-
if (!online.current || !window.navigator.onLine || !state.hasMoreNewer) return 0;
721+
if (!online.current || !window.navigator.onLine || !channel.state.messagePagination.hasNext)
722+
return 0;
725723

726724
const newestMessage = state?.messages?.[state?.messages?.length - 1];
727725
if (state.loadingMore || state.loadingMoreNewer) return 0;
@@ -743,10 +741,8 @@ const ChannelInner = <
743741
return 0;
744742
}
745743

746-
const hasMoreNewerMessages = channel.state.messages !== channel.state.latestMessages;
747-
748744
dispatch({
749-
hasMoreNewer: hasMoreNewerMessages,
745+
hasMoreNewer: channel.state.messagePagination.hasNext,
750746
messages: channel.state.messages,
751747
type: 'loadMoreNewerFinished',
752748
});
@@ -764,18 +760,9 @@ const ChannelInner = <
764760
dispatch({ loadingMore: true, type: 'setLoadingMore' });
765761
await channel.state.loadMessageIntoState(messageId, undefined, messageLimit);
766762

767-
/**
768-
* if the message we are jumping to has less than half of the page size older messages,
769-
* we have jumped to the beginning of the channel.
770-
*/
771-
const indexOfMessage = channel.state.messages.findIndex(
772-
(message) => message.id === messageId,
773-
);
774-
const hasMoreMessages = indexOfMessage >= Math.floor(messageLimit / 2);
775-
776-
loadMoreFinished(hasMoreMessages, channel.state.messages);
763+
loadMoreFinished(channel.state.messagePagination.hasPrev, channel.state.messages);
777764
dispatch({
778-
hasMoreNewer: channel.state.messages !== channel.state.latestMessages,
765+
hasMoreNewer: channel.state.messagePagination.hasNext,
779766
highlightedMessageId: messageId,
780767
type: 'jumpToMessageFinished',
781768
});
@@ -794,9 +781,7 @@ const ChannelInner = <
794781

795782
const jumpToLatestMessage: ChannelActionContextValue<StreamChatGenerics>['jumpToLatestMessage'] = useCallback(async () => {
796783
await channel.state.loadMessageIntoState('latest');
797-
// FIXME: we cannot rely on constant value 25 as the page size can be customized by integrators
798-
const hasMoreOlder = channel.state.messages.length >= 25;
799-
loadMoreFinished(hasMoreOlder, channel.state.messages);
784+
loadMoreFinished(channel.state.messagePagination.hasPrev, channel.state.messages);
800785
dispatch({
801786
type: 'jumpToLatestMessage',
802787
});
@@ -811,7 +796,6 @@ const ChannelInner = <
811796
let lastReadMessageId = channelUnreadUiState?.last_read_message_id;
812797
let firstUnreadMessageId = channelUnreadUiState?.first_unread_message_id;
813798
let isInCurrentMessageSet = false;
814-
let hasMoreMessages = true;
815799

816800
if (firstUnreadMessageId) {
817801
const result = findInMsgSetById(firstUnreadMessageId, channel.state.messages);
@@ -850,14 +834,14 @@ const ChannelInner = <
850834
).messages;
851835
} catch (e) {
852836
addNotification(t('Failed to jump to the first unread message'), 'error');
853-
loadMoreFinished(hasMoreMessages, channel.state.messages);
837+
loadMoreFinished(channel.state.messagePagination.hasPrev, channel.state.messages);
854838
return;
855839
}
856840

857841
const firstMessageWithCreationDate = messages.find((msg) => msg.created_at);
858842
if (!firstMessageWithCreationDate) {
859843
addNotification(t('Failed to jump to the first unread message'), 'error');
860-
loadMoreFinished(hasMoreMessages, channel.state.messages);
844+
loadMoreFinished(channel.state.messagePagination.hasPrev, channel.state.messages);
861845
return;
862846
}
863847
const firstMessageTimestamp = new Date(
@@ -866,13 +850,11 @@ const ChannelInner = <
866850
if (lastReadTimestamp < firstMessageTimestamp) {
867851
// whole channel is unread
868852
firstUnreadMessageId = firstMessageWithCreationDate.id;
869-
hasMoreMessages = false;
870853
} else {
871854
const result = findInMsgSetByDate(channelUnreadUiState.last_read, messages);
872855
lastReadMessageId = result.target?.id;
873-
hasMoreMessages = result.index >= Math.floor(queryMessageLimit / 2);
874856
}
875-
loadMoreFinished(hasMoreMessages, channel.state.messages);
857+
loadMoreFinished(channel.state.messagePagination.hasPrev, channel.state.messages);
876858
}
877859
}
878860

@@ -893,13 +875,12 @@ const ChannelInner = <
893875
const indexOfTarget = channel.state.messages.findIndex(
894876
(message) => message.id === targetId,
895877
) as number;
896-
hasMoreMessages = indexOfTarget >= Math.floor(queryMessageLimit / 2);
897-
loadMoreFinished(hasMoreMessages, channel.state.messages);
878+
loadMoreFinished(channel.state.messagePagination.hasPrev, channel.state.messages);
898879
firstUnreadMessageId =
899880
firstUnreadMessageId ?? channel.state.messages[indexOfTarget + 1]?.id;
900881
} catch (e) {
901882
addNotification(t('Failed to jump to the first unread message'), 'error');
902-
loadMoreFinished(hasMoreMessages, channel.state.messages);
883+
loadMoreFinished(channel.state.messagePagination.hasPrev, channel.state.messages);
903884
return;
904885
}
905886
}
@@ -916,7 +897,7 @@ const ChannelInner = <
916897
});
917898

918899
dispatch({
919-
hasMoreNewer: channel.state.messages !== channel.state.latestMessages,
900+
hasMoreNewer: channel.state.messagePagination.hasNext,
920901
highlightedMessageId: firstUnreadMessageId,
921902
type: 'jumpToMessageFinished',
922903
});

src/components/Channel/__tests__/Channel.test.js

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ const ActiveChannelSetter = ({ activeChannel }) => {
9090
const user = generateUser({ custom: 'custom-value', id: 'id', name: 'name' });
9191

9292
// create a full message state so that we can properly test `loadMore`
93-
const messages = Array.from({ length: 25 }, () => generateMessage({ user }));
93+
const messages = Array.from({ length: 25 }, (_, i) =>
94+
generateMessage({ created_at: new Date((i + 1) * 1000000), user }),
95+
);
9496

9597
const pinnedMessages = [generateMessage({ pinned: true, user })];
9698

@@ -701,6 +703,20 @@ describe('Channel', () => {
701703

702704
describe('loading more messages', () => {
703705
const limit = 10;
706+
it("should initiate the hasMore flag with the current message set's pagination hasPrev value", async () => {
707+
const { channel, chatClient } = await initClient();
708+
let hasMore;
709+
await renderComponent({ channel, chatClient }, ({ hasMore: hasMoreCtx }) => {
710+
hasMore = hasMoreCtx;
711+
});
712+
expect(hasMore).toBe(true);
713+
714+
channel.state.messageSets[0].pagination.hasPrev = false;
715+
await renderComponent({ channel, chatClient }, ({ hasMore: hasMoreCtx }) => {
716+
hasMore = hasMoreCtx;
717+
});
718+
expect(hasMore).toBe(false);
719+
});
704720
it('should be able to load more messages', async () => {
705721
const { channel, chatClient } = await initClient();
706722
const channelQuerySpy = jest.spyOn(channel, 'query');
@@ -740,7 +756,7 @@ describe('Channel', () => {
740756
it('should set hasMore to false if querying channel returns less messages than the limit', async () => {
741757
const { channel, chatClient } = await initClient();
742758
let channelHasMore = false;
743-
const newMessages = [generateMessage()];
759+
const newMessages = [generateMessage({ created_at: new Date(1000) })];
744760
await renderComponent(
745761
{ channel, chatClient },
746762
({ hasMore, loadMore, messages: contextMessages }) => {
@@ -822,8 +838,12 @@ describe('Channel', () => {
822838

823839
it('should load the second page, if the previous query has returned message count equal default messages limit', async () => {
824840
const { channel, chatClient } = await initClient();
825-
const firstPageMessages = Array.from({ length: 25 }, generateMessage);
826-
const secondPageMessages = Array.from({ length: 15 }, generateMessage);
841+
const firstPageMessages = Array.from({ length: 25 }, (_, i) =>
842+
generateMessage({ created_at: new Date((i + 16) * 100000) }),
843+
);
844+
const secondPageMessages = Array.from({ length: 15 }, (_, i) =>
845+
generateMessage({ created_at: new Date((i + 1) * 100000) }),
846+
);
827847
useMockedApis(chatClient, [queryChannelWithNewMessages(firstPageMessages, channel)]);
828848
let queryNextPageSpy;
829849
let contextMessageCount;
@@ -896,8 +916,12 @@ describe('Channel', () => {
896916
const channelQueryOptions = {
897917
messages: { limit: equalCount },
898918
};
899-
const firstPageMessages = Array.from({ length: equalCount }, generateMessage);
900-
const secondPageMessages = Array.from({ length: equalCount - 1 }, generateMessage);
919+
const firstPageMessages = Array.from({ length: equalCount }, (_, i) =>
920+
generateMessage({ created_at: new Date((i + 1 + equalCount) * 100000) }),
921+
);
922+
const secondPageMessages = Array.from({ length: equalCount - 1 }, (_, i) =>
923+
generateMessage({ created_at: new Date((i + 1) * 100000) }),
924+
);
901925
useMockedApis(chatClient, [queryChannelWithNewMessages(firstPageMessages, channel)]);
902926
let queryNextPageSpy;
903927
let contextMessageCount;

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12194,10 +12194,10 @@ [email protected]:
1219412194
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
1219512195
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
1219612196

12197-
stream-chat@^8.33.1:
12198-
version "8.36.0"
12199-
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-8.36.0.tgz#a241829fc219a409a1e04d82034d726244b8d1f7"
12200-
integrity sha512-J0s5K6lOJdrncmnHQ1YmPHBfswkozuiJ49xKUwBqGL5T4wvKM/7C+6vhUdp5pILfbBivJtIkGzQHVVizjpzQPw==
12197+
stream-chat@8.39.0:
12198+
version "8.39.0"
12199+
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-8.39.0.tgz#f4cb86bd5cac4c1272c24cd66ed4752bcda8d717"
12200+
integrity sha512-zQZR1tPrgGBbu+Gnv9F9KQx3OPUMvb0FN+39BEjkjgjRPm2JYhF78jfcYutQMiC538t3V+NgFGgj5N4sZvSsUA==
1220112201
dependencies:
1220212202
"@babel/runtime" "^7.16.3"
1220312203
"@types/jsonwebtoken" "~9.0.0"

0 commit comments

Comments
 (0)