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
2 changes: 1 addition & 1 deletion Mobile-Expensify
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1009029605
versionName "9.2.96-5"
versionCode 1009029606
versionName "9.2.96-6"
// Supported language variants must be declared here to avoid from being removed during the compilation.
// This also helps us to not include unnecessary language variants in the APK.
resConfigs "en", "es"
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>9.2.96.5</string>
<string>9.2.96.6</string>
<key>FullStory</key>
<dict>
<key>OrgId</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/NotificationServiceExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<key>CFBundleShortVersionString</key>
<string>9.2.96</string>
<key>CFBundleVersion</key>
<string>9.2.96.5</string>
<string>9.2.96.6</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/ShareViewController/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<key>CFBundleShortVersionString</key>
<string>9.2.96</string>
<key>CFBundleVersion</key>
<string>9.2.96.5</string>
<string>9.2.96.6</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
"version": "9.2.96-5",
"version": "9.2.96-6",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
Expand Down
67 changes: 32 additions & 35 deletions src/pages/EditReportFieldPage.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import {Str} from 'expensify-common';
import React, {useCallback} from 'react';
import React, {useState} from 'react';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import ConfirmModal from '@components/ConfirmModal';
import type {FormOnyxValues} from '@components/Form/types';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';
import {ModalActions} from '@components/Modal/Global/ModalContext';
import {useSession} from '@components/OnyxListItemProvider';
import type {PopoverMenuItem} from '@components/PopoverMenu';
import ScreenWrapper from '@components/ScreenWrapper';
import useConfirmModal from '@hooks/useConfirmModal';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePermissions from '@hooks/usePermissions';
Expand Down Expand Up @@ -51,43 +50,13 @@ function EditReportFieldPage({route}: EditReportFieldPageProps) {
const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true});
const hasViolations = hasViolationsReportUtils(report?.reportID, transactionViolations, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? '');

const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
const {translate} = useLocalize();
const {showConfirmModal} = useConfirmModal();
const isReportFieldTitle = isReportFieldOfTypeTitle(reportField);
const reportFieldsEnabled = ((isPaidGroupPolicyExpenseReport(report) || isInvoiceReport(report)) && !!policy?.areReportFieldsEnabled) || isReportFieldTitle;
const hasOtherViolations =
report?.fieldList && Object.entries(report.fieldList).some(([key, field]) => key !== fieldKey && field.value === '' && !isReportFieldDisabled(report, reportField, policy));

const goBack = useCallback(() => {
if (isReportFieldTitle && report?.reportID) {
Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID, backTo));
return;
}
Navigation.goBack(backTo);
}, [isReportFieldTitle, report?.reportID, backTo]);

const showDeleteModal = useCallback(() => {
if (!report || !reportField) {
return;
}
showConfirmModal({
title: translate('workspace.reportFields.delete'),
prompt: translate('workspace.reportFields.deleteConfirmation'),
confirmText: translate('common.delete'),
cancelText: translate('common.cancel'),
danger: true,
shouldEnableNewFocusManagement: true,
}).then(({action}) => {
if (action !== ModalActions.CONFIRM) {
return;
}
goBack();
setTimeout(() => {
deleteReportField(report.reportID, reportField);
}, CONST.ANIMATED_TRANSITION);
});
}, [showConfirmModal, translate, goBack, report, reportField]);

if (!reportFieldsEnabled || !reportField || !policyField || !report || isDisabled) {
return (
<ScreenWrapper
Expand All @@ -100,6 +69,22 @@ function EditReportFieldPage({route}: EditReportFieldPageProps) {
);
}

const goBack = () => {
if (isReportFieldTitle) {
Navigation.goBack(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID, backTo));
return;
}
Navigation.goBack(backTo);
};

const handleReportFieldDelete = () => {
setIsDeleteModalVisible(false);
goBack();
setTimeout(() => {
deleteReportField(report.reportID, reportField);
}, CONST.ANIMATED_TRANSITION);
};

const fieldValue = isReportFieldTitle ? (report.reportName ?? '') : (reportField.value ?? reportField.defaultValue);

