Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Conversation history does not scroll down after sending a message and IOU #27162

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/pages/home/report/ReportActionsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ const MSG_VISIBLE_THRESHOLD = 250;
// the useRef value gets reset when the reportID changes, so we use a global variable to keep track
let prevReportID = null;

// In the component we are subscribing to the arrival of new actions.
// As there is the possibility that there are multiple instances of a ReportScreen
// for the same report, we only ever want one subscription to be active, as
// the subscriptions could otherwise be conflicting.
const newActionUnsubscribeMap = {};

/**
* Create a unique key for each action in the FlatList.
* We use the reportActionID that is a string representation of a random 64-bit int, which should be
Expand Down Expand Up @@ -176,6 +182,44 @@ function ReportActionsList({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [report.lastReadTime]);

useEffect(() => {
// Why are we doing this, when in the cleanup of the useEffect we are already calling the unsubscribe function?
// Answer: On web, when navigating to another report screen, the previous report screen doesn't get unmounted,
// meaning that the cleanup might not get called. When we then open a report we had open already previosuly, a new
// ReportScreen will get created. Thus, we have to cancel the earlier subscription of the previous screen,
// because the two subscriptions could conflict!
// In case we return to the previous screen (e.g. by web back navigation) the useEffect for that screen would
// fire again, as the focus has changed and will set up the subscription correctly again.
const previousSubUnsubscribe = newActionUnsubscribeMap[report.reportID];
if (previousSubUnsubscribe) {
previousSubUnsubscribe();
}

// This callback is triggered when a new action arrives via Pusher and the event is emitted from Report.js. This allows us to maintain
// a single source of truth for the "new action" event instead of trying to derive that a new action has appeared from looking at props.
const unsubscribe = Report.subscribeToNewActionEvent(report.reportID, (isFromCurrentUser) => {
// If a new comment is added and it's from the current user scroll to the bottom otherwise leave the user positioned where
// they are now in the list.
if (!isFromCurrentUser) {
return;
}
reportScrollManager.scrollToBottom();
});

const cleanup = () => {
if (unsubscribe) {
unsubscribe();
}
Report.unsubscribeFromReportChannel(report.reportID);
};

newActionUnsubscribeMap[report.reportID] = cleanup;

return cleanup;

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [report.reportID]);

/**
* Show/hide the new floating message counter when user is scrolling back/forth in the history of messages.
*/
Expand Down
Loading