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 deep linking to reports after signing in #43307

Merged
merged 14 commits into from
Jun 23, 2024
61 changes: 52 additions & 9 deletions src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ function ReportScreen({
canEvict: false,
selector: (parentReportActions) => getParentReportAction(parentReportActions, reportOnyx?.parentReportActionID ?? ''),
});
const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP);
const wasLoadingApp = usePrevious(isLoadingApp);
const finishedLoadingApp = wasLoadingApp && !isLoadingApp;

const isLoadingReportOnyx = isLoadingOnyxValue(reportResult);
const permissions = useDeepCompareRef(reportOnyx?.permissions);
Expand Down Expand Up @@ -378,7 +381,7 @@ function ReportScreen({
return reportIDFromRoute !== '' && !!report.reportID && !isTransitioning;
}, [report, reportIDFromRoute]);

const isLoading = !reportIDFromRoute || (!isSidebarLoaded && !isReportOpenInRHP) || PersonalDetailsUtils.isPersonalDetailsEmpty();
const isLoading = isLoadingApp ?? (!reportIDFromRoute || (!isSidebarLoaded && !isReportOpenInRHP) || PersonalDetailsUtils.isPersonalDetailsEmpty());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, This caused a regression where the list doesn't scroll to the linked report action. This happens because isLoadingApp is false and that’s why the ?? operator doesn’t execute the right hand side. So the solution is to use || operator, so that the right hand side is evaluated if LHS is false. This was fixed here.

const shouldShowSkeleton =
!isLinkedMessageAvailable &&
(isLinkingToMessage ||
Expand All @@ -388,14 +391,30 @@ function ReportScreen({
(!!reportActionIDFromRoute && reportMetadata?.isLoadingInitialReportActions));
const shouldShowReportActionList = isCurrentReportLoadedFromOnyx && !isLoading;
const currentReportIDFormRoute = route.params?.reportID;

// eslint-disable-next-line rulesdir/no-negated-variables
const shouldShowNotFoundPage = useMemo(
(): boolean =>
(!wasReportAccessibleRef.current && !firstRenderRef.current && !report.reportID && !isOptimisticDelete && !reportMetadata?.isLoadingInitialReportActions && !userLeavingStatus) ||
shouldHideReport ||
(!!currentReportIDFormRoute && !ReportUtils.isValidReportIDFromPath(currentReportIDFormRoute)),
[report.reportID, isOptimisticDelete, reportMetadata?.isLoadingInitialReportActions, userLeavingStatus, shouldHideReport, currentReportIDFormRoute],
);
const shouldShowNotFoundPage = useMemo((): boolean => {
// Wait until we're sure the app is done loading (needs to be a strict equality check since it's undefined initially)
if (isLoadingApp !== false) {
return false;
}

// If we just finished loading the app, we still need to try fetching the report. Wait until that's done before
// showing the Not Found page
if (finishedLoadingApp) {
return false;
}

if (!wasReportAccessibleRef.current && !firstRenderRef.current && !report.reportID && !isOptimisticDelete && !reportMetadata?.isLoadingInitialReportActions && !userLeavingStatus) {
return true;
}

if (shouldHideReport) {
return true;
}

return !!currentReportIDFormRoute && !ReportUtils.isValidReportIDFromPath(currentReportIDFormRoute);
}, [isLoadingApp, finishedLoadingApp, report.reportID, isOptimisticDelete, reportMetadata?.isLoadingInitialReportActions, userLeavingStatus, shouldHideReport, currentReportIDFormRoute]);

const fetchReport = useCallback(() => {
Report.openReport(reportIDFromRoute, reportActionIDFromRoute);
Expand Down Expand Up @@ -425,12 +444,24 @@ function ReportScreen({
return;
}

/**
* Since OpenReport is a write, the response from OpenReport will get dropped while the app is
* still loading. This usually happens when signing in and deeplinking to a report. Instead,
* we'll fetch the report after the app finishes loading.
*
* This needs to be a strict equality check since isLoadingApp is initially undefined until the
* value is loaded from Onyx
*/
if (isLoadingApp !== false) {
return;
}

if (!shouldFetchReport(report)) {
return;
}

fetchReport();
}, [report, fetchReport, reportIDFromRoute]);
}, [report, fetchReport, reportIDFromRoute, isLoadingApp]);

const dismissBanner = useCallback(() => {
setIsBannerVisible(false);
Expand Down Expand Up @@ -615,6 +646,18 @@ function ReportScreen({
});
}, [reportMetadata?.isLoadingInitialReportActions]);

// If we deeplinked to the report after signing in, we need to fetch the report after the app is done loading
useEffect(() => {
if (!finishedLoadingApp) {
return;
}

fetchReportIfNeeded();

// This should only run once when the app is done loading
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [finishedLoadingApp]);

const navigateToEndOfReport = useCallback(() => {
Navigation.setParams({reportActionID: ''});
fetchReport();
Expand Down
Loading