From 2dd1ec3b70230e6d1ca62969d431e97f96159c7c Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Sat, 30 May 2026 09:48:20 +0200 Subject: [PATCH 1/3] Revert "Merge pull request #91750 from Expensify/cmartins-fixCrashOnMain" This reverts commit b6572e3d74189ef75ec5759257ef8afd9c812fd2, reversing changes made to 9573a6cb7dbb0475ddd2e077baf264131f6c9ce1. --- .../inbox/report/ReportActionCompose/ComposerActionButton.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerActionButton.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerActionButton.tsx index e9147bd9afd7..c0f694363919 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerActionButton.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerActionButton.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import ComposerActionMenu from './ComposerActionMenu'; import {useComposerEditState} from './ComposerContext'; import ComposerEditingButtons from './ComposerEditingButtons'; From 5b499cf983721d05c980a22fee7f84356ed050aa Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Sat, 30 May 2026 10:13:50 +0200 Subject: [PATCH 2/3] Revert "Merge pull request #90915 from margelo/@chrispader/refactor/compositional-edit-only-report-action-compose" This reverts commit 6a3c80832c9a30777415bbd8ceb919bfde18fa12, reversing changes made to e09715e09f95bd1dffd02251feb92e2ab680be08. --- src/pages/inbox/ReportScreen.tsx | 4 +- ....tsx => AgentZeroAwareTypingIndicator.tsx} | 6 +- .../ComposerActionButton.tsx | 14 --- .../ComposerActionMenu.tsx | 7 +- .../ReportActionCompose/ComposerBox.tsx | 9 +- .../ReportActionCompose/ComposerContainer.tsx | 29 ----- .../ReportActionCompose/ComposerContext.ts | 2 - .../ComposerDefaultFooter.tsx | 22 ---- .../ReportActionCompose/ComposerDropZone.tsx | 10 +- .../ComposerEditingButtons.tsx | 10 +- .../ComposerEmojiPicker.tsx | 9 +- .../ReportActionCompose/ComposerFooter.tsx | 7 +- .../ReportActionCompose/ComposerInput.tsx | 7 +- .../ReportActionCompose/ComposerInputArea.tsx | 46 -------- .../ReportActionCompose/ComposerLocalTime.tsx | 8 +- .../ReportActionCompose/ComposerProvider.tsx | 1 - .../ComposerSendButton.tsx | 5 +- .../ReportActionCompose.tsx | 102 ++++++++++++------ ...tsx => ReportActionComposePlaceholder.tsx} | 4 +- src/pages/inbox/report/ReportFooter.tsx | 22 ++-- tests/unit/ComposerLocalTimeTest.tsx | 15 +-- 21 files changed, 145 insertions(+), 194 deletions(-) rename src/pages/inbox/report/ReportActionCompose/{ComposerTypingIndicator.tsx => AgentZeroAwareTypingIndicator.tsx} (69%) delete mode 100644 src/pages/inbox/report/ReportActionCompose/ComposerActionButton.tsx delete mode 100644 src/pages/inbox/report/ReportActionCompose/ComposerContainer.tsx delete mode 100644 src/pages/inbox/report/ReportActionCompose/ComposerDefaultFooter.tsx delete mode 100644 src/pages/inbox/report/ReportActionCompose/ComposerInputArea.tsx rename src/pages/inbox/report/ReportActionCompose/{ComposerPlaceholder.tsx => ReportActionComposePlaceholder.tsx} (97%) diff --git a/src/pages/inbox/ReportScreen.tsx b/src/pages/inbox/ReportScreen.tsx index 0fe5cab9d7fb..684f69b66284 100644 --- a/src/pages/inbox/ReportScreen.tsx +++ b/src/pages/inbox/ReportScreen.tsx @@ -28,7 +28,7 @@ import useDeferNonEssentials from './hooks/useDeferNonEssentials'; import useFlushDeferredWriteOnFocus from './hooks/useFlushDeferredWriteOnFocus'; import LinkedActionNotFoundGuard from './LinkedActionNotFoundGuard'; import ReactionListWrapper from './ReactionListWrapper'; -import ReportActionCompose from './report/ReportActionCompose/ReportActionCompose'; +import ReportActionComposePlaceholder from './report/ReportActionCompose/ReportActionComposePlaceholder'; import {ReportActionEditMessageContextProvider, ReportScreenEditMessageProviderWithTransactionThread} from './report/ReportActionEditMessageContext'; import ReportFooter from './report/ReportFooter'; import useClearReportActionDraftsOnReportChange from './report/useClearReportActionDraftsOnReportChange'; @@ -148,7 +148,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) { testID="report-actions-view-wrapper" > - {shouldDeferNonEssentials ? : } + {shouldDeferNonEssentials ? : } diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerTypingIndicator.tsx b/src/pages/inbox/report/ReportActionCompose/AgentZeroAwareTypingIndicator.tsx similarity index 69% rename from src/pages/inbox/report/ReportActionCompose/ComposerTypingIndicator.tsx rename to src/pages/inbox/report/ReportActionCompose/AgentZeroAwareTypingIndicator.tsx index 7ced0f7cc9c7..835cc1323b4f 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerTypingIndicator.tsx +++ b/src/pages/inbox/report/ReportActionCompose/AgentZeroAwareTypingIndicator.tsx @@ -1,10 +1,8 @@ import React from 'react'; import useShouldSuppressConciergeIndicators from '@hooks/useShouldSuppressConciergeIndicators'; import ReportTypingIndicator from '@pages/inbox/report/ReportTypingIndicator'; -import {useComposerState} from './ComposerContext'; -function ComposerTypingIndicator() { - const {reportID} = useComposerState(); +function AgentZeroAwareTypingIndicator({reportID}: {reportID: string}) { const shouldSuppress = useShouldSuppressConciergeIndicators(reportID); if (shouldSuppress) { return null; @@ -12,4 +10,4 @@ function ComposerTypingIndicator() { return ; } -export default ComposerTypingIndicator; +export default AgentZeroAwareTypingIndicator; diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerActionButton.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerActionButton.tsx deleted file mode 100644 index c0f694363919..000000000000 --- a/src/pages/inbox/report/ReportActionCompose/ComposerActionButton.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import ComposerActionMenu from './ComposerActionMenu'; -import {useComposerEditState} from './ComposerContext'; -import ComposerEditingButtons from './ComposerEditingButtons'; - -function ComposerActionButton() { - const {isEditingInComposer} = useComposerEditState(); - - if (isEditingInComposer) { - return ; - } - return ; -} - -export default ComposerActionButton; diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerActionMenu.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerActionMenu.tsx index b7e8f4e14569..c84eda56f95f 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerActionMenu.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerActionMenu.tsx @@ -11,8 +11,11 @@ import AttachmentPickerWithMenuItems from './AttachmentPickerWithMenuItems'; import {useComposerActions, useComposerEditState, useComposerMeta, useComposerSendState, useComposerState} from './ComposerContext'; import useAttachmentPicker from './useAttachmentPicker'; -function ComposerActionMenu() { - const {reportID} = useComposerState(); +type ComposerActionMenuProps = { + reportID: string; +}; + +function ComposerActionMenu({reportID}: ComposerActionMenuProps) { const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const {isMenuVisible, isFullComposerAvailable} = useComposerState(); const {draftComment} = useComposerEditState(); diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerBox.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerBox.tsx index 0c1414788420..568c90b2a619 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerBox.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerBox.tsx @@ -1,13 +1,16 @@ import React from 'react'; -import type {PropsWithChildren} from 'react'; import {View} from 'react-native'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; import ONYXKEYS from '@src/ONYXKEYS'; import {useComposerMeta, useComposerSendState, useComposerState} from './ComposerContext'; -function ComposerBox({children}: PropsWithChildren) { - const {reportID} = useComposerState(); +type ComposerBoxProps = { + reportID: string; + children: React.ReactNode; +}; + +function ComposerBox({reportID, children}: ComposerBoxProps) { const styles = useThemeStyles(); const {isFocused} = useComposerState(); const {isExceedingMaxLength, isBlockedFromConcierge} = useComposerSendState(); diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerContainer.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerContainer.tsx deleted file mode 100644 index 7a11d44e5f90..000000000000 --- a/src/pages/inbox/report/ReportActionCompose/ComposerContainer.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import type {PropsWithChildren} from 'react'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import useOnyx from '@hooks/useOnyx'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {getReportOfflinePendingActionAndErrors} from '@libs/ReportUtils'; -import ONYXKEYS from '@src/ONYXKEYS'; -import {useComposerState} from './ComposerContext'; - -function ComposerContainer({children}: PropsWithChildren) { - const {reportID} = useComposerState(); - const styles = useThemeStyles(); - const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`); - const [isComposerFullSize = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${reportID}`); - const {reportPendingAction: pendingAction} = getReportOfflinePendingActionAndErrors(report); - - return ( - - {children} - - ); -} - -export default ComposerContainer; diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerContext.ts b/src/pages/inbox/report/ReportActionCompose/ComposerContext.ts index 64c32912a0a3..ec9b33de1433 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerContext.ts +++ b/src/pages/inbox/report/ReportActionCompose/ComposerContext.ts @@ -26,7 +26,6 @@ type ComposerText = string; // Warm — changes on interaction type ComposerState = { - reportID: string; isFocused: boolean; isMenuVisible: boolean; isFullComposerAvailable: boolean; @@ -91,7 +90,6 @@ const noop = () => {}; const ComposerTextContext = createContext(''); const defaultState: ComposerState = { - reportID: '', isFocused: false, isMenuVisible: false, isFullComposerAvailable: false, diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerDefaultFooter.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerDefaultFooter.tsx deleted file mode 100644 index 0c83e2b890ef..000000000000 --- a/src/pages/inbox/report/ReportActionCompose/ComposerDefaultFooter.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import OfflineIndicator from '@components/OfflineIndicator'; -import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useThemeStyles from '@hooks/useThemeStyles'; -import ComposerExceededLength from './ComposerExceededLength'; -import ComposerFooter from './ComposerFooter'; -import ComposerTypingIndicator from './ComposerTypingIndicator'; - -function ComposerDefaultFooter() { - const styles = useThemeStyles(); - const {shouldUseNarrowLayout} = useResponsiveLayout(); - - return ( - - {!shouldUseNarrowLayout && } - - - - ); -} - -export default ComposerDefaultFooter; diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerDropZone.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerDropZone.tsx index 0db4107e2e22..344a2316925c 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerDropZone.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerDropZone.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import type {PropsWithChildren} from 'react'; import DragAndDropConsumer from '@components/DragAndDrop/Consumer'; import DropZoneUI from '@components/DropZone/DropZoneUI'; import DualDropZone from '@components/DropZone/DualDropZone'; @@ -15,11 +14,15 @@ import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import {getParentReport, isChatRoom, isGroupChat, isInvoiceReport, isReportApproved, isSettled, temporary_getMoneyRequestOptions} from '@libs/ReportUtils'; import {hasReceipt as hasReceiptTransactionUtils} from '@libs/TransactionUtils'; import ONYXKEYS from '@src/ONYXKEYS'; -import {useComposerState} from './ComposerContext'; import useAttachmentPicker from './useAttachmentPicker'; import useReceiptDrop from './useReceiptDrop'; import useShouldAddOrReplaceReceipt from './useShouldAddOrReplaceReceipt'; +type ComposerDropZoneProps = { + reportID: string; + children: React.ReactNode; +}; + type RichDropZoneProps = { reportID: string; shouldAddOrReplaceReceipt: boolean; @@ -107,8 +110,7 @@ function RichDropZone({reportID, shouldAddOrReplaceReceipt, transactionID, onAtt ); } -function ComposerDropZone({children}: PropsWithChildren) { - const {reportID} = useComposerState(); +function ComposerDropZone({reportID, children}: ComposerDropZoneProps) { const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`); const {shouldAddOrReplaceReceipt, transactionID} = useShouldAddOrReplaceReceipt(reportID); const {pickAttachments, PDFValidationComponent: AttachmentPDFValidation, ErrorModal: AttachmentErrorModal} = useAttachmentPicker(reportID); diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerEditingButtons.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerEditingButtons.tsx index 4bf7e056ad13..77f8f58dfae0 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerEditingButtons.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerEditingButtons.tsx @@ -2,12 +2,16 @@ import React from 'react'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -import {useComposerEditActions, useComposerState} from './ComposerContext'; +import {useComposerEditActions} from './ComposerContext'; import ComposerExpandCollapseButton from './ComposerExpandCollapseButton'; import MessageEditCancelButton from './MessageEditCancelButton'; -function ComposerEditingButtons() { - const {reportID} = useComposerState(); +type ComposerEditingButtonsProps = { + /** The report ID */ + reportID: string; +}; + +function ComposerEditingButtons({reportID}: ComposerEditingButtonsProps) { const styles = useThemeStyles(); const {deleteDraft} = useComposerEditActions(); diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerEmojiPicker.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerEmojiPicker.tsx index 43f4ff1c8c47..99c26549cd59 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerEmojiPicker.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerEmojiPicker.tsx @@ -6,10 +6,13 @@ import {canUseTouchScreen} from '@libs/DeviceCapabilities'; import DomUtils from '@libs/DomUtils'; import {hideEmojiPicker, isActive as isActiveEmojiPickerAction} from '@userActions/EmojiPickerAction'; import CONST from '@src/CONST'; -import {useComposerMeta, useComposerSendState, useComposerState} from './ComposerContext'; +import {useComposerMeta, useComposerSendState} from './ComposerContext'; -function ComposerEmojiPicker() { - const {reportID} = useComposerState(); +type ComposerEmojiPickerProps = { + reportID: string; +}; + +function ComposerEmojiPicker({reportID}: ComposerEmojiPickerProps) { const styles = useThemeStyles(); const {isMediumScreenWidth} = useResponsiveLayout(); diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerFooter.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerFooter.tsx index 4bcfe5289c4c..c34ca8e8e9de 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerFooter.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerFooter.tsx @@ -1,11 +1,14 @@ import React from 'react'; -import type {PropsWithChildren} from 'react'; import {View} from 'react-native'; import useNetwork from '@hooks/useNetwork'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; -function ComposerFooter({children}: PropsWithChildren) { +type ComposerFooterProps = { + children: React.ReactNode; +}; + +function ComposerFooter({children}: ComposerFooterProps) { const styles = useThemeStyles(); // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {isSmallScreenWidth} = useResponsiveLayout(); diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerInput.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerInput.tsx index c8425c634336..1b01a369687f 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerInput.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerInput.tsx @@ -23,6 +23,10 @@ import ComposerWithSuggestions from './ComposerWithSuggestions'; import useAttachmentPicker from './useAttachmentPicker'; import useComposerSubmit from './useComposerSubmit'; +type ComposerInputProps = { + reportID: string; +}; + const AI_PLACEHOLDER_KEYS = ['reportActionCompose.askConciergeToUpdate', 'reportActionCompose.askConciergeToCorrect', 'reportActionCompose.askConciergeForHelp'] as const; function getRandomPlaceholder(translate: LocalizedTranslate): string { @@ -30,8 +34,7 @@ function getRandomPlaceholder(translate: LocalizedTranslate): string { return translate(AI_PLACEHOLDER_KEYS[randomIndex]); } -function ComposerInput() { - const {reportID} = useComposerState(); +function ComposerInput({reportID}: ComposerInputProps) { const {translate, preferredLocale} = useLocalize(); const {isMenuVisible} = useComposerState(); const {isBlockedFromConcierge, debouncedCommentMaxLengthValidation} = useComposerSendState(); diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerInputArea.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerInputArea.tsx deleted file mode 100644 index 2b59b2f8db2a..000000000000 --- a/src/pages/inbox/report/ReportActionCompose/ComposerInputArea.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react'; -import {View} from 'react-native'; -import useOnyx from '@hooks/useOnyx'; -import useThemeStyles from '@hooks/useThemeStyles'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ComposerActionButton from './ComposerActionButton'; -import ComposerBox from './ComposerBox'; -import ComposerContainer from './ComposerContainer'; -import {useComposerState} from './ComposerContext'; -import ComposerDropZone from './ComposerDropZone'; -import ComposerEmojiPicker from './ComposerEmojiPicker'; -import ComposerImportedState from './ComposerImportedState'; -import ComposerInput from './ComposerInput'; -import ComposerLocalTime from './ComposerLocalTime'; -import ComposerSendButton from './ComposerSendButton'; - -function ComposerInputArea() { - const {reportID} = useComposerState(); - const styles = useThemeStyles(); - const [isComposerFullSize = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${reportID}`); - - return ( - - - - - - - - - - - - - - - - - ); -} - -export default ComposerInputArea; diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerLocalTime.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerLocalTime.tsx index 2eca6ac0d47c..98d14016f4ce 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerLocalTime.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerLocalTime.tsx @@ -9,10 +9,12 @@ import {isAgentEmail} from '@libs/SessionUtils'; import ParticipantLocalTime from '@pages/inbox/report/ParticipantLocalTime'; import ONYXKEYS from '@src/ONYXKEYS'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import {useComposerState} from './ComposerContext'; -function ComposerLocalTime() { - const {reportID} = useComposerState(); +type ComposerLocalTimeProps = { + reportID: string; +}; + +function ComposerLocalTime({reportID}: ComposerLocalTimeProps) { const [isComposerFullSize = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${reportID}`); const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`); diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerProvider.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerProvider.tsx index 3435222bd241..7c3b41392182 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerProvider.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerProvider.tsx @@ -124,7 +124,6 @@ function ComposerProvider({children, reportID}: ComposerProviderProps) { }; const composerState = { - reportID, isFocused, isMenuVisible, isFullComposerAvailable, diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerSendButton.tsx b/src/pages/inbox/report/ReportActionCompose/ComposerSendButton.tsx index 361c4828cccb..79aab7007d88 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerSendButton.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ComposerSendButton.tsx @@ -6,12 +6,11 @@ import useLocalize from '@hooks/useLocalize'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -import {useComposerEditState, useComposerSendState, useComposerState} from './ComposerContext'; +import {useComposerEditState, useComposerSendState} from './ComposerContext'; import SubmitDraftButton from './SubmitDraftButton'; import useComposerSubmit from './useComposerSubmit'; -function ComposerSendButton() { - const {reportID} = useComposerState(); +function ComposerSendButton({reportID}: {reportID: string}) { const styles = useThemeStyles(); const {translate} = useLocalize(); const icons = useMemoizedLazyExpensifyIcons(['Send', 'Checkmark']); diff --git a/src/pages/inbox/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/inbox/report/ReportActionCompose/ReportActionCompose.tsx index 984b242f8c9d..b81935a33ada 100644 --- a/src/pages/inbox/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ReportActionCompose.tsx @@ -1,9 +1,18 @@ import React from 'react'; +import {View} from 'react-native'; +import OfflineIndicator from '@components/OfflineIndicator'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useOnyx from '@hooks/useOnyx'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {getReportOfflinePendingActionAndErrors} from '@libs/ReportUtils'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import AgentZeroAwareTypingIndicator from './AgentZeroAwareTypingIndicator'; import ComposerActionMenu from './ComposerActionMenu'; import ComposerBox from './ComposerBox'; -import ComposerContainer from './ComposerContainer'; +import {useComposerEditState} from './ComposerContext'; import type {SuggestionsRef} from './ComposerContext'; -import ComposerDefaultFooter from './ComposerDefaultFooter'; import ComposerDropZone from './ComposerDropZone'; import ComposerEditingButtons from './ComposerEditingButtons'; import ComposerEmojiPicker from './ComposerEmojiPicker'; @@ -11,53 +20,84 @@ import ComposerExceededLength from './ComposerExceededLength'; import ComposerFooter from './ComposerFooter'; import ComposerImportedState from './ComposerImportedState'; import ComposerInput from './ComposerInput'; -import ComposerInputArea from './ComposerInputArea'; import ComposerLocalTime from './ComposerLocalTime'; -import ComposerPlaceholder from './ComposerPlaceholder'; import ComposerProvider from './ComposerProvider'; import ComposerSendButton from './ComposerSendButton'; -import ComposerTypingIndicator from './ComposerTypingIndicator'; type ReportActionComposeProps = { /** Report ID */ reportID: string; + + /** Whether the composer is edit only */ + isEditOnly?: boolean; }; -function ReportActionCompose({reportID}: ReportActionComposeProps) { +function ComposerInner({reportID, isEditOnly = false}: ReportActionComposeProps) { + const styles = useThemeStyles(); + const {shouldUseNarrowLayout} = useResponsiveLayout(); + const {isEditingInComposer} = useComposerEditState(); + const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`); + const [isComposerFullSize = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${reportID}`); + const {reportPendingAction: pendingAction} = getReportOfflinePendingActionAndErrors(report); + return ( - - - - + + + + + + + {isEditingInComposer ? : } + + + + + + {!isEditOnly && ( + + {!shouldUseNarrowLayout && } + + + + )} + + + + ); } -function EditOnlyReportActionCompose({reportID}: ReportActionComposeProps) { +function Composer({reportID, ...restProps}: ReportActionComposeProps) { return ( - + ); } -ReportActionCompose.LocalTime = ComposerLocalTime; -ReportActionCompose.Container = ComposerContainer; -ReportActionCompose.ImportedState = ComposerImportedState; -ReportActionCompose.DropZone = ComposerDropZone; -ReportActionCompose.Box = ComposerBox; -ReportActionCompose.ActionMenu = ComposerActionMenu; -ReportActionCompose.Input = ComposerInput; -ReportActionCompose.EmojiPicker = ComposerEmojiPicker; -ReportActionCompose.SendButton = ComposerSendButton; -ReportActionCompose.EditingButtons = ComposerEditingButtons; -ReportActionCompose.Footer = ComposerFooter; -ReportActionCompose.TypingIndicator = ComposerTypingIndicator; -ReportActionCompose.ExceededLength = ComposerExceededLength; -ReportActionCompose.Layout = ComposerInputArea; -ReportActionCompose.Placeholder = ComposerPlaceholder; -ReportActionCompose.InputArea = ComposerInputArea; -ReportActionCompose.DefaultFooter = ComposerDefaultFooter; -ReportActionCompose.EditOnly = EditOnlyReportActionCompose; +Composer.LocalTime = ComposerLocalTime; +Composer.DropZone = ComposerDropZone; +Composer.Box = ComposerBox; +Composer.ActionMenu = ComposerActionMenu; +Composer.Input = ComposerInput; +Composer.EmojiPicker = ComposerEmojiPicker; +Composer.SendButton = ComposerSendButton; +Composer.EditingButtons = ComposerEditingButtons; +Composer.Footer = ComposerFooter; +Composer.TypingIndicator = AgentZeroAwareTypingIndicator; +Composer.ExceededLength = ComposerExceededLength; +Composer.ImportedState = ComposerImportedState; -export default ReportActionCompose; +export default Composer; export type {SuggestionsRef, ReportActionComposeProps}; diff --git a/src/pages/inbox/report/ReportActionCompose/ComposerPlaceholder.tsx b/src/pages/inbox/report/ReportActionCompose/ReportActionComposePlaceholder.tsx similarity index 97% rename from src/pages/inbox/report/ReportActionCompose/ComposerPlaceholder.tsx rename to src/pages/inbox/report/ReportActionCompose/ReportActionComposePlaceholder.tsx index f3a997f5357a..7a90fad4a08c 100644 --- a/src/pages/inbox/report/ReportActionCompose/ComposerPlaceholder.tsx +++ b/src/pages/inbox/report/ReportActionCompose/ReportActionComposePlaceholder.tsx @@ -22,7 +22,7 @@ import CONST from '@src/CONST'; * chatItemComposeSecondaryRow, and icons [Plus, Emoji, Send]. * If the real composer changes its layout or icon set, update this placeholder to match. */ -function ComposerPlaceholder() { +function ReportActionComposePlaceholder() { const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -86,4 +86,4 @@ function ComposerPlaceholder() { ); } -export default ComposerPlaceholder; +export default ReportActionComposePlaceholder; diff --git a/src/pages/inbox/report/ReportFooter.tsx b/src/pages/inbox/report/ReportFooter.tsx index ab26c755e5f2..510a60ec8221 100644 --- a/src/pages/inbox/report/ReportFooter.tsx +++ b/src/pages/inbox/report/ReportFooter.tsx @@ -97,9 +97,7 @@ function ReportFooter() { {shouldShowEnableNotificationsBanner && } - - - + ); @@ -169,9 +167,10 @@ function ReportFooter() { {isEditingWithComposer && ( - - - + )} + + + ); +} + export default ReportFooter; diff --git a/tests/unit/ComposerLocalTimeTest.tsx b/tests/unit/ComposerLocalTimeTest.tsx index 7bf6f13c107e..0fdb4ca2e4f8 100644 --- a/tests/unit/ComposerLocalTimeTest.tsx +++ b/tests/unit/ComposerLocalTimeTest.tsx @@ -5,7 +5,6 @@ import ComposeProviders from '@components/ComposeProviders'; import {LocaleContextProvider} from '@components/LocaleContextProvider'; import OnyxListItemProvider from '@components/OnyxListItemProvider'; import ComposerLocalTime from '@pages/inbox/report/ReportActionCompose/ComposerLocalTime'; -import ComposerProvider from '@pages/inbox/report/ReportActionCompose/ComposerProvider'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetailsList, Report} from '@src/types/onyx'; @@ -38,12 +37,8 @@ function buildReport(participantAccountIDs: number[]): Report { } as Report; } -function renderWithProviders(component: React.ReactElement, reportID: string) { - return render( - - {component} - , - ); +function renderWithProviders(component: React.ReactElement) { + return render({component}); } describe('ComposerLocalTime', () => { @@ -72,7 +67,7 @@ describe('ComposerLocalTime', () => { await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails); await waitForBatchedUpdates(); - renderWithProviders(, REPORT_ID); + renderWithProviders(); await waitForBatchedUpdates(); @@ -98,7 +93,7 @@ describe('ComposerLocalTime', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${REPORT_ID}`, true); await waitForBatchedUpdates(); - const {toJSON} = renderWithProviders(, REPORT_ID); + const {toJSON} = renderWithProviders(); await waitForBatchedUpdates(); @@ -122,7 +117,7 @@ describe('ComposerLocalTime', () => { await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails); await waitForBatchedUpdates(); - const {toJSON} = renderWithProviders(, REPORT_ID); + const {toJSON} = renderWithProviders(); await waitForBatchedUpdates(); From 545befec14598d3cadd5afafd6446dcc1e89c387 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Sat, 30 May 2026 11:06:28 +0200 Subject: [PATCH 3/3] Revert "Merge pull request #90365 from Expensify/jpersaud/concierge-enable-notifications-banner" This reverts commit 021bcf37b4129e2f4fb69775dbe1594844df277f, reversing changes made to e2ca8309b4fc91b052288a6577ff31702b205f6d. --- Mobile-Expensify | 2 +- src/ONYXKEYS.ts | 4 - src/components/Banner.tsx | 21 ++--- src/languages/de.ts | 1 - src/languages/en.ts | 4 - src/languages/es.ts | 4 - src/languages/fr.ts | 1 - src/languages/it.ts | 1 - src/languages/ja.ts | 4 - src/languages/nl.ts | 1 - src/languages/pl.ts | 1 - src/languages/pt-BR.ts | 1 - src/languages/zh-hans.ts | 4 - .../LocalNotification/BrowserNotifications.ts | 27 ++++-- .../notificationPermission/index.native.ts | 8 -- .../notificationPermission/index.ts | 33 -------- .../notificationPermission/types.ts | 9 -- .../actions/ConciergeNotificationBanner.ts | 11 --- .../report/EnableNotificationsBanner.tsx | 63 -------------- src/pages/inbox/report/ReportFooter.tsx | 10 +-- .../useShouldShowEnableNotificationsBanner.ts | 36 -------- src/setup/index.ts | 1 - .../ConciergeNotificationBannerTest.ts | 24 ------ tests/unit/EnableNotificationsBannerTest.tsx | 82 ------------------- ...houldShowEnableNotificationsBanner.test.ts | 66 --------------- 25 files changed, 28 insertions(+), 391 deletions(-) delete mode 100644 src/libs/Notification/notificationPermission/index.native.ts delete mode 100644 src/libs/Notification/notificationPermission/index.ts delete mode 100644 src/libs/Notification/notificationPermission/types.ts delete mode 100644 src/libs/actions/ConciergeNotificationBanner.ts delete mode 100644 src/pages/inbox/report/EnableNotificationsBanner.tsx delete mode 100644 src/pages/inbox/report/useShouldShowEnableNotificationsBanner.ts delete mode 100644 tests/actions/ConciergeNotificationBannerTest.ts delete mode 100644 tests/unit/EnableNotificationsBannerTest.tsx delete mode 100644 tests/unit/hooks/useShouldShowEnableNotificationsBanner.test.ts diff --git a/Mobile-Expensify b/Mobile-Expensify index d62323fd8d53..d04040c9f51f 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit d62323fd8d5308fa9b49d510f4b4d8383efcc978 +Subproject commit d04040c9f51f31226fb0d48bc1513dd7b15ea526 diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 74e4f1d94169..ff79ebaa9adf 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -568,9 +568,6 @@ const ONYXKEYS = { /** Stores the information if mobile selection mode is active */ RAM_ONLY_MOBILE_SELECTION_MODE: 'mobileSelectionMode', - /** Session-scoped flag: user dismissed the "enable notifications" banner in the Concierge chat */ - RAM_ONLY_HAS_DISMISSED_CONCIERGE_NOTIFICATION_BANNER: 'hasDismissedConciergeNotificationBanner', - NVP_PRIVATE_CANCELLATION_DETAILS: 'nvp_private_cancellationDetails', /** Stores the information about duplicated workspace */ @@ -1587,7 +1584,6 @@ type OnyxValuesMapping = { [ONYXKEYS.ADD_NEW_PERSONAL_CARD]: OnyxTypes.AddNewPersonalCard; [ONYXKEYS.ASSIGN_CARD]: OnyxTypes.AssignCard; [ONYXKEYS.RAM_ONLY_MOBILE_SELECTION_MODE]: boolean; - [ONYXKEYS.RAM_ONLY_HAS_DISMISSED_CONCIERGE_NOTIFICATION_BANNER]: boolean; [ONYXKEYS.DUPLICATE_WORKSPACE]: OnyxTypes.DuplicateWorkspace; [ONYXKEYS.COPY_POLICY_SETTINGS]: OnyxTypes.CopyPolicySettings; [ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL]: string; diff --git a/src/components/Banner.tsx b/src/components/Banner.tsx index ad2ca1595e65..f652653f910f 100644 --- a/src/components/Banner.tsx +++ b/src/components/Banner.tsx @@ -53,9 +53,6 @@ type BannerProps = { /** Callback called when pressing the button */ onButtonPress?: () => void; - - /** Custom action content rendered in the right side of the banner. Overrides the configured `shouldShowButton` when provided. */ - children?: React.ReactNode; }; function Banner({ @@ -67,7 +64,6 @@ function Banner({ onButtonPress, containerStyles, textStyles, - children, shouldRenderHTML = false, shouldShowIcon = false, shouldShowCloseButton = false, @@ -122,15 +118,14 @@ function Banner({ ))} - {children ?? - (shouldShowButton && ( -