Skip to content

Commit

Permalink
Merge pull request #42742 from dominictb/fix/41935
Browse files Browse the repository at this point in the history
fix: re-calc the marker when msgs are deleted
  • Loading branch information
arosiclair authored Jun 20, 2024
2 parents 8a5db3e + b7f75ef commit f618a94
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@ function ReportScreen({
<View
style={[styles.flex1, styles.justifyContentEnd, styles.overflowHidden]}
onLayout={onListLayout}
testID="report-actions-view-wrapper"
>
{shouldShowReportActionList && (
<ReportActionsView
Expand Down
32 changes: 25 additions & 7 deletions src/pages/home/report/ReportActionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -444,12 +444,14 @@ function ReportActionsList({
* Evaluate new unread marker visibility for each of the report actions.
*/
const shouldDisplayNewMarker = useCallback(
(reportAction: OnyxTypes.ReportAction, index: number): boolean => {
(reportAction: OnyxTypes.ReportAction, index: number, lastReadTime?: string, shouldCheckWithCurrentUnreadMarker?: boolean): boolean => {
// if lastReadTime is null, use the lastReadTimeRef.current
const baseLastReadTime = lastReadTime ?? lastReadTimeRef.current;
let shouldDisplay = false;
if (!currentUnreadMarker) {
if (!currentUnreadMarker || !shouldCheckWithCurrentUnreadMarker) {
const nextMessage = sortedVisibleReportActions[index + 1];
const isCurrentMessageUnread = isMessageUnread(reportAction, lastReadTimeRef.current);
shouldDisplay = isCurrentMessageUnread && (!nextMessage || !isMessageUnread(nextMessage, lastReadTimeRef.current)) && !ReportActionsUtils.shouldHideNewMarker(reportAction);
const isCurrentMessageUnread = isMessageUnread(reportAction, baseLastReadTime);
shouldDisplay = isCurrentMessageUnread && (!nextMessage || !isMessageUnread(nextMessage, baseLastReadTime)) && !ReportActionsUtils.shouldHideNewMarker(reportAction);
if (shouldDisplay && !messageManuallyMarkedUnread) {
const isWithinVisibleThreshold = scrollingVerticalOffset.current < MSG_VISIBLE_THRESHOLD ? reportAction.created < (userActiveSince.current ?? '') : true;
// Prevent displaying a new marker line when report action is of type "REPORT_PREVIEW" and last actor is the current user
Expand Down Expand Up @@ -487,21 +489,37 @@ function ReportActionsList({
return ReportUtils.isExpenseReport(report) || ReportUtils.isIOUReport(report);
}, [parentReportAction, report, sortedVisibleReportActions]);

// storing the last read time used to render the unread marker
const markerLastReadTimeRef = useRef<string | undefined>();

useEffect(() => {
if (currentUnreadMarker) {
return;
}
markerLastReadTimeRef.current = undefined;
}, [currentUnreadMarker]);

const calculateUnreadMarker = useCallback(() => {
// Iterate through the report actions and set appropriate unread marker.
// This is to avoid a warning of:
// Cannot update a component (ReportActionsList) while rendering a different component (CellRenderer).
let markerFound = false;
sortedVisibleReportActions.forEach((reportAction, index) => {
if (!shouldDisplayNewMarker(reportAction, index)) {
if (!shouldDisplayNewMarker(reportAction, index, markerLastReadTimeRef.current, false)) {
return;
}
markerFound = true;
if (!currentUnreadMarker && currentUnreadMarker !== reportAction.reportActionID) {
if (!currentUnreadMarker || currentUnreadMarker !== reportAction.reportActionID) {
cacheUnreadMarkers.set(report.reportID, reportAction.reportActionID);
setCurrentUnreadMarker(reportAction.reportActionID);
}
});

// if marker can be found, set the markerLastReadTimeRef to the last read time if necessary
if (markerFound && !markerLastReadTimeRef.current) {
markerLastReadTimeRef.current = lastReadTimeRef.current;
}

if (!markerFound && !linkedReportActionID) {
setCurrentUnreadMarker(null);
}
Expand Down Expand Up @@ -570,7 +588,7 @@ function ReportActionsList({
displayAsGroup={ReportActionsUtils.isConsecutiveActionMadeByPreviousActor(sortedVisibleReportActions, index)}
mostRecentIOUReportActionID={mostRecentIOUReportActionID}
shouldHideThreadDividerLine={shouldHideThreadDividerLine}
shouldDisplayNewMarker={shouldDisplayNewMarker(reportAction, index)}
shouldDisplayNewMarker={shouldDisplayNewMarker(reportAction, index, markerLastReadTimeRef.current, true)}
shouldDisplayReplyDivider={sortedVisibleReportActions.length > 1}
isFirstVisibleReportAction={firstVisibleReportActionID === reportAction.reportActionID}
shouldUseThreadDividerLine={shouldUseThreadDividerLine}
Expand Down
46 changes: 46 additions & 0 deletions tests/ui/UnreadIndicatorsTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,52 @@ describe('Unread Indicators', () => {
expect(displayNameTexts[1]?.props?.style?.fontWeight).toBe(FontUtils.fontWeight.bold);
expect(screen.getByText('B User')).toBeOnTheScreen();
}));
it('Delete a chat message and verify the unread indicator is moved', async () => {
const getUnreadIndicator = () => {
const newMessageLineIndicatorHintText = Localize.translateLocal('accessibilityHints.newMessageLineIndicator');
return screen.queryAllByLabelText(newMessageLineIndicatorHintText);
};

return signInAndGetAppWithUnreadChat()
.then(() => navigateToSidebarOption(0))
.then(async () => act(() => transitionEndCB?.()))
.then(async () => {
const reportActionsViewWrapper = await screen.findByTestId('report-actions-view-wrapper');
if (reportActionsViewWrapper) {
fireEvent(reportActionsViewWrapper, 'onLayout', {nativeEvent: {layout: {x: 0, y: 0, width: 100, height: 100}}});
}
return waitForBatchedUpdates();
})
.then(() => {
// Verify the new line indicator is present, and it's before the action with ID 4
const unreadIndicator = getUnreadIndicator();
expect(unreadIndicator).toHaveLength(1);
const reportActionID = unreadIndicator[0]?.props?.['data-action-id'];
expect(reportActionID).toBe('4');

// simulate delete comment event from Pusher
PusherHelper.emitOnyxUpdate([
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID}`,
value: {
'4': {
message: [],
},
},
},
]);
return waitForBatchedUpdates();
})
.then(() =>
// Verify the new line indicator is now before the action with ID 5
waitFor(() => {
const unreadIndicator = getUnreadIndicator();
const reportActionID = unreadIndicator[0]?.props?.['data-action-id'];
expect(reportActionID).toBe('5');
}),
);
});

xit('Manually marking a chat message as unread shows the new line indicator and updates the LHN', () =>
signInAndGetAppWithUnreadChat()
Expand Down

0 comments on commit f618a94

Please sign in to comment.