const handleReportFieldChange = (form: FormOnyxValues<typeof ONYXKEYS.FORMS.REPORT_FIELDS_EDIT_FORM>) => {
Expand Down Expand Up @@ -136,7 +121,7 @@ function EditReportFieldPage({route}: EditReportFieldPageProps) {
const isReportFieldDeletable = reportField.deletable && reportField?.fieldID !== CONST.REPORT_FIELD_TITLE_FIELD_ID;

if (isReportFieldDeletable) {
menuItems.push({icon: Expensicons.Trashcan, text: translate('common.delete'), onSelected: showDeleteModal, shouldCallAfterModalHide: true});
menuItems.push({icon: Expensicons.Trashcan, text: translate('common.delete'), onSelected: () => setIsDeleteModalVisible(true), shouldCallAfterModalHide: true});
}

const fieldName = Str.UCFirst(reportField.name);
Expand All @@ -154,6 +139,18 @@ function EditReportFieldPage({route}: EditReportFieldPageProps) {
onBackButtonPress={goBack}
/>

<ConfirmModal
title={translate('workspace.reportFields.delete')}
isVisible={isDeleteModalVisible}
onConfirm={handleReportFieldDelete}
onCancel={() => setIsDeleteModalVisible(false)}
prompt={translate('workspace.reportFields.deleteConfirmation')}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
danger
shouldEnableNewFocusManagement
/>

{(reportField.type === CONST.REPORT_FIELD_TYPES.TEXT || isReportFieldTitle) && (
<EditReportFieldText
fieldName={reportField.name}
Expand Down
85 changes: 51 additions & 34 deletions src/pages/ReportDetailsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import reportsSelector from '@selectors/Attributes';
import {Str} from 'expensify-common';
import React, {useCallback, useEffect, useMemo} from 'react';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import AvatarWithImagePicker from '@components/AvatarWithImagePicker';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import ConfirmModal from '@components/ConfirmModal';
import DisplayNames from '@components/DisplayNames';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import MentionReportContext from '@components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/MentionReportContext';
import MenuItem from '@components/MenuItem';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import {ModalActions} from '@components/Modal/Global/ModalContext';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import ParentNavigationSubtitle from '@components/ParentNavigationSubtitle';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
Expand All @@ -23,7 +23,6 @@ import ScreenWrapper from '@components/ScreenWrapper';
import ScrollView from '@components/ScrollView';
import {useSearchContext} from '@components/Search/SearchContext';
import useAncestors from '@hooks/useAncestors';
import useConfirmModal from '@hooks/useConfirmModal';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useDeleteTransactions from '@hooks/useDeleteTransactions';
import useDuplicateTransactionsAndViolations from '@hooks/useDuplicateTransactionsAndViolations';
Expand Down Expand Up @@ -183,7 +182,8 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false});
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true});
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const {showConfirmModal} = useConfirmModal();
const [isLastMemberLeavingGroupModalVisible, setIsLastMemberLeavingGroupModalVisible] = useState(false);
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
const isPolicyAdmin = useMemo(() => isPolicyAdminUtil(policy), [policy]);
const isPolicyEmployee = useMemo(() => isPolicyEmployeeUtil(report?.policyID, policy), [report?.policyID, policy]);
const isPolicyExpenseChat = useMemo(() => isPolicyExpenseChatUtil(report), [report]);
Expand Down Expand Up @@ -307,6 +307,14 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
const [reportAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector});
const isWorkspaceChat = useMemo(() => isWorkspaceChatUtil(report?.chatType ?? ''), [report?.chatType]);

useEffect(() => {
if (canDeleteRequest) {
return;
}

setIsDeleteModalVisible(false);
}, [canDeleteRequest]);

useEffect(() => {
// Do not fetch private notes if isLoadingPrivateNotes is already defined, or if the network is offline, or if the report is a self DM.
if (isPrivateNotesFetchTriggered || isOffline || isSelfDM) {
Expand All @@ -328,21 +336,6 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
});
}, [isRootGroupChat, isPolicyEmployee, isPolicyAdmin, quickAction?.chatReportID, report]);

const showLastMemberLeavingModal = useCallback(() => {
showConfirmModal({
title: translate('groupChat.lastMemberTitle'),
prompt: translate('groupChat.lastMemberWarning'),
confirmText: translate('common.leave'),
cancelText: translate('common.cancel'),
danger: true,
}).then(({action}) => {
if (action !== ModalActions.CONFIRM) {
return;
}
leaveChat();
});
}, [showConfirmModal, translate, leaveChat]);

