Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions src/libs/API/parameters/MarkAsUnreadParams.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
type MarkAsUnreadParams = {
reportID: string;
lastReadTime: string;
reportActionID: string;
};

export default MarkAsUnreadParams;
6 changes: 4 additions & 2 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,7 @@ function readNewestAction(reportID: string | undefined, shouldResetUnreadMarker
/**
* Sets the last read time on a report
*/
function markCommentAsUnread(reportID: string | undefined, reportActionCreated: string) {
function markCommentAsUnread(reportID: string | undefined, reportAction: ReportAction) {
if (!reportID) {
Log.warn('7339cd6c-3263-4f89-98e5-730f0be15784 Invalid report passed to MarkCommentAsUnread. Not calling the API because it wil fail.');
return;
Expand All @@ -1466,9 +1466,10 @@ function markCommentAsUnread(reportID: string | undefined, reportActionCreated:
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
const transactionThreadReportID = ReportActionsUtils.getOneTransactionThreadReportID(reportID, reportActions ?? []);
const transactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`];

// If no action created date is provided, use the last action's from other user
const actionCreationTime =
reportActionCreated || (latestReportActionFromOtherUsers?.created ?? getReportLastVisibleActionCreated(report, transactionThreadReport) ?? DateUtils.getDBTime(0));
reportAction?.created || (latestReportActionFromOtherUsers?.created ?? getReportLastVisibleActionCreated(report, transactionThreadReport) ?? DateUtils.getDBTime(0));

// We subtract 1 millisecond so that the lastReadTime is updated to just before a given reportAction's created date
// For example, if we want to mark a report action with ID 100 and created date '2014-04-01 16:07:02.999' unread, we set the lastReadTime to '2014-04-01 16:07:02.998'
Expand All @@ -1488,6 +1489,7 @@ function markCommentAsUnread(reportID: string | undefined, reportActionCreated:
const parameters: MarkAsUnreadParams = {
reportID,
lastReadTime,
reportActionID: reportAction?.reportActionID,
};

API.write(WRITE_COMMANDS.MARK_AS_UNREAD, parameters, {optimisticData});
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/report/ContextMenu/ContextMenuActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ const ContextMenuActions: ContextMenuAction[] = [
successIcon: Expensicons.Checkmark,
shouldShow: ({type, isUnreadChat}) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION || (type === CONST.CONTEXT_MENU_TYPES.REPORT && !isUnreadChat),
onPress: (closePopover, {reportAction, reportID}) => {
markCommentAsUnread(reportID, reportAction?.created);
markCommentAsUnread(reportID, reportAction);
if (closePopover) {
hideContextMenu(true, ReportActionComposeFocusManager.focus);
}
Expand Down
6 changes: 3 additions & 3 deletions tests/actions/ReportTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ describe('actions/Report', () => {

// When the user manually marks a message as "unread"
jest.advanceTimersByTime(10);
Report.markCommentAsUnread(REPORT_ID, reportActionCreatedDate);
Report.markCommentAsUnread(REPORT_ID, reportActions['1']);
return waitForBatchedUpdates();
})
.then(() => {
Expand Down Expand Up @@ -443,13 +443,13 @@ describe('actions/Report', () => {
expect(ReportUtils.isUnread(report, undefined)).toBe(false);

// When the user manually marks a message as "unread"
Report.markCommentAsUnread(REPORT_ID, reportActionCreatedDate);
Report.markCommentAsUnread(REPORT_ID, reportActions[400]);
return waitForBatchedUpdates();
})
.then(() => {
// Then we should expect the report to be to be unread
expect(ReportUtils.isUnread(report, undefined)).toBe(true);
expect(report?.lastReadTime).toBe(DateUtils.subtractMillisecondsFromDateTime(reportActionCreatedDate, 1));
expect(report?.lastReadTime).toBe(DateUtils.subtractMillisecondsFromDateTime(reportActions[400].created, 1));

// If the user deletes the last comment after the lastReadTime the lastMessageText will reflect the new last comment
Report.deleteReportComment(REPORT_ID, {...reportActions[400]});
Expand Down
53 changes: 27 additions & 26 deletions tests/ui/UnreadIndicatorsTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,26 @@ const USER_C_ACCOUNT_ID = 3;
const USER_C_EMAIL = 'user_c@test.com';
let reportAction3CreatedDate: string;
let reportAction9CreatedDate: string;
const TEN_MINUTES_AGO = subMinutes(new Date(), 10);
const createdReportActionID = rand64().toString();
const createdReportAction = {
actionName: CONST.REPORT.ACTIONS.TYPE.CREATED,
automatic: false,
created: format(TEN_MINUTES_AGO, CONST.DATE.FNS_DB_FORMAT_STRING),
reportActionID: createdReportActionID,
message: [
{
style: 'strong',
text: '__FAKE__',
type: 'TEXT',
},
{
style: 'normal',
text: 'created this report',
type: 'TEXT',
},
],
};

/**
* Sets up a test with a logged in user that has one unread chat from another user. Returns the <App/> test instance.
Expand All @@ -127,7 +147,6 @@ function signInAndGetAppWithUnreadChat(): Promise<void> {
return waitForBatchedUpdates();
})
.then(async () => {
const TEN_MINUTES_AGO = subMinutes(new Date(), 10);
reportAction3CreatedDate = format(addSeconds(TEN_MINUTES_AGO, 30), CONST.DATE.FNS_DB_FORMAT_STRING);
reportAction9CreatedDate = format(addSeconds(TEN_MINUTES_AGO, 90), CONST.DATE.FNS_DB_FORMAT_STRING);

Expand All @@ -145,26 +164,8 @@ function signInAndGetAppWithUnreadChat(): Promise<void> {
lastActorAccountID: USER_B_ACCOUNT_ID,
type: CONST.REPORT.TYPE.CHAT,
});
const createdReportActionID = rand64().toString();
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID}`, {
[createdReportActionID]: {
actionName: CONST.REPORT.ACTIONS.TYPE.CREATED,
automatic: false,
created: format(TEN_MINUTES_AGO, CONST.DATE.FNS_DB_FORMAT_STRING),
reportActionID: createdReportActionID,
message: [
{
style: 'strong',
text: '__FAKE__',
type: 'TEXT',
},
{
style: 'normal',
text: 'created this report',
type: 'TEXT',
},
],
},
[createdReportActionID]: createdReportAction,
1: TestHelper.buildTestReportComment(format(addSeconds(TEN_MINUTES_AGO, 10), CONST.DATE.FNS_DB_FORMAT_STRING), USER_B_ACCOUNT_ID, '1'),
2: TestHelper.buildTestReportComment(format(addSeconds(TEN_MINUTES_AGO, 20), CONST.DATE.FNS_DB_FORMAT_STRING), USER_B_ACCOUNT_ID, '2'),
3: TestHelper.buildTestReportComment(reportAction3CreatedDate, USER_B_ACCOUNT_ID, '3'),
Expand Down Expand Up @@ -292,7 +293,7 @@ describe('Unread Indicators', () => {
const NEW_REPORT_ID = '2';
const NEW_REPORT_CREATED_DATE = subSeconds(new Date(), 5);
const NEW_REPORT_FIST_MESSAGE_CREATED_DATE = addSeconds(NEW_REPORT_CREATED_DATE, 1);
const createdReportActionID = rand64();
const createdReportActionIDLocal = rand64();
const commentReportActionID = rand64();
PusherHelper.emitOnyxUpdate([
{
Expand All @@ -316,11 +317,11 @@ describe('Unread Indicators', () => {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${NEW_REPORT_ID}`,
value: {
[createdReportActionID]: {
[createdReportActionIDLocal]: {
actionName: CONST.REPORT.ACTIONS.TYPE.CREATED,
automatic: false,
created: format(NEW_REPORT_CREATED_DATE, CONST.DATE.FNS_DB_FORMAT_STRING),
reportActionID: createdReportActionID,
reportActionID: createdReportActionIDLocal,
},
[commentReportActionID]: {
actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT,
Expand Down Expand Up @@ -386,7 +387,7 @@ describe('Unread Indicators', () => {
.then(() => {
// It's difficult to trigger marking a report comment as unread since we would have to mock the long press event and then
// another press on the context menu item so we will do it via the action directly and then test if the UI has updated properly
markCommentAsUnread(REPORT_ID, reportAction3CreatedDate);
markCommentAsUnread(REPORT_ID, createdReportAction);
return waitForBatchedUpdates();
})
.then(() => {
Expand Down Expand Up @@ -484,7 +485,7 @@ describe('Unread Indicators', () => {
expect(unreadIndicator).toHaveLength(0);

// Mark a previous comment as unread and verify the unread action indicator returns
markCommentAsUnread(REPORT_ID, reportAction9CreatedDate);
markCommentAsUnread(REPORT_ID, createdReportAction);
return waitForBatchedUpdates();
})
.then(() => {
Expand Down Expand Up @@ -566,7 +567,7 @@ describe('Unread Indicators', () => {
const firstNewReportAction = reportActions ? lastItem(reportActions) : undefined;

if (firstNewReportAction) {
markCommentAsUnread(REPORT_ID, firstNewReportAction?.created);
markCommentAsUnread(REPORT_ID, firstNewReportAction);

await waitForBatchedUpdates();

Expand Down