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: App crashes when clicking on search icon while app is loading #53521

Merged
merged 6 commits into from
Dec 11, 2024
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
13 changes: 8 additions & 5 deletions src/components/OptionListContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import usePrevious from '@hooks/usePrevious';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import type {OptionList} from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetails, Report} from '@src/types/onyx';
import {usePersonalDetails} from './OnyxProvider';
Expand Down Expand Up @@ -35,7 +34,7 @@ const OptionsListContext = createContext<OptionsListContextProps>({
resetOptions: () => {},
});

const isEqualPersonalDetail = (prevPersonalDetail: PersonalDetails | null, personalDetail: PersonalDetails | null) =>
const isEqualPersonalDetail = (prevPersonalDetail: PersonalDetails, personalDetail: PersonalDetails) =>
prevPersonalDetail?.firstName === personalDetail?.firstName &&
prevPersonalDetail?.lastName === personalDetail?.lastName &&
prevPersonalDetail?.login === personalDetail?.login &&
Expand All @@ -49,7 +48,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) {
});
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);

const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT;
const personalDetails = usePersonalDetails();
const prevPersonalDetails = usePrevious(personalDetails);

/**
Expand Down Expand Up @@ -83,16 +82,20 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) {
return;
}

if (!personalDetails) {
return;
}

const newReportOptions: Array<{
replaceIndex: number;
newReportOption: OptionsListUtils.SearchOption<Report>;
}> = [];

Object.keys(personalDetails).forEach((accountID) => {
const prevPersonalDetail = prevPersonalDetails?.[accountID];
const personalDetail = personalDetails?.[accountID];
const personalDetail = personalDetails[accountID];

if (isEqualPersonalDetail(prevPersonalDetail, personalDetail)) {
if (prevPersonalDetail && personalDetail && isEqualPersonalDetail(prevPersonalDetail, personalDetail)) {
return;
}

Expand Down
30 changes: 7 additions & 23 deletions src/components/ReportActionItem/TaskView.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import React, {useEffect} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import Checkbox from '@components/Checkbox';
import Hoverable from '@components/Hoverable';
import Icon from '@components/Icon';
Expand All @@ -26,31 +24,24 @@ import * as TaskUtils from '@libs/TaskUtils';
import * as Session from '@userActions/Session';
import * as Task from '@userActions/Task';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {PersonalDetailsList, Report} from '@src/types/onyx';
import type {Report} from '@src/types/onyx';

type TaskViewOnyxProps = {
/** All of the personal details for everyone */
personalDetails: OnyxEntry<PersonalDetailsList>;
type TaskViewProps = WithCurrentUserPersonalDetailsProps & {
/** The report currently being looked at */
report: Report;
};

type TaskViewProps = TaskViewOnyxProps &
WithCurrentUserPersonalDetailsProps & {
/** The report currently being looked at */
report: Report;
};

function TaskView({report, ...props}: TaskViewProps) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
useEffect(() => {
Task.setTaskReport(report);
}, [report]);