const shouldShowLeaveButton = canLeaveChat(report, policy, !!reportNameValuePairs?.private_isArchived);
const shouldShowGoToWorkspace = shouldShowPolicy(policy, false, currentUserPersonalDetails?.email) && !policy?.isJoinRequestPending;

Expand Down Expand Up @@ -533,7 +526,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
isAnonymousAction: true,
action: () => {
if (getParticipantsAccountIDsForDisplay(report, false, true).length === 1 && isRootGroupChat) {
showLastMemberLeavingModal();
setIsLastMemberLeavingGroupModalVisible(true);
return;
}

Expand Down Expand Up @@ -587,7 +580,6 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
isTaskActionable,
isRootGroupChat,
leaveChat,
showLastMemberLeavingModal,
isSmallScreenWidth,
isRestrictedToPreferredPolicy,
preferredPolicyID,
Expand Down Expand Up @@ -926,22 +918,20 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
}
}, [iouTransactionID, requestParentReportAction, isSingleTransactionView, moneyRequestReport, isChatIOUReportArchived, iouReport, chatIOUReport]);

const showDeleteModal = useCallback(() => {
showConfirmModal({
title: caseID === CASES.DEFAULT ? translate('task.deleteTask') : translate('iou.deleteExpense', {count: 1}),
prompt: caseID === CASES.DEFAULT ? translate('task.deleteConfirmation') : translate('iou.deleteConfirmation', {count: 1}),
confirmText: translate('common.delete'),
cancelText: translate('common.cancel'),
danger: true,
shouldEnableNewFocusManagement: true,
}).then(({action}) => {
if (action !== ModalActions.CONFIRM) {
// A flag to indicate whether the user chose to delete the transaction or not
const isTransactionDeleted = useRef<boolean>(false);

useEffect(() => {
return () => {
// Perform the actual deletion after the details page is unmounted. This prevents the [Deleted ...] text from briefly appearing when dismissing the modal.
if (!isTransactionDeleted.current) {
return;
}
isTransactionDeleted.current = false;
navigateToTargetUrl();
deleteTransaction();
});
}, [showConfirmModal, caseID, translate, navigateToTargetUrl, deleteTransaction]);
};
}, [deleteTransaction, navigateToTargetUrl]);

const mentionReportContextValue = useMemo(() => ({currentReportID: report.reportID, exactlyMatch: true}), [report.reportID]);

Expand Down Expand Up @@ -1024,10 +1014,37 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
key={CONST.REPORT_DETAILS_MENU_ITEM.DELETE}
icon={expensifyIcons.Trashcan}
title={caseID === CASES.DEFAULT ? translate('common.delete') : translate('reportActionContextMenu.deleteAction', {action: requestParentReportAction})}
onPress={showDeleteModal}
onPress={() => setIsDeleteModalVisible(true)}
/>
)}
</ScrollView>
<ConfirmModal
danger
title={translate('groupChat.lastMemberTitle')}
isVisible={isLastMemberLeavingGroupModalVisible}
onConfirm={() => {
setIsLastMemberLeavingGroupModalVisible(false);
leaveChat();
}}
onCancel={() => setIsLastMemberLeavingGroupModalVisible(false)}
prompt={translate('groupChat.lastMemberWarning')}
confirmText={translate('common.leave')}
cancelText={translate('common.cancel')}
/>
<ConfirmModal
title={caseID === CASES.DEFAULT ? translate('task.deleteTask') : translate('iou.deleteExpense', {count: 1})}
isVisible={isDeleteModalVisible}
onConfirm={() => {
setIsDeleteModalVisible(false);
isTransactionDeleted.current = true;
}}
onCancel={() => setIsDeleteModalVisible(false)}
prompt={caseID === CASES.DEFAULT ? translate('task.deleteConfirmation') : translate('iou.deleteConfirmation', {count: 1})}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
danger
shouldEnableNewFocusManagement
/>
</FullPageNotFoundView>
</ScreenWrapper>
);
Expand Down
Loading
Loading