Skip to content

Commit

Permalink
Merge pull request #44955 from software-mansion-labs/fix-useLastAcces…
Browse files Browse the repository at this point in the history
…sedReportID

perf: remove `useLastAccessedReportID` hook and call `findLastAccessedReport` only when needed
  • Loading branch information
roryabraham authored Jul 9, 2024
2 parents bf785d9 + 9c4741b commit 7bbb3fb
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 188 deletions.
148 changes: 0 additions & 148 deletions src/hooks/useLastAccessedReportID.ts

This file was deleted.

41 changes: 27 additions & 14 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,26 @@ Onyx.connect({
},
});

let allReportMetadata: OnyxCollection<ReportMetadata>;
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_METADATA,
waitForCollectionCallback: true,
callback: (value) => {
if (!value) {
return;
}
allReportMetadata = value;
},
});

let isFirstTimeNewExpensifyUser = false;
Onyx.connect({
key: ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER,
callback: (value) => {
isFirstTimeNewExpensifyUser = value ?? false;
},
});

function getCurrentUserAvatar(): AvatarSource | undefined {
return currentUserPersonalDetails?.avatar;
}
Expand Down Expand Up @@ -1150,30 +1170,23 @@ function hasExpensifyGuidesEmails(accountIDs: number[]): boolean {
return accountIDs.some((accountID) => Str.extractEmailDomain(allPersonalDetails?.[accountID]?.login ?? '') === CONST.EMAIL.GUIDES_DOMAIN);
}

