Skip to content

Commit

Permalink
Merge pull request #43083 from Expensify/Rory-FixCrashInReportFooter
Browse files Browse the repository at this point in the history
Fix console error in ReportFooter
  • Loading branch information
luacmartins authored Jun 7, 2024
2 parents a9b15b1 + 1a1adc9 commit a1ed1ab
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 50 deletions.
2 changes: 2 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,8 @@ type OnyxValuesMapping = {
[ONYXKEYS.BETAS]: OnyxTypes.Beta[];
[ONYXKEYS.NVP_PRIORITY_MODE]: ValueOf<typeof CONST.PRIORITY_MODE>;
[ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE]: OnyxTypes.BlockedFromConcierge;

// The value of this nvp is a string representation of the date when the block expires, or an empty string if the user is not blocked
[ONYXKEYS.NVP_BLOCKED_FROM_CHAT]: string;
[ONYXKEYS.NVP_PRIVATE_PUSH_NOTIFICATION_ID]: string;
[ONYXKEYS.NVP_TRY_FOCUS_MODE]: boolean;
Expand Down
91 changes: 41 additions & 50 deletions src/pages/home/report/ReportFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import lodashIsEqual from 'lodash/isEqual';
import React, {memo, useCallback} from 'react';
import {Keyboard, View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import AnonymousReportFooter from '@components/AnonymousReportFooter';
import ArchivedReportFooter from '@components/ArchivedReportFooter';
Expand All @@ -15,6 +15,7 @@ import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import Log from '@libs/Log';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
Expand All @@ -29,18 +30,7 @@ import type {EmptyObject} from '@src/types/utils/EmptyObject';
import ReportActionCompose from './ReportActionCompose/ReportActionCompose';
import SystemChatReportFooterMessage from './SystemChatReportFooterMessage';

type ReportFooterOnyxProps = {
/** Whether to show the compose input */
shouldShowComposeInput: OnyxEntry<boolean>;

/** Session info for the currently logged in user. */
session: OnyxEntry<OnyxTypes.Session>;

/** Whether user is blocked from chat. */
blockedFromChat: OnyxEntry<string>;
};

type ReportFooterProps = ReportFooterOnyxProps & {
type ReportFooterProps = {
/** Report object for the current report */
report?: OnyxTypes.Report;

Expand Down Expand Up @@ -79,33 +69,47 @@ type ReportFooterProps = ReportFooterOnyxProps & {
function ReportFooter({
lastReportAction,
pendingAction,
session,
report = {reportID: '0'},
reportMetadata,
reportNameValuePairs,
policy,
shouldShowComposeInput = false,
isEmptyChat = true,
isReportReadyForDisplay = true,
listHeight = 0,
isComposerFullSize = false,
blockedFromChat,
onComposerBlur,
onComposerFocus,
}: ReportFooterProps) {
const styles = useThemeStyles();
const {isOffline} = useNetwork();
const {translate} = useLocalize();
const {windowWidth, isSmallScreenWidth} = useWindowDimensions();

const [shouldShowComposeInput] = useOnyx(ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT, {initialValue: false});
const [isAnonymousUser] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.authTokenType === CONST.AUTH_TOKEN_TYPES.ANONYMOUS});
const [isBlockedFromChat] = useOnyx(ONYXKEYS.NVP_BLOCKED_FROM_CHAT, {
selector: (dateString) => {
if (!dateString) {
return false;
}
try {
return new Date(dateString) >= new Date();
} catch (error) {
// If the NVP is malformed, we'll assume the user is not blocked from chat. This is not expected, so if it happens we'll log an alert.
Log.alert(`[${CONST.ERROR.ENSURE_BUGBOT}] Found malformed ${ONYXKEYS.NVP_BLOCKED_FROM_CHAT} nvp`, dateString);
return false;
}
},
});

const chatFooterStyles = {...styles.chatFooter, minHeight: !isOffline ? CONST.CHAT_FOOTER_MIN_HEIGHT : 0};
const isArchivedRoom = ReportUtils.isArchivedRoom(report, reportNameValuePairs);
const isAnonymousUser = session?.authTokenType === CONST.AUTH_TOKEN_TYPES.ANONYMOUS;

const isSmallSizeLayout = windowWidth - (isSmallScreenWidth ? 0 : variables.sideBarWidth) < variables.anonymousReportFooterBreakpoint;

// If a user just signed in and is viewing a public report, optimistically show the composer while loading the report, since they will have write access when the response comes back.
const showComposerOptimistically = !isAnonymousUser && ReportUtils.isPublicRoom(report) && reportMetadata?.isLoadingInitialReportActions;
const hideComposer = (!ReportUtils.canUserPerformWriteAction(report, reportNameValuePairs) && !showComposerOptimistically) || blockedFromChat;
const shouldShowComposerOptimistically = !isAnonymousUser && ReportUtils.isPublicRoom(report) && !!reportMetadata?.isLoadingInitialReportActions;
const shouldHideComposer = (!ReportUtils.canUserPerformWriteAction(report, reportNameValuePairs) && !shouldShowComposerOptimistically) || isBlockedFromChat;
const canWriteInReport = ReportUtils.canWriteInReport(report);
const isSystemChat = ReportUtils.isSystemChat(report);
const isAdminsOnlyPostingRoom = ReportUtils.isAdminsOnlyPostingRoom(report);
Expand Down Expand Up @@ -166,7 +170,7 @@ function ReportFooter({

return (
<>
{hideComposer && (
{shouldHideComposer && (
<View
style={[
styles.chatFooter,
Expand All @@ -181,20 +185,22 @@ function ReportFooter({
/>
)}
{isArchivedRoom && <ArchivedReportFooter report={report} />}
{!isArchivedRoom && blockedFromChat && <BlockedReportFooter />}
{!isArchivedRoom && isBlockedFromChat && <BlockedReportFooter />}
{!isAnonymousUser && !canWriteInReport && isSystemChat && <SystemChatReportFooterMessage />}
{isAdminsOnlyPostingRoom && !isUserPolicyAdmin && !isArchivedRoom && !isAnonymousUser && !blockedFromChat && (
{isAdminsOnlyPostingRoom && !isUserPolicyAdmin && !isArchivedRoom && !isAnonymousUser && !isBlockedFromChat && (
<Banner
containerStyles={[styles.chatFooterBanner]}
text={translate('adminOnlyCanPost')}
icon={Expensicons.Lightbulb}
shouldShowIcon
/>
)}
{!isSmallScreenWidth && <View style={styles.offlineIndicatorRow}>{hideComposer && <OfflineIndicator containerStyles={[styles.chatItemComposeSecondaryRow]} />}</View>}
{!isSmallScreenWidth && (
<View style={styles.offlineIndicatorRow}>{shouldHideComposer && <OfflineIndicator containerStyles={[styles.chatItemComposeSecondaryRow]} />}</View>
)}
</View>
)}
{!hideComposer && (!!shouldShowComposeInput || !isSmallScreenWidth) && (
{!shouldHideComposer && (shouldShowComposeInput || !isSmallScreenWidth) && (
<View style={[chatFooterStyles, isComposerFullSize && styles.chatFooterFullCompose]}>
<SwipeableView onSwipeDown={Keyboard.dismiss}>
<ReportActionCompose
Expand All @@ -219,30 +225,15 @@ function ReportFooter({

ReportFooter.displayName = 'ReportFooter';

export default withOnyx<ReportFooterProps, ReportFooterOnyxProps>({
shouldShowComposeInput: {
key: ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT,
initialValue: false,
},
session: {
key: ONYXKEYS.SESSION,
},
blockedFromChat: {
key: ONYXKEYS.NVP_BLOCKED_FROM_CHAT,
},
})(
memo(
ReportFooter,
(prevProps, nextProps) =>
lodashIsEqual(prevProps.report, nextProps.report) &&
prevProps.pendingAction === nextProps.pendingAction &&
prevProps.listHeight === nextProps.listHeight &&
prevProps.isComposerFullSize === nextProps.isComposerFullSize &&
prevProps.isEmptyChat === nextProps.isEmptyChat &&
prevProps.lastReportAction === nextProps.lastReportAction &&
prevProps.shouldShowComposeInput === nextProps.shouldShowComposeInput &&
prevProps.isReportReadyForDisplay === nextProps.isReportReadyForDisplay &&
lodashIsEqual(prevProps.session, nextProps.session) &&
lodashIsEqual(prevProps.reportMetadata, nextProps.reportMetadata),
),
export default memo(
ReportFooter,
(prevProps, nextProps) =>
lodashIsEqual(prevProps.report, nextProps.report) &&
prevProps.pendingAction === nextProps.pendingAction &&
prevProps.listHeight === nextProps.listHeight &&
prevProps.isComposerFullSize === nextProps.isComposerFullSize &&
prevProps.isEmptyChat === nextProps.isEmptyChat &&
prevProps.lastReportAction === nextProps.lastReportAction &&
prevProps.isReportReadyForDisplay === nextProps.isReportReadyForDisplay &&
lodashIsEqual(prevProps.reportMetadata, nextProps.reportMetadata),
);

0 comments on commit a1ed1ab

Please sign in to comment.