Skip to content

Commit 4ec5c1c

Browse files
authored
Merge pull request #90238 from nabi-ebrahimi/fix/public-room-message-send-after-restart
fix: resolve public room message send failure after app restart with emoji text
2 parents 33279d4 + d33c77a commit 4ec5c1c

4 files changed

Lines changed: 87 additions & 1 deletion

File tree

src/hooks/useLoadReportActions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ function useLoadReportActions({
117117
// (which may include Pusher-delivered actions like Concierge replies that skip gaps)
118118
if (newestFetchedReportActionID) {
119119
getNewerActions(reportID, newestFetchedReportActionID);
120+
121+
// Keep transaction thread in sync for mixed report+thread views.
122+
if (isTransactionThreadReport) {
123+
getNewerActions(transactionThreadReportID, transactionThreadNewestAction?.reportActionID);
124+
}
120125
return;
121126
}
122127

src/libs/PaginationUtils.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,19 @@ function getContinuousChain<TResource>(sortedItems: TResource[], pages: Pages, g
412412

413413
const linkedPage = pagesWithIndexes.find((pageIndex) => index >= pageIndex.firstIndex && index <= pageIndex.lastIndex);
414414

415+
const newestPage = selectNewestPageWithIndex(pagesWithIndexes);
416+
417+
// If the linked action is newer than the newest page boundary, show the newest chain
418+
// instead of collapsing to a single-item result.
419+
if (!linkedPage && newestPage && index < newestPage.firstIndex) {
420+
return {
421+
data: sortedItems.slice(0, newestPage.lastIndex + 1),
422+
hasNextPage: newestPage.lastID !== CONST.PAGINATION_END_ID,
423+
hasPreviousPage: newestPage.firstID !== CONST.PAGINATION_START_ID,
424+
resourceItem,
425+
};
426+
}
427+
415428
// If we are linked to an action in a gap return it by itself
416429
if (!linkedPage && resourceItem) {
417430
return {data: [resourceItem.item], hasNextPage: false, hasPreviousPage: false, resourceItem};
@@ -432,8 +445,11 @@ function getContinuousChain<TResource>(sortedItems: TResource[], pages: Pages, g
432445
return {data: sortedItems, hasNextPage: false, hasPreviousPage: false, resourceItem};
433446
}
434447

448+
// For the default newest chain, include known newer items that sit before the first fetched page.
449+
const startIndex = id ? page.firstIndex : 0;
450+
435451
return {
436-
data: sortedItems.slice(page.firstIndex, page.lastIndex + 1),
452+
data: sortedItems.slice(startIndex, page.lastIndex + 1),
437453
hasNextPage: page.lastID !== CONST.PAGINATION_END_ID,
438454
hasPreviousPage: page.firstID !== CONST.PAGINATION_START_ID,
439455
resourceItem,

src/pages/inbox/report/ReportActionsView.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ function ReportActionsView({reportID, onLayout}: ReportActionsViewProps) {
6767
const canPerformWriteAction = !!canUserPerformWriteAction(report, isReportArchived);
6868

6969
const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP);
70+
71+
const [reportPaginationState] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_PAGINATION_STATE}${reportID}`);
72+
7073
const reportPreviewAction = useMemo(() => getReportPreviewAction(report?.chatReportID, report?.reportID), [report?.chatReportID, report?.reportID]);
7174
const didLayout = useRef(false);
7275

@@ -92,6 +95,7 @@ function ReportActionsView({reportID, onLayout}: ReportActionsViewProps) {
9295
transactionThreadReportID,
9396
hasOlderActions,
9497
hasNewerActions,
98+
newestFetchedReportActionID: reportPaginationState?.newestFetchedReportActionID,
9599
});
96100

97101
const {sortedReportActions, sortedVisibleReportActions, isConciergeSidePanel, showConciergeSidePanelWelcome, showFullHistory, hasPreviousMessages, handleShowPreviousMessages} =

tests/unit/PaginationUtilsTest.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,67 @@ describe('PaginationUtils', () => {
250250
expect(result.hasNextPage).toBe(true);
251251
});
252252

253+
it('includes known newer actions before the first page for the default chain', () => {
254+
const input = createItems([
255+
// Given these sortedItems
256+
'18',
257+
'17',
258+
'16',
259+
'15',
260+
'14',
261+
// Gap
262+
'12',
263+
'11',
264+
'10',
265+
'9',
266+
]);
267+
268+
const pages = [
269+
// Given these pages
270+
['17', '16', '15', '14'],
271+
['12', '11', '10', '9'],
272+
];
273+
274+
const expectedResult = createItems([
275+
// Expect these sortedItems
276+
'18',
277+
'17',
278+
'16',
279+
'15',
280+
'14',
281+
]);
282+
const result = getContinuousChain(input, pages, getID, '');
283+
expect(result.data).toStrictEqual(expectedResult);
284+
expect(result.hasPreviousPage).toBe(true);
285+
expect(result.hasNextPage).toBe(true);
286+
});
287+
288+
it('when linked to an item newer than the newest page boundary, returns the newest chain instead of a single item', () => {
289+
const input = createItems([
290+
'18',
291+
'17',
292+
'16',
293+
'15',
294+
'14',
295+
// Gap
296+
'12',
297+
'11',
298+
'10',
299+
'9',
300+
]);
301+
302+
const pages = [
303+
['17', '16', '15', '14'],
304+
['12', '11', '10', '9'],
305+
];
306+
307+
const expectedResult = createItems(['18', '17', '16', '15', '14']);
308+
const result = getContinuousChain(input, pages, getID, '18');
309+
expect(result.data).toStrictEqual(expectedResult);
310+
expect(result.hasPreviousPage).toBe(true);
311+
expect(result.hasNextPage).toBe(true);
312+
});
313+
253314
it('given a page with an empty firstItemID include actions until the start', () => {
254315
const input = createItems([
255316
// Given these sortedItems

0 commit comments

Comments
 (0)