function findLastAccessedReport(
reports: OnyxCollection<Report>,
ignoreDomainRooms: boolean,
policies: OnyxCollection<Policy>,
isFirstTimeNewExpensifyUser: boolean,
openOnAdminRoom = false,
reportMetadata: OnyxCollection<ReportMetadata> = {},
policyID?: string,
policyMemberAccountIDs: number[] = [],
excludeReportID?: string,
): OnyxEntry<Report> {
function findLastAccessedReport(ignoreDomainRooms: boolean, openOnAdminRoom = false, policyID?: string, excludeReportID?: string): OnyxEntry<Report> {
// If it's the user's first time using New Expensify, then they could either have:
// - just a Concierge report, if so we'll return that
// - their Concierge report, and a separate report that must have deeplinked them to the app before they created their account.
// If it's the latter, we'll use the deeplinked report over the Concierge report,
// since the Concierge report would be incorrectly selected over the deep-linked report in the logic below.

let reportsValues = Object.values(reports ?? {});
const policyMemberAccountIDs = PolicyUtils.getPolicyEmployeeListByIdWithoutCurrentUser(allPolicies, policyID, currentUserAccountID);

const allReports = ReportConnection.getAllReports();
let reportsValues = Object.values(allReports ?? {});

if (!!policyID || policyMemberAccountIDs.length > 0) {
reportsValues = filterReportsByPolicyIDAndMemberAccountIDs(reportsValues, policyMemberAccountIDs, policyID);
}

let sortedReports = sortReportsByLastRead(reportsValues, reportMetadata);
let sortedReports = sortReportsByLastRead(reportsValues, allReportMetadata);

let adminReport: OnyxEntry<Report>;
if (openOnAdminRoom) {
Expand All @@ -1197,7 +1210,7 @@ function findLastAccessedReport(
if (
ignoreDomainRooms &&
isDomainRoom(report) &&
getPolicyType(report, policies) !== CONST.POLICY.TYPE.FREE &&
getPolicyType(report, allPolicies) !== CONST.POLICY.TYPE.FREE &&
!hasExpensifyGuidesEmails(Object.keys(report?.participants ?? {}).map(Number))
) {
return false;
Expand Down
20 changes: 1 addition & 19 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ import type {
RecentlyUsedReportFields,
ReportAction,
ReportActionReactions,
ReportMetadata,
ReportUserIsTyping,
} from '@src/types/onyx';
import type {Decision} from '@src/types/onyx/OriginalMessage';
Expand Down Expand Up @@ -222,13 +221,6 @@ Onyx.connect({
},
});

let reportMetadata: OnyxCollection<ReportMetadata> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_METADATA,
waitForCollectionCallback: true,
callback: (value) => (reportMetadata = value),
});

const typingWatchTimers: Record<string, NodeJS.Timeout> = {};

let reportIDDeeplinkedFromOldDot: string | undefined;
Expand Down Expand Up @@ -2581,17 +2573,7 @@ function getCurrentUserAccountID(): number {
}

function navigateToMostRecentReport(currentReport: OnyxEntry<Report>) {
const lastAccessedReportID = ReportUtils.findLastAccessedReport(
ReportConnection.getAllReports(),
false,
undefined,
false,
false,
reportMetadata,
undefined,
[],
currentReport?.reportID,
)?.reportID;
const lastAccessedReportID = ReportUtils.findLastAccessedReport(false, false, undefined, currentReport?.reportID)?.reportID;

if (lastAccessedReportID) {
const lastAccessedReportRoute = ROUTES.REPORT_WITH_ID.getRoute(lastAccessedReportID ?? '-1');
Expand Down
11 changes: 7 additions & 4 deletions src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ import ScreenWrapper from '@components/ScreenWrapper';
import TaskHeaderActionButton from '@components/TaskHeaderActionButton';
import type {CurrentReportIDContextValue} from '@components/withCurrentReportID';
import withCurrentReportID from '@components/withCurrentReportID';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import useAppFocusEvent from '@hooks/useAppFocusEvent';
import useDeepCompareRef from '@hooks/useDeepCompareRef';
import useIsReportOpenInRHP from '@hooks/useIsReportOpenInRHP';
import useLastAccessedReportID from '@hooks/useLastAccessedReportID';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import usePermissions from '@hooks/usePermissions';
import usePrevious from '@hooks/usePrevious';
import useThemeStyles from '@hooks/useThemeStyles';
import useViewportOffsetTop from '@hooks/useViewportOffsetTop';
Expand Down Expand Up @@ -146,10 +147,12 @@ function ReportScreen({
const prevIsFocused = usePrevious(isFocused);
const firstRenderRef = useRef(true);
const flatListRef = useRef<FlatList>(null);
const {canUseDefaultRooms} = usePermissions();
const reactionListRef = useRef<ReactionListRef>(null);
const {isOffline} = useNetwork();
const isReportOpenInRHP = useIsReportOpenInRHP();
const {isSmallScreenWidth} = useWindowDimensions();
const {activeWorkspaceID} = useActiveWorkspace();
const shouldUseNarrowLayout = isSmallScreenWidth || isReportOpenInRHP;

const [modal] = useOnyx(ONYXKEYS.MODAL);
Expand All @@ -169,8 +172,6 @@ function ReportScreen({
const isLoadingReportOnyx = isLoadingOnyxValue(reportResult);
const permissions = useDeepCompareRef(reportOnyx?.permissions);

// Check if there's a reportID in the route. If not, set it to the last accessed reportID
const lastAccessedReportID = useLastAccessedReportID(!!route.params.openOnAdminRoom);
useEffect(() => {
// Don't update if there is a reportID in the params already
if (route.params.reportID) {
Expand All @@ -182,6 +183,8 @@ function ReportScreen({
return;
}

const lastAccessedReportID = ReportUtils.findLastAccessedReport(!canUseDefaultRooms, !!route.params.openOnAdminRoom, activeWorkspaceID)?.reportID;

// It's possible that reports aren't fully loaded yet
// in that case the reportID is undefined
if (!lastAccessedReportID) {
Expand All @@ -190,7 +193,7 @@ function ReportScreen({

Log.info(`[ReportScreen] no reportID found in params, setting it to lastAccessedReportID: ${lastAccessedReportID}`);
navigation.setParams({reportID: lastAccessedReportID});
}, [lastAccessedReportID, navigation, route]);
}, [activeWorkspaceID, canUseDefaultRooms, navigation, route]);

/**
* Create a lightweight Report so as to keep the re-rendering as light as possible by
Expand Down
12 changes: 9 additions & 3 deletions tests/perf-test/ReportUtils.perf-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ describe('ReportUtils', () => {
keys: ONYXKEYS,
safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
});
});

Onyx.multiSet({
beforeEach(async () => {
await Onyx.multiSet({
...mockedPoliciesMap,
...mockedReportsMap,
});
Expand All @@ -55,13 +57,17 @@ describe('ReportUtils', () => {

test('[ReportUtils] findLastAccessedReport on 2k reports and policies', async () => {
const ignoreDomainRooms = true;
const isFirstTimeNewExpensifyUser = true;
const reports = getMockedReports(2000);
const policies = getMockedPolicies(2000);
const openOnAdminRoom = true;

await Onyx.multiSet({
[ONYXKEYS.COLLECTION.REPORT]: reports,
[ONYXKEYS.COLLECTION.POLICY]: policies,
});

await waitForBatchedUpdates();
await measureFunction(() => ReportUtils.findLastAccessedReport(reports, ignoreDomainRooms, policies, isFirstTimeNewExpensifyUser, openOnAdminRoom));
await measureFunction(() => ReportUtils.findLastAccessedReport(ignoreDomainRooms, openOnAdminRoom));
});

test('[ReportUtils] canDeleteReportAction on 1k reports and policies', async () => {
Expand Down

0 comments on commit 7bbb3fb

Please sign in to comment.