diff --git a/src/CONST.ts b/src/CONST.ts
index 19720c05a93c..95cb4f94b169 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -2055,6 +2055,7 @@ const CONST = {
INFO: 'info',
},
REPORT_DETAILS_MENU_ITEM: {
+ SHARE_CODE: 'shareCode',
MEMBERS: 'member',
INVITE: 'invite',
SETTINGS: 'settings',
diff --git a/src/components/ChatDetailsQuickActionsBar.tsx b/src/components/ChatDetailsQuickActionsBar.tsx
index d289587ce953..f15fc31aec45 100644
--- a/src/components/ChatDetailsQuickActionsBar.tsx
+++ b/src/components/ChatDetailsQuickActionsBar.tsx
@@ -1,12 +1,11 @@
-import React from 'react';
+import React, {useState} from 'react';
import {View} from 'react-native';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
-import Navigation from '@libs/Navigation/Navigation';
import * as Report from '@userActions/Report';
-import ROUTES from '@src/ROUTES';
import type {Report as OnyxReportType} from '@src/types/onyx';
import Button from './Button';
+import ConfirmModal from './ConfirmModal';
import * as Expensicons from './Icon/Expensicons';
type ChatDetailsQuickActionsBarProps = {
@@ -15,26 +14,45 @@ type ChatDetailsQuickActionsBarProps = {
function ChatDetailsQuickActionsBar({report}: ChatDetailsQuickActionsBarProps) {
const styles = useThemeStyles();
+ const [isLastMemberLeavingGroupModalVisible, setIsLastMemberLeavingGroupModalVisible] = useState(false);
const {translate} = useLocalize();
const isPinned = !!report.isPinned;
return (
+ {
+ setIsLastMemberLeavingGroupModalVisible(false);
+ Report.leaveGroupChat(report.reportID);
+ }}
+ onCancel={() => setIsLastMemberLeavingGroupModalVisible(false)}
+ prompt={translate('groupChat.lastMemberWarning')}
+ confirmText={translate('common.leave')}
+ cancelText={translate('common.cancel')}
+ />
diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts
index cf4ab6e0d7b9..51221ddb1236 100644
--- a/src/libs/PolicyUtils.ts
+++ b/src/libs/PolicyUtils.ts
@@ -143,7 +143,7 @@ const isPolicyEmployee = (policyID: string, policies: OnyxCollection): b
/**
* Checks if the current user is an owner (creator) of the policy.
*/
-const isPolicyOwner = (policy: OnyxEntry | EmptyObject, currentUserAccountID: number): boolean => policy?.ownerAccountID === currentUserAccountID;
+const isPolicyOwner = (policy: OnyxEntry, currentUserAccountID: number): boolean => policy?.ownerAccountID === currentUserAccountID;
/**
* Create an object mapping member emails to their accountIDs. Filter for members without errors if includeMemberWithErrors is false, and get the login email from the personalDetail object using the accountID.
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index fb3371e94491..64b77cae6313 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -6393,7 +6393,7 @@ function hasActionsWithErrors(reportID: string): boolean {
return Object.values(reportActions).some((action) => !isEmptyObject(action.errors));
}
-function canLeavePolicyExpenseChat(report: OnyxEntry, policy: OnyxEntry | EmptyObject): boolean {
+function canLeavePolicyExpenseChat(report: OnyxEntry, policy: OnyxEntry): boolean {
return isPolicyExpenseChat(report) && !(PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPolicyOwner(policy, currentUserAccountID ?? -1) || isReportOwner(report));
}
diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx
index e97df0450eb8..ca66a0e97bb5 100644
--- a/src/pages/ReportDetailsPage.tsx
+++ b/src/pages/ReportDetailsPage.tsx
@@ -1,6 +1,6 @@
import {useRoute} from '@react-navigation/native';
import type {StackScreenProps} from '@react-navigation/stack';
-import React, {useCallback, useEffect, useMemo, useState} from 'react';
+import React, {useEffect, useMemo} from 'react';
import {View} from 'react-native';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
@@ -29,7 +29,6 @@ import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as Report from '@userActions/Report';
-import ConfirmModal from '@src/components/ConfirmModal';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -50,7 +49,6 @@ type ReportDetailsPageMenuItem = {
action: () => void;
brickRoadIndicator?: ValueOf;
subtitle?: number;
- shouldShowRightIcon?: boolean;
};
type ReportDetailsPageOnyxProps = {
@@ -67,12 +65,10 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
const {isOffline} = useNetwork();
const styles = useThemeStyles();
const route = useRoute();
- const [isLastMemberLeavingGroupModalVisible, setIsLastMemberLeavingGroupModalVisible] = useState(false);
const policy = useMemo(() => policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID ?? ''}`], [policies, report?.policyID]);
const isPolicyAdmin = useMemo(() => PolicyUtils.isPolicyAdmin(policy ?? null), [policy]);
const isPolicyEmployee = useMemo(() => PolicyUtils.isPolicyEmployee(report?.policyID ?? '', policies), [report?.policyID, policies]);
const shouldUseFullTitle = useMemo(() => ReportUtils.shouldUseFullTitleToDisplay(report), [report]);
- const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report);
const isChatRoom = useMemo(() => ReportUtils.isChatRoom(report), [report]);
const isUserCreatedPolicyRoom = useMemo(() => ReportUtils.isUserCreatedPolicyRoom(report), [report]);
const isDefaultRoom = useMemo(() => ReportUtils.isDefaultRoom(report), [report]);
@@ -83,8 +79,6 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
const isInvoiceReport = useMemo(() => ReportUtils.isInvoiceReport(report), [report]);
const canEditReportDescription = useMemo(() => ReportUtils.canEditReportDescription(report, policy), [report, policy]);
const shouldShowReportDescription = isChatRoom && (canEditReportDescription || report.description !== '');
- const canLeaveRoom = ReportUtils.canLeaveRoom(report, isPolicyEmployee);
- const canLeavePolicyExpenseChat = ReportUtils.canLeavePolicyExpenseChat(report, policy ?? {});
// eslint-disable-next-line react-hooks/exhaustive-deps -- policy is a dependency because `getChatRoomSubtitle` calls `getPolicyName` which in turn retrieves the value from the `policy` value stored in Onyx
const chatRoomSubtitle = useMemo(() => ReportUtils.getChatRoomSubtitle(report), [report, policy]);
@@ -105,11 +99,10 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
return !pendingMember || pendingMember.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE ? accountID : [];
});
+ const isGroupDMChat = useMemo(() => ReportUtils.isDM(report) && participants.length > 1, [report, participants.length]);
const isPrivateNotesFetchTriggered = report?.isLoadingPrivateNotes !== undefined;
const isSelfDM = useMemo(() => ReportUtils.isSelfDM(report), [report]);
- const canLeave =
- !isSelfDM && (isChatThread || isUserCreatedPolicyRoom || canLeaveRoom || canLeavePolicyExpenseChat) && report.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
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.
@@ -120,15 +113,6 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
Report.getReportPrivateNote(report?.reportID ?? '');
}, [report?.reportID, isOffline, isPrivateNotesFetchTriggered, isSelfDM]);
- const leaveChat = useCallback(() => {
- if (isChatRoom) {
- const isWorkspaceMemberLeavingWorkspaceRoom = (report.visibility === CONST.REPORT.VISIBILITY.RESTRICTED || isPolicyExpenseChat) && isPolicyEmployee;
- Report.leaveRoom(report.reportID, isWorkspaceMemberLeavingWorkspaceRoom);
- return;
- }
- Report.leaveGroupChat(report.reportID);
- }, [isChatRoom, isPolicyEmployee, isPolicyExpenseChat, report.reportID, report.visibility]);
-
const menuItems: ReportDetailsPageMenuItem[] = useMemo(() => {
const items: ReportDetailsPageMenuItem[] = [];
@@ -136,6 +120,16 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
return [];
}
+ if (!isGroupDMChat) {
+ items.push({
+ key: CONST.REPORT_DETAILS_MENU_ITEM.SHARE_CODE,
+ translationKey: 'common.shareCode',
+ icon: Expensicons.QrCode,
+ isAnonymousAction: true,
+ action: () => Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS_SHARE_CODE.getRoute(report?.reportID ?? '')),
+ });
+ }
+
if (isArchivedRoom) {
return items;
}
@@ -202,27 +196,10 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
});
}
- if (isGroupChat || (isChatRoom && canLeave)) {
- items.push({
- key: CONST.REPORT_DETAILS_MENU_ITEM.LEAVE_ROOM,
- translationKey: 'common.leave',
- icon: Expensicons.Exit,
- isAnonymousAction: true,
- shouldShowRightIcon: false,
- action: () => {
- if (Object.keys(report?.participants ?? {}).length === 1 && isGroupChat) {
- setIsLastMemberLeavingGroupModalVisible(true);
- return;
- }
-
- leaveChat();
- },
- });
- }
-
return items;
}, [
isSelfDM,
+ isGroupDMChat,
isArchivedRoom,
isGroupChat,
isDefaultRoom,
@@ -232,12 +209,9 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
participants.length,
report,
isMoneyRequestReport,
- isChatRoom,
- canLeave,
+ isInvoiceReport,
activeChatMembers.length,
session,
- leaveChat,
- isInvoiceReport,
]);
const displayNamesWithTooltips = useMemo(() => {
@@ -346,10 +320,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
{shouldShowReportDescription && (
-
+
)}
- {(isGroupChat || isChatRoom) && }
+ {isGroupChat && }
{menuItems.map((item) => {
const brickRoadIndicator =
ReportUtils.hasReportNameError(report) && item.key === CONST.REPORT_DETAILS_MENU_ITEM.SETTINGS ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined;
@@ -373,25 +344,12 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD
icon={item.icon}
onPress={item.action}
isAnonymousAction={item.isAnonymousAction}
- shouldShowRightIcon={item.shouldShowRightIcon ?? true}
+ shouldShowRightIcon
brickRoadIndicator={brickRoadIndicator ?? item.brickRoadIndicator}
/>
);
})}
- {
- setIsLastMemberLeavingGroupModalVisible(false);
- Report.leaveGroupChat(report.reportID);
- }}
- onCancel={() => setIsLastMemberLeavingGroupModalVisible(false)}
- prompt={translate('groupChat.lastMemberWarning')}
- confirmText={translate('common.leave')}
- cancelText={translate('common.cancel')}
- />
);