const personalDetails = usePersonalDetails();
const taskTitle = convertToLTR(report.reportName ?? '');
const assigneeTooltipDetails = ReportUtils.getDisplayNamesWithTooltips(
OptionsListUtils.getPersonalDetailsForAccountIDs(report.managerID ? [report.managerID] : [], props.personalDetails),
OptionsListUtils.getPersonalDetailsForAccountIDs(report.managerID ? [report.managerID] : [], personalDetails),
false,
);
const isCompleted = ReportUtils.isCompletedTaskReport(report);
Expand All @@ -59,7 +50,6 @@ function TaskView({report, ...props}: TaskViewProps) {
const canActionTask = Task.canActionTask(report, props.currentUserPersonalDetails.accountID);
const disableState = !canModifyTask;
const isDisableInteractive = !canModifyTask || !isOpen;
const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT;
const {translate} = useLocalize();

return (
Expand Down Expand Up @@ -190,10 +180,4 @@ function TaskView({report, ...props}: TaskViewProps) {

TaskView.displayName = 'TaskView';

const TaskViewWithOnyx = withOnyx<TaskViewProps, TaskViewOnyxProps>({
personalDetails: {
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
},
})(TaskView);

export default withCurrentUserPersonalDetails(TaskViewWithOnyx);
export default withCurrentUserPersonalDetails(TaskView);
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const getSubstitutionsKey = (filterKey: SearchFilterKey, value: string) => `${fi
*/
function buildSubstitutionsMap(
query: string,
personalDetails: OnyxTypes.PersonalDetailsList,
personalDetails: OnyxTypes.PersonalDetailsList | undefined,
reports: OnyxCollection<OnyxTypes.Report>,
allTaxRates: Record<string, string[]>,
): SubstitutionMap {
Expand Down
6 changes: 3 additions & 3 deletions src/components/createOnyxContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type CreateOnyxContext<TOnyxKey extends OnyxKey> = [
WithOnyxKey<TOnyxKey>,
ComponentType<Omit<ProviderPropsWithOnyx<TOnyxKey>, TOnyxKey>>,
React.Context<OnyxValue<TOnyxKey>>,
() => NonNullable<OnyxValue<TOnyxKey>>,
() => OnyxValue<TOnyxKey>,
];

export default <TOnyxKey extends OnyxKey>(onyxKeyName: TOnyxKey): CreateOnyxContext<TOnyxKey> => {
Expand All @@ -43,7 +43,7 @@ export default <TOnyxKey extends OnyxKey>(onyxKeyName: TOnyxKey): CreateOnyxCont
}

Provider.displayName = `${Str.UCFirst(onyxKeyName)}Provider`;

// eslint-disable-next-line
const ProviderWithOnyx = withOnyx<ProviderPropsWithOnyx<TOnyxKey>, ProviderOnyxProps<TOnyxKey>>({
[onyxKeyName]: {
key: onyxKeyName,
Expand Down Expand Up @@ -87,7 +87,7 @@ export default <TOnyxKey extends OnyxKey>(onyxKeyName: TOnyxKey): CreateOnyxCont
if (value === null) {
throw new Error(`useOnyxContext must be used within a OnyxProvider [key: ${onyxKeyName}]`);
}
return value as NonNullable<OnyxValue<TOnyxKey>>;
return value as OnyxValue<TOnyxKey>;
};

return [withOnyxKey, ProviderWithOnyx, Context, useOnyxContext];
Expand Down
8 changes: 4 additions & 4 deletions src/libs/SearchQueryUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ function buildFilterFormValuesFromQuery(
policyCategories: OnyxCollection<OnyxTypes.PolicyCategories>,
policyTags: OnyxCollection<OnyxTypes.PolicyTagLists>,
currencyList: OnyxTypes.CurrencyList,
personalDetails: OnyxTypes.PersonalDetailsList,
personalDetails: OnyxTypes.PersonalDetailsList | undefined,
cardList: OnyxTypes.CardList,
reports: OnyxCollection<OnyxTypes.Report>,
taxRates: Record<string, string[]>,
Expand Down Expand Up @@ -391,7 +391,7 @@ function buildFilterFormValuesFromQuery(
filtersForm[filterKey] = filterValues.filter((id) => reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`]?.reportID);
}
if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM || filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO) {
filtersForm[filterKey] = filterValues.filter((id) => personalDetails[id]);
filtersForm[filterKey] = filterValues.filter((id) => personalDetails && personalDetails[id]);
}
if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.CURRENCY) {
const validCurrency = new Set(Object.keys(currencyList));
Expand Down Expand Up @@ -488,7 +488,7 @@ function getPolicyIDFromSearchQuery(queryJSON: SearchQueryJSON) {
/**
* Returns the human-readable "pretty" string for a specified filter value.
*/
function getFilterDisplayValue(filterName: string, filterValue: string, personalDetails: OnyxTypes.PersonalDetailsList, reports: OnyxCollection<OnyxTypes.Report>) {
function getFilterDisplayValue(filterName: string, filterValue: string, personalDetails: OnyxTypes.PersonalDetailsList | undefined, reports: OnyxCollection<OnyxTypes.Report>) {
if (filterName === CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM || filterName === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO) {
// login can be an empty string
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
Expand Down Expand Up @@ -519,7 +519,7 @@ function getFilterDisplayValue(filterName: string, filterValue: string, personal
*/
function buildUserReadableQueryString(
queryJSON: SearchQueryJSON,
PersonalDetails: OnyxTypes.PersonalDetailsList,
PersonalDetails: OnyxTypes.PersonalDetailsList | undefined,
reports: OnyxCollection<OnyxTypes.Report>,
taxRates: Record<string, string[]>,
) {
Expand Down
4 changes: 2 additions & 2 deletions src/pages/RoomMembersPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function RoomMembersPage({report, policies}: RoomMembersPageProps) {
const [userSearchPhrase] = useOnyx(ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE);
const [searchValue, setSearchValue] = useState('');
const [didLoadRoomMembers, setDidLoadRoomMembers] = useState(false);
const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT;
const personalDetails = usePersonalDetails();
const policy = useMemo(() => policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID ?? ''}`], [policies, report?.policyID]);
const isPolicyExpenseChat = useMemo(() => ReportUtils.isPolicyExpenseChat(report), [report]);
const backTo = route.params.backTo;
Expand Down Expand Up @@ -212,7 +212,7 @@ function RoomMembersPage({report, policies}: RoomMembersPageProps) {
let result: ListItem[] = [];

participants.forEach((accountID) => {
const details = personalDetails[accountID];
const details = personalDetails?.[accountID];

// If search value is provided, filter out members that don't match the search value
if (!details || (searchValue.trim() && !OptionsListUtils.isSearchStringMatchUserDetails(details, searchValue))) {
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Search/AdvancedSearchFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ function getFilterCardDisplayTitle(filters: Partial<SearchAdvancedFiltersForm>,
: undefined;
}

function getFilterParticipantDisplayTitle(accountIDs: string[], personalDetails: PersonalDetailsList) {
const selectedPersonalDetails = accountIDs.map((id) => personalDetails[id]);
function getFilterParticipantDisplayTitle(accountIDs: string[], personalDetails: PersonalDetailsList | undefined) {
const selectedPersonalDetails = accountIDs.map((id) => personalDetails?.[id]);

return selectedPersonalDetails
.map((personalDetail) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ function ReportActionCompose({
const {isOffline} = useNetwork();
const actionButtonRef = useRef<View | HTMLDivElement | null>(null);
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT;
const personalDetails = usePersonalDetails();
const navigation = useNavigation();
const [blockedFromConcierge] = useOnyx(ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE);
const [shouldShowComposeInput = true] = useOnyx(ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT);
Expand Down Expand Up @@ -328,7 +328,7 @@ function ReportActionCompose({
// When we invite someone to a room they don't have the policy object, but we still want them to be able to mention other reports they are members of, so we only check if the policyID in the report is from a workspace
const isGroupPolicyReport = useMemo(() => !!report?.policyID && report.policyID !== CONST.POLICY.ID_FAKE, [report]);
const reportRecipientAcountIDs = ReportUtils.getReportRecipientAccountIDs(report, currentUserPersonalDetails.accountID);
const reportRecipient = personalDetails[reportRecipientAcountIDs[0]];
const reportRecipient = personalDetails?.[reportRecipientAcountIDs[0]];
const shouldUseFocusedColor = !isBlockedFromConcierge && !disabled && isFocused;

const hasReportRecipient = !isEmptyObject(reportRecipient);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function SuggestionMention(
{value, selection, setSelection, updateComment, isAutoSuggestionPickerLarge, measureParentContainerAndReportCursor, isComposerFocused, isGroupPolicyReport, policyID}: SuggestionProps,
ref: ForwardedRef<SuggestionsRef>,
) {
const personalDetails = usePersonalDetails() ?? CONST.EMPTY_OBJECT;
const personalDetails = usePersonalDetails();
const {translate, formatPhoneNumber} = useLocalize();
const [suggestionValues, setSuggestionValues] = useState(defaultSuggestionsValues);
const suggestionValuesRef = useRef(suggestionValues);
Expand All @@ -112,7 +112,7 @@ function SuggestionMention(
},
[currentReport],
);
const weightedPersonalDetails: PersonalDetailsList | SuggestionPersonalDetailsList = useMemo(() => {
const weightedPersonalDetails: PersonalDetailsList | SuggestionPersonalDetailsList | undefined = useMemo(() => {
const policyEmployeeAccountIDs = getPolicyEmployeeAccountIDs(policyID);
if (!ReportUtils.isGroupChat(currentReport) && !ReportUtils.doesReportBelongToWorkspace(currentReport, policyEmployeeAccountIDs, policyID)) {
return personalDetails;
Expand Down Expand Up @@ -264,7 +264,7 @@ function SuggestionMention(
);

const getUserMentionOptions = useCallback(
(personalDetailsParam: PersonalDetailsList | SuggestionPersonalDetailsList, searchValue = ''): Mention[] => {
(personalDetailsParam: PersonalDetailsList | SuggestionPersonalDetailsList | undefined, searchValue = ''): Mention[] => {
const suggestions = [];

if (CONST.AUTO_COMPLETE_SUGGESTER.HERE_TEXT.includes(searchValue.toLowerCase())) {
Expand Down
4 changes: 2 additions & 2 deletions src/pages/home/report/ReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ function ReportActionItem({
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- This is needed to prevent the app from crashing when the app is using imported state.
const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID || '-1'}`);
const StyleUtils = useStyleUtils();
const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT;
const personalDetails = usePersonalDetails();
const [isContextMenuActive, setIsContextMenuActive] = useState(() => ReportActionContextMenu.isActiveReportAction(action.reportActionID));
const [isEmojiPickerActive, setIsEmojiPickerActive] = useState<boolean | undefined>();
const [isPaymentMethodPopoverActive, setIsPaymentMethodPopoverActive] = useState<boolean | undefined>();
Expand Down Expand Up @@ -603,7 +603,7 @@ function ReportActionItem({
);
} else if (ReportActionsUtils.isReimbursementQueuedAction(action)) {
const linkedReport = ReportUtils.isChatThread(report) ? parentReport : report;
const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails[linkedReport?.ownerAccountID ?? -1]);
const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(personalDetails?.[linkedReport?.ownerAccountID ?? -1]);
const paymentType = ReportActionsUtils.getOriginalMessage(action)?.paymentType ?? '';

const missingPaymentMethod = ReportUtils.getIndicatedMissingPaymentMethod(userWallet, linkedReport?.reportID ?? '-1', action);
Expand Down
8 changes: 4 additions & 4 deletions src/pages/home/report/ReportActionItemSingle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,16 @@ function ReportActionItemSingle({
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
const personalDetails = usePersonalDetails() ?? CONST.EMPTY_OBJECT;
const personalDetails = usePersonalDetails();
const policy = usePolicy(report?.policyID);
const delegatePersonalDetails = personalDetails[action?.delegateAccountID ?? ''];
const delegatePersonalDetails = personalDetails?.[action?.delegateAccountID ?? ''];
const ownerAccountID = iouReport?.ownerAccountID ?? action?.childOwnerAccountID;
const isReportPreviewAction = action?.actionName === CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW;
const actorAccountID = ReportUtils.getReportActionActorAccountID(action, iouReport, report);
const [invoiceReceiverPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report?.invoiceReceiver && 'policyID' in report.invoiceReceiver ? report.invoiceReceiver.policyID : -1}`);

let displayName = ReportUtils.getDisplayNameForParticipant(actorAccountID);
const {avatar, login, pendingFields, status, fallbackIcon} = personalDetails[actorAccountID ?? -1] ?? {};
const {avatar, login, pendingFields, status, fallbackIcon} = personalDetails?.[actorAccountID ?? -1] ?? {};
const accountOwnerDetails = getPersonalDetailByEmail(login ?? '');
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
let actorHint = (login || (displayName ?? '')).replace(CONST.REGEX.MERGED_ACCOUNT_PREFIX, '');
Expand All @@ -108,7 +108,7 @@ function ReportActionItemSingle({
actorHint = displayName;
avatarSource = ReportUtils.getWorkspaceIcon(report, policy).source;
avatarId = report?.policyID;
} else if (action?.delegateAccountID && personalDetails[action?.delegateAccountID]) {
} else if (action?.delegateAccountID && personalDetails?.[action?.delegateAccountID]) {
displayName = delegatePersonalDetails?.displayName ?? '';
avatarSource = delegatePersonalDetails?.avatar;
avatarId = delegatePersonalDetails?.accountID;
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/report/ReportActionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ function ReportActionsList({
parentReportActionForTransactionThread,
}: ReportActionsListProps) {
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const personalDetailsList = usePersonalDetails() || CONST.EMPTY_OBJECT;
const personalDetailsList = usePersonalDetails();
const styles = useThemeStyles();
const {translate} = useLocalize();
const {windowHeight} = useWindowDimensions();
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/report/ReportFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ function ReportFooter({
let assigneeChatReport;
if (mentionWithDomain) {
if (isValidMention) {
assignee = Object.values(allPersonalDetails).find((value) => value?.login === mentionWithDomain) ?? undefined;
assignee = Object.values(allPersonalDetails ?? {}).find((value) => value?.login === mentionWithDomain) ?? undefined;
if (!Object.keys(assignee ?? {}).length) {
const assigneeAccountID = UserUtils.generateAccountID(mentionWithDomain);
const optimisticDataForNewAssignee = Task.setNewOptimisticAssignee(mentionWithDomain, assigneeAccountID);
Expand Down
2 changes: 1 addition & 1 deletion src/pages/iou/request/MoneyRequestAttendeeSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde
const [betas] = useOnyx(ONYXKEYS.BETAS);
const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
const session = useSession();
const isCurrentUserAttendee = attendees.some((attendee) => attendee.accountID === session.accountID);
const isCurrentUserAttendee = attendees.some((attendee) => attendee.accountID === session?.accountID);
const [recentAttendees] = useOnyx(ONYXKEYS.NVP_RECENT_ATTENDEES);
const policy = usePolicy(activePolicyID);
const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function IOURequestStepConfirmation({
isLoadingTransaction,
}: IOURequestStepConfirmationProps) {
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT;
const personalDetails = usePersonalDetails();

const [policyDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${IOU.getIOURequestPolicyID(transaction, reportDraft)}`);
const [policyReal] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${IOU.getIOURequestPolicyID(transaction, reportReal)}`);
Expand Down
Loading