Skip to content

Commit b2c2aee

Browse files
authored
[CLNP-8108][fix]: Fixed a bug where the message list did not scroll to the startingPoint set on the GroupChannel (#1397)
Fixes [CLNP-8108](https://sendbird.atlassian.net/browse/CLNP-8108) ### Changelogs - Fixed a bug where the message list did not scroll to the startingPoint set on the GroupChannel ### Checklist Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If unsure, ask the members. This is a reminder of what we look for before merging your code. - [x] **All tests pass locally with my changes** - [ ] **I have added tests that prove my fix is effective or that my feature works** - [ ] **Public components / utils / props are appropriately exported** - [ ] I have added necessary documentation (if appropriate) ## External Contributions This project is not yet set up to accept pull requests from external contributors. If you have a pull request that you believe should be accepted, please contact the Developer Relations team <developer-advocates@sendbird.com> with details and we'll evaluate if we can set up a [CLA](https://en.wikipedia.org/wiki/Contributor_License_Agreement) to allow for the contribution. [CLNP-8108]: https://sendbird.atlassian.net/browse/CLNP-8108?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
1 parent 4baf8ae commit b2c2aee

File tree

3 files changed

+27
-7
lines changed

3 files changed

+27
-7
lines changed

src/modules/GroupChannel/context/GroupChannelProvider.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,10 +302,10 @@ const GroupChannelManager :React.FC<React.PropsWithChildren<GroupChannelProvider
302302

303303
// Starting point handling
304304
useEffect(() => {
305-
if (typeof startingPoint === 'number' && messageDataSource.initialized) {
305+
if (typeof startingPoint === 'number' && state.initialized) {
306306
actions.scrollToMessage(startingPoint, 0, false, false);
307307
}
308-
}, [messageDataSource.initialized, startingPoint]);
308+
}, [state.initialized, startingPoint]);
309309

310310
// Animated message handling
311311
useEffect(() => {

src/modules/GroupChannel/context/__tests__/useGroupChannel.spec.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,12 @@ describe('useGroupChannel', () => {
301301
});
302302
it('loads message and scrolls when message does not exist', async () => {
303303
const mockScrollPubSub = { publish: jest.fn() };
304-
const mockResetWithStartingPoint = jest.fn().mockResolvedValue(undefined);
304+
const mockResetWithStartingPoint = jest.fn().mockImplementation(async (startingPoint: number) => {
305+
mockStore.setState((prev) => ({
306+
...prev,
307+
messages: [{ createdAt: startingPoint, messageId: 123 }],
308+
} as typeof prev));
309+
});
305310
const mockStore = createMockStore({
306311
messages: [],
307312
initialized: true,

src/modules/GroupChannel/context/hooks/useGroupChannel.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,8 @@ export const useGroupChannel = () => {
126126
clickHandler.deactivate();
127127

128128
setAnimatedMessageId(null);
129-
const message = state.messages.find(
130-
(it) => it.messageId === messageId || it.createdAt === createdAt,
131-
);
129+
130+
const message = state.messages.find((it) => it.messageId === messageId || it.createdAt === createdAt);
132131

133132
if (message) {
134133
const topOffset = getMessageTopOffset(message.createdAt);
@@ -137,7 +136,23 @@ export const useGroupChannel = () => {
137136
} else if (state.initialized) {
138137
await state.resetWithStartingPoint(createdAt);
139138
setTimeout(() => {
140-
const topOffset = getMessageTopOffset(createdAt);
139+
// NOTE: Inside setTimeout callback, the closure-captured `state` is a stale snapshot (before reset).
140+
// Use store.getState() to get the latest state (including updated messages) at callback execution time.
141+
const currentState = store.getState();
142+
143+
if (currentState.messages.length === 0) return; // empty channel case.
144+
let message = null;
145+
let distance = Number.MAX_SAFE_INTEGER;
146+
for (const it of currentState.messages) {
147+
if (it.createdAt > createdAt) break;
148+
const diff = Math.abs(it.createdAt - createdAt);
149+
if (diff < distance) {
150+
distance = diff;
151+
message = it;
152+
}
153+
}
154+
155+
const topOffset = getMessageTopOffset(message.createdAt);
141156
if (topOffset !== null) {
142157
state.scrollPubSub.publish('scroll', {
143158
top: topOffset,

0 commit comments

Comments
 (0)